1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2014 Filipe David Borba Manana <fdmanana@gmail.com>
6 #include <linux/hashtable.h>
7 #include <linux/xattr.h>
10 #include "btrfs_inode.h"
11 #include "transaction.h"
14 #include "compression.h"
15 #include "space-info.h"
17 #include "accessors.h"
21 #define BTRFS_PROP_HANDLERS_HT_BITS 8
22 static DEFINE_HASHTABLE(prop_handlers_ht
, BTRFS_PROP_HANDLERS_HT_BITS
);
25 struct hlist_node node
;
26 const char *xattr_name
;
27 int (*validate
)(const struct btrfs_inode
*inode
, const char *value
,
29 int (*apply
)(struct inode
*inode
, const char *value
, size_t len
);
30 const char *(*extract
)(const struct inode
*inode
);
31 bool (*ignore
)(const struct btrfs_inode
*inode
);
35 static const struct hlist_head
*find_prop_handlers_by_hash(const u64 hash
)
39 h
= &prop_handlers_ht
[hash_min(hash
, BTRFS_PROP_HANDLERS_HT_BITS
)];
46 static const struct prop_handler
*
47 find_prop_handler(const char *name
,
48 const struct hlist_head
*handlers
)
50 struct prop_handler
*h
;
53 u64 hash
= btrfs_name_hash(name
, strlen(name
));
55 handlers
= find_prop_handlers_by_hash(hash
);
60 hlist_for_each_entry(h
, handlers
, node
)
61 if (!strcmp(h
->xattr_name
, name
))
67 int btrfs_validate_prop(const struct btrfs_inode
*inode
, const char *name
,
68 const char *value
, size_t value_len
)
70 const struct prop_handler
*handler
;
72 if (strlen(name
) <= XATTR_BTRFS_PREFIX_LEN
)
75 handler
= find_prop_handler(name
, NULL
);
82 return handler
->validate(inode
, value
, value_len
);
86 * Check if a property should be ignored (not set) for an inode.
88 * @inode: The target inode.
89 * @name: The property's name.
91 * The caller must be sure the given property name is valid, for example by
92 * having previously called btrfs_validate_prop().
94 * Returns: true if the property should be ignored for the given inode
95 * false if the property must not be ignored for the given inode
97 bool btrfs_ignore_prop(const struct btrfs_inode
*inode
, const char *name
)
99 const struct prop_handler
*handler
;
101 handler
= find_prop_handler(name
, NULL
);
102 ASSERT(handler
!= NULL
);
104 return handler
->ignore(inode
);
107 int btrfs_set_prop(struct btrfs_trans_handle
*trans
, struct btrfs_inode
*inode
,
108 const char *name
, const char *value
, size_t value_len
,
111 const struct prop_handler
*handler
;
114 handler
= find_prop_handler(name
, NULL
);
118 if (value_len
== 0) {
119 ret
= btrfs_setxattr(trans
, &inode
->vfs_inode
, handler
->xattr_name
,
124 ret
= handler
->apply(&inode
->vfs_inode
, NULL
, 0);
130 ret
= btrfs_setxattr(trans
, &inode
->vfs_inode
, handler
->xattr_name
, value
,
134 ret
= handler
->apply(&inode
->vfs_inode
, value
, value_len
);
136 btrfs_setxattr(trans
, &inode
->vfs_inode
, handler
->xattr_name
, NULL
,
141 set_bit(BTRFS_INODE_HAS_PROPS
, &inode
->runtime_flags
);
146 static int iterate_object_props(struct btrfs_root
*root
,
147 struct btrfs_path
*path
,
149 void (*iterator
)(void *,
150 const struct prop_handler
*,
156 char *name_buf
= NULL
;
157 char *value_buf
= NULL
;
158 int name_buf_len
= 0;
159 int value_buf_len
= 0;
162 struct btrfs_key key
;
163 struct btrfs_dir_item
*di
;
164 struct extent_buffer
*leaf
;
165 u32 total_len
, cur
, this_len
;
167 const struct hlist_head
*handlers
;
169 slot
= path
->slots
[0];
170 leaf
= path
->nodes
[0];
172 if (slot
>= btrfs_header_nritems(leaf
)) {
173 ret
= btrfs_next_leaf(root
, path
);
181 btrfs_item_key_to_cpu(leaf
, &key
, slot
);
182 if (key
.objectid
!= objectid
)
184 if (key
.type
!= BTRFS_XATTR_ITEM_KEY
)
187 handlers
= find_prop_handlers_by_hash(key
.offset
);
191 di
= btrfs_item_ptr(leaf
, slot
, struct btrfs_dir_item
);
193 total_len
= btrfs_item_size(leaf
, slot
);
195 while (cur
< total_len
) {
196 u32 name_len
= btrfs_dir_name_len(leaf
, di
);
197 u32 data_len
= btrfs_dir_data_len(leaf
, di
);
198 unsigned long name_ptr
, data_ptr
;
199 const struct prop_handler
*handler
;
201 this_len
= sizeof(*di
) + name_len
+ data_len
;
202 name_ptr
= (unsigned long)(di
+ 1);
203 data_ptr
= name_ptr
+ name_len
;
205 if (name_len
<= XATTR_BTRFS_PREFIX_LEN
||
206 memcmp_extent_buffer(leaf
, XATTR_BTRFS_PREFIX
,
208 XATTR_BTRFS_PREFIX_LEN
))
211 if (name_len
>= name_buf_len
) {
213 name_buf_len
= name_len
+ 1;
214 name_buf
= kmalloc(name_buf_len
, GFP_NOFS
);
220 read_extent_buffer(leaf
, name_buf
, name_ptr
, name_len
);
221 name_buf
[name_len
] = '\0';
223 handler
= find_prop_handler(name_buf
, handlers
);
227 if (data_len
> value_buf_len
) {
229 value_buf_len
= data_len
;
230 value_buf
= kmalloc(data_len
, GFP_NOFS
);
236 read_extent_buffer(leaf
, value_buf
, data_ptr
, data_len
);
238 iterator(ctx
, handler
, value_buf
, data_len
);
241 di
= (struct btrfs_dir_item
*)((char *) di
+ this_len
);
250 btrfs_release_path(path
);
257 static void inode_prop_iterator(void *ctx
,
258 const struct prop_handler
*handler
,
262 struct inode
*inode
= ctx
;
263 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
266 ret
= handler
->apply(inode
, value
, len
);
268 btrfs_warn(root
->fs_info
,
269 "error applying prop %s to ino %llu (root %llu): %d",
270 handler
->xattr_name
, btrfs_ino(BTRFS_I(inode
)),
271 btrfs_root_id(root
), ret
);
273 set_bit(BTRFS_INODE_HAS_PROPS
, &BTRFS_I(inode
)->runtime_flags
);
276 int btrfs_load_inode_props(struct inode
*inode
, struct btrfs_path
*path
)
278 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
279 u64 ino
= btrfs_ino(BTRFS_I(inode
));
281 return iterate_object_props(root
, path
, ino
, inode_prop_iterator
, inode
);
284 static int prop_compression_validate(const struct btrfs_inode
*inode
,
285 const char *value
, size_t len
)
287 if (!btrfs_inode_can_compress(inode
))
293 if (btrfs_compress_is_valid_type(value
, len
))
296 if ((len
== 2 && strncmp("no", value
, 2) == 0) ||
297 (len
== 4 && strncmp("none", value
, 4) == 0))
303 static int prop_compression_apply(struct inode
*inode
, const char *value
,
306 struct btrfs_fs_info
*fs_info
= inode_to_fs_info(inode
);
309 /* Reset to defaults */
311 BTRFS_I(inode
)->flags
&= ~BTRFS_INODE_COMPRESS
;
312 BTRFS_I(inode
)->flags
&= ~BTRFS_INODE_NOCOMPRESS
;
313 BTRFS_I(inode
)->prop_compress
= BTRFS_COMPRESS_NONE
;
317 /* Set NOCOMPRESS flag */
318 if ((len
== 2 && strncmp("no", value
, 2) == 0) ||
319 (len
== 4 && strncmp("none", value
, 4) == 0)) {
320 BTRFS_I(inode
)->flags
|= BTRFS_INODE_NOCOMPRESS
;
321 BTRFS_I(inode
)->flags
&= ~BTRFS_INODE_COMPRESS
;
322 BTRFS_I(inode
)->prop_compress
= BTRFS_COMPRESS_NONE
;
327 if (!strncmp("lzo", value
, 3)) {
328 type
= BTRFS_COMPRESS_LZO
;
329 btrfs_set_fs_incompat(fs_info
, COMPRESS_LZO
);
330 } else if (!strncmp("zlib", value
, 4)) {
331 type
= BTRFS_COMPRESS_ZLIB
;
332 } else if (!strncmp("zstd", value
, 4)) {
333 type
= BTRFS_COMPRESS_ZSTD
;
334 btrfs_set_fs_incompat(fs_info
, COMPRESS_ZSTD
);
339 BTRFS_I(inode
)->flags
&= ~BTRFS_INODE_NOCOMPRESS
;
340 BTRFS_I(inode
)->flags
|= BTRFS_INODE_COMPRESS
;
341 BTRFS_I(inode
)->prop_compress
= type
;
346 static bool prop_compression_ignore(const struct btrfs_inode
*inode
)
349 * Compression only has effect for regular files, and for directories
350 * we set it just to propagate it to new files created inside them.
351 * Everything else (symlinks, devices, sockets, fifos) is pointless as
352 * it will do nothing, so don't waste metadata space on a compression
353 * xattr for anything that is neither a file nor a directory.
355 if (!S_ISREG(inode
->vfs_inode
.i_mode
) &&
356 !S_ISDIR(inode
->vfs_inode
.i_mode
))
362 static const char *prop_compression_extract(const struct inode
*inode
)
364 switch (BTRFS_I(inode
)->prop_compress
) {
365 case BTRFS_COMPRESS_ZLIB
:
366 case BTRFS_COMPRESS_LZO
:
367 case BTRFS_COMPRESS_ZSTD
:
368 return btrfs_compress_type2str(BTRFS_I(inode
)->prop_compress
);
376 static struct prop_handler prop_handlers
[] = {
378 .xattr_name
= XATTR_BTRFS_PREFIX
"compression",
379 .validate
= prop_compression_validate
,
380 .apply
= prop_compression_apply
,
381 .extract
= prop_compression_extract
,
382 .ignore
= prop_compression_ignore
,
387 int btrfs_inode_inherit_props(struct btrfs_trans_handle
*trans
,
388 struct inode
*inode
, const struct inode
*parent
)
390 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
391 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
394 bool need_reserve
= false;
396 if (!test_bit(BTRFS_INODE_HAS_PROPS
,
397 &BTRFS_I(parent
)->runtime_flags
))
400 for (i
= 0; i
< ARRAY_SIZE(prop_handlers
); i
++) {
401 const struct prop_handler
*h
= &prop_handlers
[i
];
408 if (h
->ignore(BTRFS_I(inode
)))
411 value
= h
->extract(parent
);
416 * This is not strictly necessary as the property should be
417 * valid, but in case it isn't, don't propagate it further.
419 ret
= h
->validate(BTRFS_I(inode
), value
, strlen(value
));
424 * Currently callers should be reserving 1 item for properties,
425 * since we only have 1 property that we currently support. If
426 * we add more in the future we need to try and reserve more
427 * space for them. But we should also revisit how we do space
428 * reservations if we do add more properties in the future.
431 num_bytes
= btrfs_calc_insert_metadata_size(fs_info
, 1);
432 ret
= btrfs_block_rsv_add(fs_info
, trans
->block_rsv
,
434 BTRFS_RESERVE_NO_FLUSH
);
439 ret
= btrfs_setxattr(trans
, inode
, h
->xattr_name
, value
,
442 ret
= h
->apply(inode
, value
, strlen(value
));
444 btrfs_setxattr(trans
, inode
, h
->xattr_name
,
447 set_bit(BTRFS_INODE_HAS_PROPS
,
448 &BTRFS_I(inode
)->runtime_flags
);
452 btrfs_block_rsv_release(fs_info
, trans
->block_rsv
,
463 int __init
btrfs_props_init(void)
467 for (i
= 0; i
< ARRAY_SIZE(prop_handlers
); i
++) {
468 struct prop_handler
*p
= &prop_handlers
[i
];
469 u64 h
= btrfs_name_hash(p
->xattr_name
, strlen(p
->xattr_name
));
471 hash_add(prop_handlers_ht
, &p
->node
, h
);