2 * Copyright (C) 2014 Filipe David Borba Manana <fdmanana@gmail.com>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #include <linux/hashtable.h>
21 #include "btrfs_inode.h"
23 #include "transaction.h"
25 #include "compression.h"
27 #define BTRFS_PROP_HANDLERS_HT_BITS 8
28 static DEFINE_HASHTABLE(prop_handlers_ht
, BTRFS_PROP_HANDLERS_HT_BITS
);
31 struct hlist_node node
;
32 const char *xattr_name
;
33 int (*validate
)(const char *value
, size_t len
);
34 int (*apply
)(struct inode
*inode
, const char *value
, size_t len
);
35 const char *(*extract
)(struct inode
*inode
);
39 static int prop_compression_validate(const char *value
, size_t len
);
40 static int prop_compression_apply(struct inode
*inode
,
43 static const char *prop_compression_extract(struct inode
*inode
);
45 static struct prop_handler prop_handlers
[] = {
47 .xattr_name
= XATTR_BTRFS_PREFIX
"compression",
48 .validate
= prop_compression_validate
,
49 .apply
= prop_compression_apply
,
50 .extract
= prop_compression_extract
,
55 void __init
btrfs_props_init(void)
59 hash_init(prop_handlers_ht
);
61 for (i
= 0; i
< ARRAY_SIZE(prop_handlers
); i
++) {
62 struct prop_handler
*p
= &prop_handlers
[i
];
63 u64 h
= btrfs_name_hash(p
->xattr_name
, strlen(p
->xattr_name
));
65 hash_add(prop_handlers_ht
, &p
->node
, h
);
69 static const struct hlist_head
*find_prop_handlers_by_hash(const u64 hash
)
73 h
= &prop_handlers_ht
[hash_min(hash
, BTRFS_PROP_HANDLERS_HT_BITS
)];
80 static const struct prop_handler
*
81 find_prop_handler(const char *name
,
82 const struct hlist_head
*handlers
)
84 struct prop_handler
*h
;
87 u64 hash
= btrfs_name_hash(name
, strlen(name
));
89 handlers
= find_prop_handlers_by_hash(hash
);
94 hlist_for_each_entry(h
, handlers
, node
)
95 if (!strcmp(h
->xattr_name
, name
))
101 static int __btrfs_set_prop(struct btrfs_trans_handle
*trans
,
108 const struct prop_handler
*handler
;
111 if (strlen(name
) <= XATTR_BTRFS_PREFIX_LEN
)
114 handler
= find_prop_handler(name
, NULL
);
118 if (value_len
== 0) {
119 ret
= __btrfs_setxattr(trans
, inode
, handler
->xattr_name
,
124 ret
= handler
->apply(inode
, NULL
, 0);
130 ret
= handler
->validate(value
, value_len
);
133 ret
= __btrfs_setxattr(trans
, inode
, handler
->xattr_name
,
134 value
, value_len
, flags
);
137 ret
= handler
->apply(inode
, value
, value_len
);
139 __btrfs_setxattr(trans
, inode
, handler
->xattr_name
,
144 set_bit(BTRFS_INODE_HAS_PROPS
, &BTRFS_I(inode
)->runtime_flags
);
149 int btrfs_set_prop(struct inode
*inode
,
155 return __btrfs_set_prop(NULL
, inode
, name
, value
, value_len
, flags
);
158 static int iterate_object_props(struct btrfs_root
*root
,
159 struct btrfs_path
*path
,
161 void (*iterator
)(void *,
162 const struct prop_handler
*,
167 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
169 char *name_buf
= NULL
;
170 char *value_buf
= NULL
;
171 int name_buf_len
= 0;
172 int value_buf_len
= 0;
175 struct btrfs_key key
;
176 struct btrfs_dir_item
*di
;
177 struct extent_buffer
*leaf
;
178 u32 total_len
, cur
, this_len
;
180 const struct hlist_head
*handlers
;
182 slot
= path
->slots
[0];
183 leaf
= path
->nodes
[0];
185 if (slot
>= btrfs_header_nritems(leaf
)) {
186 ret
= btrfs_next_leaf(root
, path
);
194 btrfs_item_key_to_cpu(leaf
, &key
, slot
);
195 if (key
.objectid
!= objectid
)
197 if (key
.type
!= BTRFS_XATTR_ITEM_KEY
)
200 handlers
= find_prop_handlers_by_hash(key
.offset
);
204 di
= btrfs_item_ptr(leaf
, slot
, struct btrfs_dir_item
);
206 total_len
= btrfs_item_size_nr(leaf
, slot
);
208 while (cur
< total_len
) {
209 u32 name_len
= btrfs_dir_name_len(leaf
, di
);
210 u32 data_len
= btrfs_dir_data_len(leaf
, di
);
211 unsigned long name_ptr
, data_ptr
;
212 const struct prop_handler
*handler
;
214 this_len
= sizeof(*di
) + name_len
+ data_len
;
215 name_ptr
= (unsigned long)(di
+ 1);
216 data_ptr
= name_ptr
+ name_len
;
218 if (verify_dir_item(fs_info
, leaf
,
219 path
->slots
[0], di
)) {
224 if (name_len
<= XATTR_BTRFS_PREFIX_LEN
||
225 memcmp_extent_buffer(leaf
, XATTR_BTRFS_PREFIX
,
227 XATTR_BTRFS_PREFIX_LEN
))
230 if (name_len
>= name_buf_len
) {
232 name_buf_len
= name_len
+ 1;
233 name_buf
= kmalloc(name_buf_len
, GFP_NOFS
);
239 read_extent_buffer(leaf
, name_buf
, name_ptr
, name_len
);
240 name_buf
[name_len
] = '\0';
242 handler
= find_prop_handler(name_buf
, handlers
);
246 if (data_len
> value_buf_len
) {
248 value_buf_len
= data_len
;
249 value_buf
= kmalloc(data_len
, GFP_NOFS
);
255 read_extent_buffer(leaf
, value_buf
, data_ptr
, data_len
);
257 iterator(ctx
, handler
, value_buf
, data_len
);
260 di
= (struct btrfs_dir_item
*)((char *) di
+ this_len
);
269 btrfs_release_path(path
);
276 static void inode_prop_iterator(void *ctx
,
277 const struct prop_handler
*handler
,
281 struct inode
*inode
= ctx
;
282 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
285 ret
= handler
->apply(inode
, value
, len
);
287 btrfs_warn(root
->fs_info
,
288 "error applying prop %s to ino %llu (root %llu): %d",
289 handler
->xattr_name
, btrfs_ino(BTRFS_I(inode
)),
290 root
->root_key
.objectid
, ret
);
292 set_bit(BTRFS_INODE_HAS_PROPS
, &BTRFS_I(inode
)->runtime_flags
);
295 int btrfs_load_inode_props(struct inode
*inode
, struct btrfs_path
*path
)
297 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
298 u64 ino
= btrfs_ino(BTRFS_I(inode
));
301 ret
= iterate_object_props(root
, path
, ino
, inode_prop_iterator
, inode
);
306 static int inherit_props(struct btrfs_trans_handle
*trans
,
308 struct inode
*parent
)
310 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
311 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
315 if (!test_bit(BTRFS_INODE_HAS_PROPS
,
316 &BTRFS_I(parent
)->runtime_flags
))
319 for (i
= 0; i
< ARRAY_SIZE(prop_handlers
); i
++) {
320 const struct prop_handler
*h
= &prop_handlers
[i
];
327 value
= h
->extract(parent
);
331 num_bytes
= btrfs_calc_trans_metadata_size(fs_info
, 1);
332 ret
= btrfs_block_rsv_add(root
, trans
->block_rsv
,
333 num_bytes
, BTRFS_RESERVE_NO_FLUSH
);
336 ret
= __btrfs_set_prop(trans
, inode
, h
->xattr_name
,
337 value
, strlen(value
), 0);
338 btrfs_block_rsv_release(fs_info
, trans
->block_rsv
, num_bytes
);
347 int btrfs_inode_inherit_props(struct btrfs_trans_handle
*trans
,
354 return inherit_props(trans
, inode
, dir
);
357 int btrfs_subvol_inherit_props(struct btrfs_trans_handle
*trans
,
358 struct btrfs_root
*root
,
359 struct btrfs_root
*parent_root
)
361 struct super_block
*sb
= root
->fs_info
->sb
;
362 struct btrfs_key key
;
363 struct inode
*parent_inode
, *child_inode
;
366 key
.objectid
= BTRFS_FIRST_FREE_OBJECTID
;
367 key
.type
= BTRFS_INODE_ITEM_KEY
;
370 parent_inode
= btrfs_iget(sb
, &key
, parent_root
, NULL
);
371 if (IS_ERR(parent_inode
))
372 return PTR_ERR(parent_inode
);
374 child_inode
= btrfs_iget(sb
, &key
, root
, NULL
);
375 if (IS_ERR(child_inode
)) {
377 return PTR_ERR(child_inode
);
380 ret
= inherit_props(trans
, child_inode
, parent_inode
);
387 static int prop_compression_validate(const char *value
, size_t len
)
389 if (!strncmp("lzo", value
, len
))
391 else if (!strncmp("zlib", value
, len
))
393 else if (!strncmp("zstd", value
, len
))
399 static int prop_compression_apply(struct inode
*inode
,
406 BTRFS_I(inode
)->flags
|= BTRFS_INODE_NOCOMPRESS
;
407 BTRFS_I(inode
)->flags
&= ~BTRFS_INODE_COMPRESS
;
408 BTRFS_I(inode
)->prop_compress
= BTRFS_COMPRESS_NONE
;
413 if (!strncmp("lzo", value
, 3))
414 type
= BTRFS_COMPRESS_LZO
;
415 else if (!strncmp("zlib", value
, 4))
416 type
= BTRFS_COMPRESS_ZLIB
;
417 else if (!strncmp("zstd", value
, len
))
418 type
= BTRFS_COMPRESS_ZSTD
;
422 BTRFS_I(inode
)->flags
&= ~BTRFS_INODE_NOCOMPRESS
;
423 BTRFS_I(inode
)->flags
|= BTRFS_INODE_COMPRESS
;
424 BTRFS_I(inode
)->prop_compress
= type
;
429 static const char *prop_compression_extract(struct inode
*inode
)
431 switch (BTRFS_I(inode
)->prop_compress
) {
432 case BTRFS_COMPRESS_ZLIB
:
434 case BTRFS_COMPRESS_LZO
:
436 case BTRFS_COMPRESS_ZSTD
: