1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2014 Filipe David Borba Manana <fdmanana@gmail.com>
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/hashtable.h>
7*4882a593Smuzhiyun #include "props.h"
8*4882a593Smuzhiyun #include "btrfs_inode.h"
9*4882a593Smuzhiyun #include "transaction.h"
10*4882a593Smuzhiyun #include "ctree.h"
11*4882a593Smuzhiyun #include "xattr.h"
12*4882a593Smuzhiyun #include "compression.h"
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #define BTRFS_PROP_HANDLERS_HT_BITS 8
15*4882a593Smuzhiyun static DEFINE_HASHTABLE(prop_handlers_ht, BTRFS_PROP_HANDLERS_HT_BITS);
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun struct prop_handler {
18*4882a593Smuzhiyun struct hlist_node node;
19*4882a593Smuzhiyun const char *xattr_name;
20*4882a593Smuzhiyun int (*validate)(const char *value, size_t len);
21*4882a593Smuzhiyun int (*apply)(struct inode *inode, const char *value, size_t len);
22*4882a593Smuzhiyun const char *(*extract)(struct inode *inode);
23*4882a593Smuzhiyun int inheritable;
24*4882a593Smuzhiyun };
25*4882a593Smuzhiyun
find_prop_handlers_by_hash(const u64 hash)26*4882a593Smuzhiyun static const struct hlist_head *find_prop_handlers_by_hash(const u64 hash)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun struct hlist_head *h;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun h = &prop_handlers_ht[hash_min(hash, BTRFS_PROP_HANDLERS_HT_BITS)];
31*4882a593Smuzhiyun if (hlist_empty(h))
32*4882a593Smuzhiyun return NULL;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun return h;
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun static const struct prop_handler *
find_prop_handler(const char * name,const struct hlist_head * handlers)38*4882a593Smuzhiyun find_prop_handler(const char *name,
39*4882a593Smuzhiyun const struct hlist_head *handlers)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun struct prop_handler *h;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun if (!handlers) {
44*4882a593Smuzhiyun u64 hash = btrfs_name_hash(name, strlen(name));
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun handlers = find_prop_handlers_by_hash(hash);
47*4882a593Smuzhiyun if (!handlers)
48*4882a593Smuzhiyun return NULL;
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun hlist_for_each_entry(h, handlers, node)
52*4882a593Smuzhiyun if (!strcmp(h->xattr_name, name))
53*4882a593Smuzhiyun return h;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun return NULL;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
btrfs_validate_prop(const char * name,const char * value,size_t value_len)58*4882a593Smuzhiyun int btrfs_validate_prop(const char *name, const char *value, size_t value_len)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun const struct prop_handler *handler;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun if (strlen(name) <= XATTR_BTRFS_PREFIX_LEN)
63*4882a593Smuzhiyun return -EINVAL;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun handler = find_prop_handler(name, NULL);
66*4882a593Smuzhiyun if (!handler)
67*4882a593Smuzhiyun return -EINVAL;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun if (value_len == 0)
70*4882a593Smuzhiyun return 0;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun return handler->validate(value, value_len);
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
btrfs_set_prop(struct btrfs_trans_handle * trans,struct inode * inode,const char * name,const char * value,size_t value_len,int flags)75*4882a593Smuzhiyun int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
76*4882a593Smuzhiyun const char *name, const char *value, size_t value_len,
77*4882a593Smuzhiyun int flags)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun const struct prop_handler *handler;
80*4882a593Smuzhiyun int ret;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun handler = find_prop_handler(name, NULL);
83*4882a593Smuzhiyun if (!handler)
84*4882a593Smuzhiyun return -EINVAL;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun if (value_len == 0) {
87*4882a593Smuzhiyun ret = btrfs_setxattr(trans, inode, handler->xattr_name,
88*4882a593Smuzhiyun NULL, 0, flags);
89*4882a593Smuzhiyun if (ret)
90*4882a593Smuzhiyun return ret;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun ret = handler->apply(inode, NULL, 0);
93*4882a593Smuzhiyun ASSERT(ret == 0);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun return ret;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun ret = btrfs_setxattr(trans, inode, handler->xattr_name, value,
99*4882a593Smuzhiyun value_len, flags);
100*4882a593Smuzhiyun if (ret)
101*4882a593Smuzhiyun return ret;
102*4882a593Smuzhiyun ret = handler->apply(inode, value, value_len);
103*4882a593Smuzhiyun if (ret) {
104*4882a593Smuzhiyun btrfs_setxattr(trans, inode, handler->xattr_name, NULL,
105*4882a593Smuzhiyun 0, flags);
106*4882a593Smuzhiyun return ret;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun set_bit(BTRFS_INODE_HAS_PROPS, &BTRFS_I(inode)->runtime_flags);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun return 0;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
iterate_object_props(struct btrfs_root * root,struct btrfs_path * path,u64 objectid,void (* iterator)(void *,const struct prop_handler *,const char *,size_t),void * ctx)114*4882a593Smuzhiyun static int iterate_object_props(struct btrfs_root *root,
115*4882a593Smuzhiyun struct btrfs_path *path,
116*4882a593Smuzhiyun u64 objectid,
117*4882a593Smuzhiyun void (*iterator)(void *,
118*4882a593Smuzhiyun const struct prop_handler *,
119*4882a593Smuzhiyun const char *,
120*4882a593Smuzhiyun size_t),
121*4882a593Smuzhiyun void *ctx)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun int ret;
124*4882a593Smuzhiyun char *name_buf = NULL;
125*4882a593Smuzhiyun char *value_buf = NULL;
126*4882a593Smuzhiyun int name_buf_len = 0;
127*4882a593Smuzhiyun int value_buf_len = 0;
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun while (1) {
130*4882a593Smuzhiyun struct btrfs_key key;
131*4882a593Smuzhiyun struct btrfs_dir_item *di;
132*4882a593Smuzhiyun struct extent_buffer *leaf;
133*4882a593Smuzhiyun u32 total_len, cur, this_len;
134*4882a593Smuzhiyun int slot;
135*4882a593Smuzhiyun const struct hlist_head *handlers;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun slot = path->slots[0];
138*4882a593Smuzhiyun leaf = path->nodes[0];
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (slot >= btrfs_header_nritems(leaf)) {
141*4882a593Smuzhiyun ret = btrfs_next_leaf(root, path);
142*4882a593Smuzhiyun if (ret < 0)
143*4882a593Smuzhiyun goto out;
144*4882a593Smuzhiyun else if (ret > 0)
145*4882a593Smuzhiyun break;
146*4882a593Smuzhiyun continue;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun btrfs_item_key_to_cpu(leaf, &key, slot);
150*4882a593Smuzhiyun if (key.objectid != objectid)
151*4882a593Smuzhiyun break;
152*4882a593Smuzhiyun if (key.type != BTRFS_XATTR_ITEM_KEY)
153*4882a593Smuzhiyun break;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun handlers = find_prop_handlers_by_hash(key.offset);
156*4882a593Smuzhiyun if (!handlers)
157*4882a593Smuzhiyun goto next_slot;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
160*4882a593Smuzhiyun cur = 0;
161*4882a593Smuzhiyun total_len = btrfs_item_size_nr(leaf, slot);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun while (cur < total_len) {
164*4882a593Smuzhiyun u32 name_len = btrfs_dir_name_len(leaf, di);
165*4882a593Smuzhiyun u32 data_len = btrfs_dir_data_len(leaf, di);
166*4882a593Smuzhiyun unsigned long name_ptr, data_ptr;
167*4882a593Smuzhiyun const struct prop_handler *handler;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun this_len = sizeof(*di) + name_len + data_len;
170*4882a593Smuzhiyun name_ptr = (unsigned long)(di + 1);
171*4882a593Smuzhiyun data_ptr = name_ptr + name_len;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun if (name_len <= XATTR_BTRFS_PREFIX_LEN ||
174*4882a593Smuzhiyun memcmp_extent_buffer(leaf, XATTR_BTRFS_PREFIX,
175*4882a593Smuzhiyun name_ptr,
176*4882a593Smuzhiyun XATTR_BTRFS_PREFIX_LEN))
177*4882a593Smuzhiyun goto next_dir_item;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun if (name_len >= name_buf_len) {
180*4882a593Smuzhiyun kfree(name_buf);
181*4882a593Smuzhiyun name_buf_len = name_len + 1;
182*4882a593Smuzhiyun name_buf = kmalloc(name_buf_len, GFP_NOFS);
183*4882a593Smuzhiyun if (!name_buf) {
184*4882a593Smuzhiyun ret = -ENOMEM;
185*4882a593Smuzhiyun goto out;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun read_extent_buffer(leaf, name_buf, name_ptr, name_len);
189*4882a593Smuzhiyun name_buf[name_len] = '\0';
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun handler = find_prop_handler(name_buf, handlers);
192*4882a593Smuzhiyun if (!handler)
193*4882a593Smuzhiyun goto next_dir_item;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun if (data_len > value_buf_len) {
196*4882a593Smuzhiyun kfree(value_buf);
197*4882a593Smuzhiyun value_buf_len = data_len;
198*4882a593Smuzhiyun value_buf = kmalloc(data_len, GFP_NOFS);
199*4882a593Smuzhiyun if (!value_buf) {
200*4882a593Smuzhiyun ret = -ENOMEM;
201*4882a593Smuzhiyun goto out;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun read_extent_buffer(leaf, value_buf, data_ptr, data_len);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun iterator(ctx, handler, value_buf, data_len);
207*4882a593Smuzhiyun next_dir_item:
208*4882a593Smuzhiyun cur += this_len;
209*4882a593Smuzhiyun di = (struct btrfs_dir_item *)((char *) di + this_len);
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun next_slot:
213*4882a593Smuzhiyun path->slots[0]++;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun ret = 0;
217*4882a593Smuzhiyun out:
218*4882a593Smuzhiyun btrfs_release_path(path);
219*4882a593Smuzhiyun kfree(name_buf);
220*4882a593Smuzhiyun kfree(value_buf);
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun return ret;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
inode_prop_iterator(void * ctx,const struct prop_handler * handler,const char * value,size_t len)225*4882a593Smuzhiyun static void inode_prop_iterator(void *ctx,
226*4882a593Smuzhiyun const struct prop_handler *handler,
227*4882a593Smuzhiyun const char *value,
228*4882a593Smuzhiyun size_t len)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun struct inode *inode = ctx;
231*4882a593Smuzhiyun struct btrfs_root *root = BTRFS_I(inode)->root;
232*4882a593Smuzhiyun int ret;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun ret = handler->apply(inode, value, len);
235*4882a593Smuzhiyun if (unlikely(ret))
236*4882a593Smuzhiyun btrfs_warn(root->fs_info,
237*4882a593Smuzhiyun "error applying prop %s to ino %llu (root %llu): %d",
238*4882a593Smuzhiyun handler->xattr_name, btrfs_ino(BTRFS_I(inode)),
239*4882a593Smuzhiyun root->root_key.objectid, ret);
240*4882a593Smuzhiyun else
241*4882a593Smuzhiyun set_bit(BTRFS_INODE_HAS_PROPS, &BTRFS_I(inode)->runtime_flags);
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
btrfs_load_inode_props(struct inode * inode,struct btrfs_path * path)244*4882a593Smuzhiyun int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun struct btrfs_root *root = BTRFS_I(inode)->root;
247*4882a593Smuzhiyun u64 ino = btrfs_ino(BTRFS_I(inode));
248*4882a593Smuzhiyun int ret;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun ret = iterate_object_props(root, path, ino, inode_prop_iterator, inode);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun return ret;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
prop_compression_validate(const char * value,size_t len)255*4882a593Smuzhiyun static int prop_compression_validate(const char *value, size_t len)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun if (!value)
258*4882a593Smuzhiyun return 0;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun if (btrfs_compress_is_valid_type(value, len))
261*4882a593Smuzhiyun return 0;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun return -EINVAL;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
prop_compression_apply(struct inode * inode,const char * value,size_t len)266*4882a593Smuzhiyun static int prop_compression_apply(struct inode *inode, const char *value,
267*4882a593Smuzhiyun size_t len)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
270*4882a593Smuzhiyun int type;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun if (len == 0) {
273*4882a593Smuzhiyun BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
274*4882a593Smuzhiyun BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS;
275*4882a593Smuzhiyun BTRFS_I(inode)->prop_compress = BTRFS_COMPRESS_NONE;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun return 0;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun if (!strncmp("lzo", value, 3)) {
281*4882a593Smuzhiyun type = BTRFS_COMPRESS_LZO;
282*4882a593Smuzhiyun btrfs_set_fs_incompat(fs_info, COMPRESS_LZO);
283*4882a593Smuzhiyun } else if (!strncmp("zlib", value, 4)) {
284*4882a593Smuzhiyun type = BTRFS_COMPRESS_ZLIB;
285*4882a593Smuzhiyun } else if (!strncmp("zstd", value, 4)) {
286*4882a593Smuzhiyun type = BTRFS_COMPRESS_ZSTD;
287*4882a593Smuzhiyun btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD);
288*4882a593Smuzhiyun } else {
289*4882a593Smuzhiyun return -EINVAL;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS;
293*4882a593Smuzhiyun BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS;
294*4882a593Smuzhiyun BTRFS_I(inode)->prop_compress = type;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun return 0;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
prop_compression_extract(struct inode * inode)299*4882a593Smuzhiyun static const char *prop_compression_extract(struct inode *inode)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun switch (BTRFS_I(inode)->prop_compress) {
302*4882a593Smuzhiyun case BTRFS_COMPRESS_ZLIB:
303*4882a593Smuzhiyun case BTRFS_COMPRESS_LZO:
304*4882a593Smuzhiyun case BTRFS_COMPRESS_ZSTD:
305*4882a593Smuzhiyun return btrfs_compress_type2str(BTRFS_I(inode)->prop_compress);
306*4882a593Smuzhiyun default:
307*4882a593Smuzhiyun break;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun return NULL;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun static struct prop_handler prop_handlers[] = {
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun .xattr_name = XATTR_BTRFS_PREFIX "compression",
316*4882a593Smuzhiyun .validate = prop_compression_validate,
317*4882a593Smuzhiyun .apply = prop_compression_apply,
318*4882a593Smuzhiyun .extract = prop_compression_extract,
319*4882a593Smuzhiyun .inheritable = 1
320*4882a593Smuzhiyun },
321*4882a593Smuzhiyun };
322*4882a593Smuzhiyun
inherit_props(struct btrfs_trans_handle * trans,struct inode * inode,struct inode * parent)323*4882a593Smuzhiyun static int inherit_props(struct btrfs_trans_handle *trans,
324*4882a593Smuzhiyun struct inode *inode,
325*4882a593Smuzhiyun struct inode *parent)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun struct btrfs_root *root = BTRFS_I(inode)->root;
328*4882a593Smuzhiyun struct btrfs_fs_info *fs_info = root->fs_info;
329*4882a593Smuzhiyun int ret;
330*4882a593Smuzhiyun int i;
331*4882a593Smuzhiyun bool need_reserve = false;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun if (!test_bit(BTRFS_INODE_HAS_PROPS,
334*4882a593Smuzhiyun &BTRFS_I(parent)->runtime_flags))
335*4882a593Smuzhiyun return 0;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(prop_handlers); i++) {
338*4882a593Smuzhiyun const struct prop_handler *h = &prop_handlers[i];
339*4882a593Smuzhiyun const char *value;
340*4882a593Smuzhiyun u64 num_bytes = 0;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun if (!h->inheritable)
343*4882a593Smuzhiyun continue;
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun value = h->extract(parent);
346*4882a593Smuzhiyun if (!value)
347*4882a593Smuzhiyun continue;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun /*
350*4882a593Smuzhiyun * This is not strictly necessary as the property should be
351*4882a593Smuzhiyun * valid, but in case it isn't, don't propagate it futher.
352*4882a593Smuzhiyun */
353*4882a593Smuzhiyun ret = h->validate(value, strlen(value));
354*4882a593Smuzhiyun if (ret)
355*4882a593Smuzhiyun continue;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun /*
358*4882a593Smuzhiyun * Currently callers should be reserving 1 item for properties,
359*4882a593Smuzhiyun * since we only have 1 property that we currently support. If
360*4882a593Smuzhiyun * we add more in the future we need to try and reserve more
361*4882a593Smuzhiyun * space for them. But we should also revisit how we do space
362*4882a593Smuzhiyun * reservations if we do add more properties in the future.
363*4882a593Smuzhiyun */
364*4882a593Smuzhiyun if (need_reserve) {
365*4882a593Smuzhiyun num_bytes = btrfs_calc_insert_metadata_size(fs_info, 1);
366*4882a593Smuzhiyun ret = btrfs_block_rsv_add(root, trans->block_rsv,
367*4882a593Smuzhiyun num_bytes, BTRFS_RESERVE_NO_FLUSH);
368*4882a593Smuzhiyun if (ret)
369*4882a593Smuzhiyun return ret;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun ret = btrfs_setxattr(trans, inode, h->xattr_name, value,
373*4882a593Smuzhiyun strlen(value), 0);
374*4882a593Smuzhiyun if (!ret) {
375*4882a593Smuzhiyun ret = h->apply(inode, value, strlen(value));
376*4882a593Smuzhiyun if (ret)
377*4882a593Smuzhiyun btrfs_setxattr(trans, inode, h->xattr_name,
378*4882a593Smuzhiyun NULL, 0, 0);
379*4882a593Smuzhiyun else
380*4882a593Smuzhiyun set_bit(BTRFS_INODE_HAS_PROPS,
381*4882a593Smuzhiyun &BTRFS_I(inode)->runtime_flags);
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun if (need_reserve) {
385*4882a593Smuzhiyun btrfs_block_rsv_release(fs_info, trans->block_rsv,
386*4882a593Smuzhiyun num_bytes, NULL);
387*4882a593Smuzhiyun if (ret)
388*4882a593Smuzhiyun return ret;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun need_reserve = true;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun return 0;
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun
btrfs_inode_inherit_props(struct btrfs_trans_handle * trans,struct inode * inode,struct inode * dir)396*4882a593Smuzhiyun int btrfs_inode_inherit_props(struct btrfs_trans_handle *trans,
397*4882a593Smuzhiyun struct inode *inode,
398*4882a593Smuzhiyun struct inode *dir)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun if (!dir)
401*4882a593Smuzhiyun return 0;
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun return inherit_props(trans, inode, dir);
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
btrfs_subvol_inherit_props(struct btrfs_trans_handle * trans,struct btrfs_root * root,struct btrfs_root * parent_root)406*4882a593Smuzhiyun int btrfs_subvol_inherit_props(struct btrfs_trans_handle *trans,
407*4882a593Smuzhiyun struct btrfs_root *root,
408*4882a593Smuzhiyun struct btrfs_root *parent_root)
409*4882a593Smuzhiyun {
410*4882a593Smuzhiyun struct super_block *sb = root->fs_info->sb;
411*4882a593Smuzhiyun struct inode *parent_inode, *child_inode;
412*4882a593Smuzhiyun int ret;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun parent_inode = btrfs_iget(sb, BTRFS_FIRST_FREE_OBJECTID, parent_root);
415*4882a593Smuzhiyun if (IS_ERR(parent_inode))
416*4882a593Smuzhiyun return PTR_ERR(parent_inode);
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun child_inode = btrfs_iget(sb, BTRFS_FIRST_FREE_OBJECTID, root);
419*4882a593Smuzhiyun if (IS_ERR(child_inode)) {
420*4882a593Smuzhiyun iput(parent_inode);
421*4882a593Smuzhiyun return PTR_ERR(child_inode);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun ret = inherit_props(trans, child_inode, parent_inode);
425*4882a593Smuzhiyun iput(child_inode);
426*4882a593Smuzhiyun iput(parent_inode);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun return ret;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
btrfs_props_init(void)431*4882a593Smuzhiyun void __init btrfs_props_init(void)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun int i;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(prop_handlers); i++) {
436*4882a593Smuzhiyun struct prop_handler *p = &prop_handlers[i];
437*4882a593Smuzhiyun u64 h = btrfs_name_hash(p->xattr_name, strlen(p->xattr_name));
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun hash_add(prop_handlers_ht, &p->node, h);
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
443