1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2014 Filipe David Borba Manana <fdmanana@gmail.com>
6 #include <linux/hashtable.h>
8 #include "btrfs_inode.h"
9 #include "transaction.h"
12 #include "compression.h"
14 #define BTRFS_PROP_HANDLERS_HT_BITS 8
15 static DEFINE_HASHTABLE(prop_handlers_ht
, BTRFS_PROP_HANDLERS_HT_BITS
);
18 struct hlist_node node
;
19 const char *xattr_name
;
20 int (*validate
)(const char *value
, size_t len
);
21 int (*apply
)(struct inode
*inode
, const char *value
, size_t len
);
22 const char *(*extract
)(struct inode
*inode
);
26 static const struct hlist_head
*find_prop_handlers_by_hash(const u64 hash
)
30 h
= &prop_handlers_ht
[hash_min(hash
, BTRFS_PROP_HANDLERS_HT_BITS
)];
37 static const struct prop_handler
*
38 find_prop_handler(const char *name
,
39 const struct hlist_head
*handlers
)
41 struct prop_handler
*h
;
44 u64 hash
= btrfs_name_hash(name
, strlen(name
));
46 handlers
= find_prop_handlers_by_hash(hash
);
51 hlist_for_each_entry(h
, handlers
, node
)
52 if (!strcmp(h
->xattr_name
, name
))
58 int btrfs_validate_prop(const char *name
, const char *value
, size_t value_len
)
60 const struct prop_handler
*handler
;
62 if (strlen(name
) <= XATTR_BTRFS_PREFIX_LEN
)
65 handler
= find_prop_handler(name
, NULL
);
72 return handler
->validate(value
, value_len
);
75 int btrfs_set_prop(struct btrfs_trans_handle
*trans
, struct inode
*inode
,
76 const char *name
, const char *value
, size_t value_len
,
79 const struct prop_handler
*handler
;
82 handler
= find_prop_handler(name
, NULL
);
87 ret
= btrfs_setxattr(trans
, inode
, handler
->xattr_name
,
92 ret
= handler
->apply(inode
, NULL
, 0);
98 ret
= btrfs_setxattr(trans
, inode
, handler
->xattr_name
, value
,
102 ret
= handler
->apply(inode
, value
, value_len
);
104 btrfs_setxattr(trans
, inode
, handler
->xattr_name
, NULL
,
109 set_bit(BTRFS_INODE_HAS_PROPS
, &BTRFS_I(inode
)->runtime_flags
);
114 static int iterate_object_props(struct btrfs_root
*root
,
115 struct btrfs_path
*path
,
117 void (*iterator
)(void *,
118 const struct prop_handler
*,
124 char *name_buf
= NULL
;
125 char *value_buf
= NULL
;
126 int name_buf_len
= 0;
127 int value_buf_len
= 0;
130 struct btrfs_key key
;
131 struct btrfs_dir_item
*di
;
132 struct extent_buffer
*leaf
;
133 u32 total_len
, cur
, this_len
;
135 const struct hlist_head
*handlers
;
137 slot
= path
->slots
[0];
138 leaf
= path
->nodes
[0];
140 if (slot
>= btrfs_header_nritems(leaf
)) {
141 ret
= btrfs_next_leaf(root
, path
);
149 btrfs_item_key_to_cpu(leaf
, &key
, slot
);
150 if (key
.objectid
!= objectid
)
152 if (key
.type
!= BTRFS_XATTR_ITEM_KEY
)
155 handlers
= find_prop_handlers_by_hash(key
.offset
);
159 di
= btrfs_item_ptr(leaf
, slot
, struct btrfs_dir_item
);
161 total_len
= btrfs_item_size_nr(leaf
, slot
);
163 while (cur
< total_len
) {
164 u32 name_len
= btrfs_dir_name_len(leaf
, di
);
165 u32 data_len
= btrfs_dir_data_len(leaf
, di
);
166 unsigned long name_ptr
, data_ptr
;
167 const struct prop_handler
*handler
;
169 this_len
= sizeof(*di
) + name_len
+ data_len
;
170 name_ptr
= (unsigned long)(di
+ 1);
171 data_ptr
= name_ptr
+ name_len
;
173 if (name_len
<= XATTR_BTRFS_PREFIX_LEN
||
174 memcmp_extent_buffer(leaf
, XATTR_BTRFS_PREFIX
,
176 XATTR_BTRFS_PREFIX_LEN
))
179 if (name_len
>= name_buf_len
) {
181 name_buf_len
= name_len
+ 1;
182 name_buf
= kmalloc(name_buf_len
, GFP_NOFS
);
188 read_extent_buffer(leaf
, name_buf
, name_ptr
, name_len
);
189 name_buf
[name_len
] = '\0';
191 handler
= find_prop_handler(name_buf
, handlers
);
195 if (data_len
> value_buf_len
) {
197 value_buf_len
= data_len
;
198 value_buf
= kmalloc(data_len
, GFP_NOFS
);
204 read_extent_buffer(leaf
, value_buf
, data_ptr
, data_len
);
206 iterator(ctx
, handler
, value_buf
, data_len
);
209 di
= (struct btrfs_dir_item
*)((char *) di
+ this_len
);
218 btrfs_release_path(path
);
225 static void inode_prop_iterator(void *ctx
,
226 const struct prop_handler
*handler
,
230 struct inode
*inode
= ctx
;
231 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
234 ret
= handler
->apply(inode
, value
, len
);
236 btrfs_warn(root
->fs_info
,
237 "error applying prop %s to ino %llu (root %llu): %d",
238 handler
->xattr_name
, btrfs_ino(BTRFS_I(inode
)),
239 root
->root_key
.objectid
, ret
);
241 set_bit(BTRFS_INODE_HAS_PROPS
, &BTRFS_I(inode
)->runtime_flags
);
244 int btrfs_load_inode_props(struct inode
*inode
, struct btrfs_path
*path
)
246 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
247 u64 ino
= btrfs_ino(BTRFS_I(inode
));
250 ret
= iterate_object_props(root
, path
, ino
, inode_prop_iterator
, inode
);
255 static int prop_compression_validate(const char *value
, size_t len
)
260 if (btrfs_compress_is_valid_type(value
, len
))
266 static int prop_compression_apply(struct inode
*inode
, const char *value
,
269 struct btrfs_fs_info
*fs_info
= btrfs_sb(inode
->i_sb
);
273 BTRFS_I(inode
)->flags
|= BTRFS_INODE_NOCOMPRESS
;
274 BTRFS_I(inode
)->flags
&= ~BTRFS_INODE_COMPRESS
;
275 BTRFS_I(inode
)->prop_compress
= BTRFS_COMPRESS_NONE
;
280 if (!strncmp("lzo", value
, 3)) {
281 type
= BTRFS_COMPRESS_LZO
;
282 btrfs_set_fs_incompat(fs_info
, COMPRESS_LZO
);
283 } else if (!strncmp("zlib", value
, 4)) {
284 type
= BTRFS_COMPRESS_ZLIB
;
285 } else if (!strncmp("zstd", value
, 4)) {
286 type
= BTRFS_COMPRESS_ZSTD
;
287 btrfs_set_fs_incompat(fs_info
, COMPRESS_ZSTD
);
292 BTRFS_I(inode
)->flags
&= ~BTRFS_INODE_NOCOMPRESS
;
293 BTRFS_I(inode
)->flags
|= BTRFS_INODE_COMPRESS
;
294 BTRFS_I(inode
)->prop_compress
= type
;
299 static const char *prop_compression_extract(struct inode
*inode
)
301 switch (BTRFS_I(inode
)->prop_compress
) {
302 case BTRFS_COMPRESS_ZLIB
:
303 case BTRFS_COMPRESS_LZO
:
304 case BTRFS_COMPRESS_ZSTD
:
305 return btrfs_compress_type2str(BTRFS_I(inode
)->prop_compress
);
313 static struct prop_handler prop_handlers
[] = {
315 .xattr_name
= XATTR_BTRFS_PREFIX
"compression",
316 .validate
= prop_compression_validate
,
317 .apply
= prop_compression_apply
,
318 .extract
= prop_compression_extract
,
323 static int inherit_props(struct btrfs_trans_handle
*trans
,
325 struct inode
*parent
)
327 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
328 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
331 bool need_reserve
= false;
333 if (!test_bit(BTRFS_INODE_HAS_PROPS
,
334 &BTRFS_I(parent
)->runtime_flags
))
337 for (i
= 0; i
< ARRAY_SIZE(prop_handlers
); i
++) {
338 const struct prop_handler
*h
= &prop_handlers
[i
];
345 value
= h
->extract(parent
);
350 * This is not strictly necessary as the property should be
351 * valid, but in case it isn't, don't propagate it futher.
353 ret
= h
->validate(value
, strlen(value
));
358 * Currently callers should be reserving 1 item for properties,
359 * since we only have 1 property that we currently support. If
360 * we add more in the future we need to try and reserve more
361 * space for them. But we should also revisit how we do space
362 * reservations if we do add more properties in the future.
365 num_bytes
= btrfs_calc_insert_metadata_size(fs_info
, 1);
366 ret
= btrfs_block_rsv_add(root
, trans
->block_rsv
,
367 num_bytes
, BTRFS_RESERVE_NO_FLUSH
);
372 ret
= btrfs_setxattr(trans
, inode
, h
->xattr_name
, value
,
375 ret
= h
->apply(inode
, value
, strlen(value
));
377 btrfs_setxattr(trans
, inode
, h
->xattr_name
,
380 set_bit(BTRFS_INODE_HAS_PROPS
,
381 &BTRFS_I(inode
)->runtime_flags
);
385 btrfs_block_rsv_release(fs_info
, trans
->block_rsv
,
396 int btrfs_inode_inherit_props(struct btrfs_trans_handle
*trans
,
403 return inherit_props(trans
, inode
, dir
);
406 int btrfs_subvol_inherit_props(struct btrfs_trans_handle
*trans
,
407 struct btrfs_root
*root
,
408 struct btrfs_root
*parent_root
)
410 struct super_block
*sb
= root
->fs_info
->sb
;
411 struct inode
*parent_inode
, *child_inode
;
414 parent_inode
= btrfs_iget(sb
, BTRFS_FIRST_FREE_OBJECTID
, parent_root
);
415 if (IS_ERR(parent_inode
))
416 return PTR_ERR(parent_inode
);
418 child_inode
= btrfs_iget(sb
, BTRFS_FIRST_FREE_OBJECTID
, root
);
419 if (IS_ERR(child_inode
)) {
421 return PTR_ERR(child_inode
);
424 ret
= inherit_props(trans
, child_inode
, parent_inode
);
431 void __init
btrfs_props_init(void)
435 for (i
= 0; i
< ARRAY_SIZE(prop_handlers
); i
++) {
436 struct prop_handler
*p
= &prop_handlers
[i
];
437 u64 h
= btrfs_name_hash(p
->xattr_name
, strlen(p
->xattr_name
));
439 hash_add(prop_handlers_ht
, &p
->node
, h
);