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"
26 #define BTRFS_PROP_HANDLERS_HT_BITS 8
27 static DEFINE_HASHTABLE(prop_handlers_ht
, BTRFS_PROP_HANDLERS_HT_BITS
);
30 struct hlist_node node
;
31 const char *xattr_name
;
32 int (*validate
)(const char *value
, size_t len
);
33 int (*apply
)(struct inode
*inode
, const char *value
, size_t len
);
34 const char *(*extract
)(struct inode
*inode
);
38 static int prop_compression_validate(const char *value
, size_t len
);
39 static int prop_compression_apply(struct inode
*inode
,
42 static const char *prop_compression_extract(struct inode
*inode
);
44 static struct prop_handler prop_handlers
[] = {
46 .xattr_name
= XATTR_BTRFS_PREFIX
"compression",
47 .validate
= prop_compression_validate
,
48 .apply
= prop_compression_apply
,
49 .extract
= prop_compression_extract
,
54 void __init
btrfs_props_init(void)
58 hash_init(prop_handlers_ht
);
60 for (i
= 0; i
< ARRAY_SIZE(prop_handlers
); i
++) {
61 struct prop_handler
*p
= &prop_handlers
[i
];
62 u64 h
= btrfs_name_hash(p
->xattr_name
, strlen(p
->xattr_name
));
64 hash_add(prop_handlers_ht
, &p
->node
, h
);
68 static const struct hlist_head
*find_prop_handlers_by_hash(const u64 hash
)
72 h
= &prop_handlers_ht
[hash_min(hash
, BTRFS_PROP_HANDLERS_HT_BITS
)];
79 static const struct prop_handler
*
80 find_prop_handler(const char *name
,
81 const struct hlist_head
*handlers
)
83 struct prop_handler
*h
;
86 u64 hash
= btrfs_name_hash(name
, strlen(name
));
88 handlers
= find_prop_handlers_by_hash(hash
);
93 hlist_for_each_entry(h
, handlers
, node
)
94 if (!strcmp(h
->xattr_name
, name
))
100 static int __btrfs_set_prop(struct btrfs_trans_handle
*trans
,
107 const struct prop_handler
*handler
;
110 if (strlen(name
) <= XATTR_BTRFS_PREFIX_LEN
)
113 handler
= find_prop_handler(name
, NULL
);
117 if (value_len
== 0) {
118 ret
= __btrfs_setxattr(trans
, inode
, handler
->xattr_name
,
123 ret
= handler
->apply(inode
, NULL
, 0);
129 ret
= handler
->validate(value
, value_len
);
132 ret
= __btrfs_setxattr(trans
, inode
, handler
->xattr_name
,
133 value
, value_len
, flags
);
136 ret
= handler
->apply(inode
, value
, value_len
);
138 __btrfs_setxattr(trans
, inode
, handler
->xattr_name
,
143 set_bit(BTRFS_INODE_HAS_PROPS
, &BTRFS_I(inode
)->runtime_flags
);
148 int btrfs_set_prop(struct inode
*inode
,
154 return __btrfs_set_prop(NULL
, inode
, name
, value
, value_len
, flags
);
157 static int iterate_object_props(struct btrfs_root
*root
,
158 struct btrfs_path
*path
,
160 void (*iterator
)(void *,
161 const struct prop_handler
*,
167 char *name_buf
= NULL
;
168 char *value_buf
= NULL
;
169 int name_buf_len
= 0;
170 int value_buf_len
= 0;
173 struct btrfs_key key
;
174 struct btrfs_dir_item
*di
;
175 struct extent_buffer
*leaf
;
176 u32 total_len
, cur
, this_len
;
178 const struct hlist_head
*handlers
;
180 slot
= path
->slots
[0];
181 leaf
= path
->nodes
[0];
183 if (slot
>= btrfs_header_nritems(leaf
)) {
184 ret
= btrfs_next_leaf(root
, path
);
192 btrfs_item_key_to_cpu(leaf
, &key
, slot
);
193 if (key
.objectid
!= objectid
)
195 if (key
.type
!= BTRFS_XATTR_ITEM_KEY
)
198 handlers
= find_prop_handlers_by_hash(key
.offset
);
202 di
= btrfs_item_ptr(leaf
, slot
, struct btrfs_dir_item
);
204 total_len
= btrfs_item_size_nr(leaf
, slot
);
206 while (cur
< total_len
) {
207 u32 name_len
= btrfs_dir_name_len(leaf
, di
);
208 u32 data_len
= btrfs_dir_data_len(leaf
, di
);
209 unsigned long name_ptr
, data_ptr
;
210 const struct prop_handler
*handler
;
212 this_len
= sizeof(*di
) + name_len
+ data_len
;
213 name_ptr
= (unsigned long)(di
+ 1);
214 data_ptr
= name_ptr
+ name_len
;
216 if (name_len
<= XATTR_BTRFS_PREFIX_LEN
||
217 memcmp_extent_buffer(leaf
, XATTR_BTRFS_PREFIX
,
219 XATTR_BTRFS_PREFIX_LEN
))
222 if (name_len
>= name_buf_len
) {
224 name_buf_len
= name_len
+ 1;
225 name_buf
= kmalloc(name_buf_len
, GFP_NOFS
);
231 read_extent_buffer(leaf
, name_buf
, name_ptr
, name_len
);
232 name_buf
[name_len
] = '\0';
234 handler
= find_prop_handler(name_buf
, handlers
);
238 if (data_len
> value_buf_len
) {
240 value_buf_len
= data_len
;
241 value_buf
= kmalloc(data_len
, GFP_NOFS
);
247 read_extent_buffer(leaf
, value_buf
, data_ptr
, data_len
);
249 iterator(ctx
, handler
, value_buf
, data_len
);
252 di
= (struct btrfs_dir_item
*)((char *) di
+ this_len
);
261 btrfs_release_path(path
);
268 static void inode_prop_iterator(void *ctx
,
269 const struct prop_handler
*handler
,
273 struct inode
*inode
= ctx
;
274 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
277 ret
= handler
->apply(inode
, value
, len
);
279 btrfs_warn(root
->fs_info
,
280 "error applying prop %s to ino %llu (root %llu): %d",
281 handler
->xattr_name
, btrfs_ino(inode
),
282 root
->root_key
.objectid
, ret
);
284 set_bit(BTRFS_INODE_HAS_PROPS
, &BTRFS_I(inode
)->runtime_flags
);
287 int btrfs_load_inode_props(struct inode
*inode
, struct btrfs_path
*path
)
289 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
290 u64 ino
= btrfs_ino(inode
);
293 ret
= iterate_object_props(root
, path
, ino
, inode_prop_iterator
, inode
);
298 static int inherit_props(struct btrfs_trans_handle
*trans
,
300 struct inode
*parent
)
302 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
306 if (!test_bit(BTRFS_INODE_HAS_PROPS
,
307 &BTRFS_I(parent
)->runtime_flags
))
310 for (i
= 0; i
< ARRAY_SIZE(prop_handlers
); i
++) {
311 const struct prop_handler
*h
= &prop_handlers
[i
];
318 value
= h
->extract(parent
);
322 num_bytes
= btrfs_calc_trans_metadata_size(root
, 1);
323 ret
= btrfs_block_rsv_add(root
, trans
->block_rsv
,
324 num_bytes
, BTRFS_RESERVE_NO_FLUSH
);
327 ret
= __btrfs_set_prop(trans
, inode
, h
->xattr_name
,
328 value
, strlen(value
), 0);
329 btrfs_block_rsv_release(root
, trans
->block_rsv
, num_bytes
);
338 int btrfs_inode_inherit_props(struct btrfs_trans_handle
*trans
,
345 return inherit_props(trans
, inode
, dir
);
348 int btrfs_subvol_inherit_props(struct btrfs_trans_handle
*trans
,
349 struct btrfs_root
*root
,
350 struct btrfs_root
*parent_root
)
352 struct btrfs_key key
;
353 struct inode
*parent_inode
, *child_inode
;
356 key
.objectid
= BTRFS_FIRST_FREE_OBJECTID
;
357 key
.type
= BTRFS_INODE_ITEM_KEY
;
360 parent_inode
= btrfs_iget(parent_root
->fs_info
->sb
, &key
,
362 if (IS_ERR(parent_inode
))
363 return PTR_ERR(parent_inode
);
365 child_inode
= btrfs_iget(root
->fs_info
->sb
, &key
, root
, NULL
);
366 if (IS_ERR(child_inode
)) {
368 return PTR_ERR(child_inode
);
371 ret
= inherit_props(trans
, child_inode
, parent_inode
);
378 static int prop_compression_validate(const char *value
, size_t len
)
380 if (!strncmp("lzo", value
, len
))
382 else if (!strncmp("zlib", value
, len
))
388 static int prop_compression_apply(struct inode
*inode
,
395 BTRFS_I(inode
)->flags
|= BTRFS_INODE_NOCOMPRESS
;
396 BTRFS_I(inode
)->flags
&= ~BTRFS_INODE_COMPRESS
;
397 BTRFS_I(inode
)->force_compress
= BTRFS_COMPRESS_NONE
;
402 if (!strncmp("lzo", value
, len
))
403 type
= BTRFS_COMPRESS_LZO
;
404 else if (!strncmp("zlib", value
, len
))
405 type
= BTRFS_COMPRESS_ZLIB
;
409 BTRFS_I(inode
)->flags
&= ~BTRFS_INODE_NOCOMPRESS
;
410 BTRFS_I(inode
)->flags
|= BTRFS_INODE_COMPRESS
;
411 BTRFS_I(inode
)->force_compress
= type
;
416 static const char *prop_compression_extract(struct inode
*inode
)
418 switch (BTRFS_I(inode
)->force_compress
) {
419 case BTRFS_COMPRESS_ZLIB
:
421 case BTRFS_COMPRESS_LZO
: