aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/Makefile2
-rw-r--r--fs/btrfs/btrfs_inode.h1
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/inode.c42
-rw-r--r--fs/btrfs/ioctl.c19
-rw-r--r--fs/btrfs/props.c427
-rw-r--r--fs/btrfs/props.h42
-rw-r--r--fs/btrfs/super.c3
-rw-r--r--fs/btrfs/xattr.c12
-rw-r--r--include/uapi/linux/xattr.h3
10 files changed, 545 insertions, 10 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
index 1a44e42d602a..af7f000e905c 100644
--- a/fs/btrfs/Makefile
+++ b/fs/btrfs/Makefile
@@ -9,7 +9,7 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
9 export.o tree-log.o free-space-cache.o zlib.o lzo.o \ 9 export.o tree-log.o free-space-cache.o zlib.o lzo.o \
10 compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \ 10 compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \
11 reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \ 11 reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \
12 uuid-tree.o 12 uuid-tree.o props.o
13 13
14btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o 14btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o
15btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o 15btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index 661b0ac90e8f..8fed2125689e 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -43,6 +43,7 @@
43#define BTRFS_INODE_COPY_EVERYTHING 8 43#define BTRFS_INODE_COPY_EVERYTHING 8
44#define BTRFS_INODE_IN_DELALLOC_LIST 9 44#define BTRFS_INODE_IN_DELALLOC_LIST 9
45#define BTRFS_INODE_READDIO_NEED_LOCK 10 45#define BTRFS_INODE_READDIO_NEED_LOCK 10
46#define BTRFS_INODE_HAS_PROPS 11
46 47
47/* in memory btrfs inode */ 48/* in memory btrfs inode */
48struct btrfs_inode { 49struct btrfs_inode {
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f52a60b9eba5..3cebb4aeddc7 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3703,7 +3703,9 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput);
3703int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end, 3703int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
3704 struct extent_state **cached_state); 3704 struct extent_state **cached_state);
3705int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, 3705int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
3706 struct btrfs_root *new_root, u64 new_dirid); 3706 struct btrfs_root *new_root,
3707 struct btrfs_root *parent_root,
3708 u64 new_dirid);
3707int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset, 3709int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset,
3708 size_t size, struct bio *bio, 3710 size_t size, struct bio *bio,
3709 unsigned long bio_flags); 3711 unsigned long bio_flags);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 23f18eb5fb55..1ea19cea96d0 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -58,6 +58,7 @@
58#include "inode-map.h" 58#include "inode-map.h"
59#include "backref.h" 59#include "backref.h"
60#include "hash.h" 60#include "hash.h"
61#include "props.h"
61 62
62struct btrfs_iget_args { 63struct btrfs_iget_args {
63 u64 ino; 64 u64 ino;
@@ -3265,7 +3266,8 @@ out:
3265 * slot is the slot the inode is in, objectid is the objectid of the inode 3266 * slot is the slot the inode is in, objectid is the objectid of the inode
3266 */ 3267 */
3267static noinline int acls_after_inode_item(struct extent_buffer *leaf, 3268static noinline int acls_after_inode_item(struct extent_buffer *leaf,
3268 int slot, u64 objectid) 3269 int slot, u64 objectid,
3270 int *first_xattr_slot)
3269{ 3271{
3270 u32 nritems = btrfs_header_nritems(leaf); 3272 u32 nritems = btrfs_header_nritems(leaf);
3271 struct btrfs_key found_key; 3273 struct btrfs_key found_key;
@@ -3281,6 +3283,7 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
3281 } 3283 }
3282 3284
3283 slot++; 3285 slot++;
3286 *first_xattr_slot = -1;
3284 while (slot < nritems) { 3287 while (slot < nritems) {
3285 btrfs_item_key_to_cpu(leaf, &found_key, slot); 3288 btrfs_item_key_to_cpu(leaf, &found_key, slot);
3286 3289
@@ -3290,6 +3293,8 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
3290 3293
3291 /* we found an xattr, assume we've got an acl */ 3294 /* we found an xattr, assume we've got an acl */
3292 if (found_key.type == BTRFS_XATTR_ITEM_KEY) { 3295 if (found_key.type == BTRFS_XATTR_ITEM_KEY) {
3296 if (*first_xattr_slot == -1)
3297 *first_xattr_slot = slot;
3293 if (found_key.offset == xattr_access || 3298 if (found_key.offset == xattr_access ||
3294 found_key.offset == xattr_default) 3299 found_key.offset == xattr_default)
3295 return 1; 3300 return 1;
@@ -3318,6 +3323,8 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
3318 * something larger than an xattr. We have to assume the inode 3323 * something larger than an xattr. We have to assume the inode
3319 * has acls 3324 * has acls
3320 */ 3325 */
3326 if (*first_xattr_slot == -1)
3327 *first_xattr_slot = slot;
3321 return 1; 3328 return 1;
3322} 3329}
3323 3330
@@ -3337,6 +3344,7 @@ static void btrfs_read_locked_inode(struct inode *inode)
3337 u32 rdev; 3344 u32 rdev;
3338 int ret; 3345 int ret;
3339 bool filled = false; 3346 bool filled = false;
3347 int first_xattr_slot;
3340 3348
3341 ret = btrfs_fill_inode(inode, &rdev); 3349 ret = btrfs_fill_inode(inode, &rdev);
3342 if (!ret) 3350 if (!ret)
@@ -3346,7 +3354,6 @@ static void btrfs_read_locked_inode(struct inode *inode)
3346 if (!path) 3354 if (!path)
3347 goto make_bad; 3355 goto make_bad;
3348 3356
3349 path->leave_spinning = 1;
3350 memcpy(&location, &BTRFS_I(inode)->location, sizeof(location)); 3357 memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
3351 3358
3352 ret = btrfs_lookup_inode(NULL, root, path, &location, 0); 3359 ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
@@ -3429,12 +3436,21 @@ cache_acl:
3429 * any xattrs or acls 3436 * any xattrs or acls
3430 */ 3437 */
3431 maybe_acls = acls_after_inode_item(leaf, path->slots[0], 3438 maybe_acls = acls_after_inode_item(leaf, path->slots[0],
3432 btrfs_ino(inode)); 3439 btrfs_ino(inode), &first_xattr_slot);
3440 if (first_xattr_slot != -1) {
3441 path->slots[0] = first_xattr_slot;
3442 ret = btrfs_load_inode_props(inode, path);
3443 if (ret)
3444 btrfs_err(root->fs_info,
3445 "error loading props for ino %llu (root %llu): %d\n",
3446 btrfs_ino(inode),
3447 root->root_key.objectid, ret);
3448 }
3449 btrfs_free_path(path);
3450
3433 if (!maybe_acls) 3451 if (!maybe_acls)
3434 cache_no_acl(inode); 3452 cache_no_acl(inode);
3435 3453
3436 btrfs_free_path(path);
3437
3438 switch (inode->i_mode & S_IFMT) { 3454 switch (inode->i_mode & S_IFMT) {
3439 case S_IFREG: 3455 case S_IFREG:
3440 inode->i_mapping->a_ops = &btrfs_aops; 3456 inode->i_mapping->a_ops = &btrfs_aops;
@@ -5607,6 +5623,12 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
5607 5623
5608 btrfs_update_root_times(trans, root); 5624 btrfs_update_root_times(trans, root);
5609 5625
5626 ret = btrfs_inode_inherit_props(trans, inode, dir);
5627 if (ret)
5628 btrfs_err(root->fs_info,
5629 "error inheriting props for ino %llu (root %llu): %d",
5630 btrfs_ino(inode), root->root_key.objectid, ret);
5631
5610 return inode; 5632 return inode;
5611fail: 5633fail:
5612 if (dir) 5634 if (dir)
@@ -7889,7 +7911,9 @@ out:
7889 * create a new subvolume directory/inode (helper for the ioctl). 7911 * create a new subvolume directory/inode (helper for the ioctl).
7890 */ 7912 */
7891int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, 7913int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
7892 struct btrfs_root *new_root, u64 new_dirid) 7914 struct btrfs_root *new_root,
7915 struct btrfs_root *parent_root,
7916 u64 new_dirid)
7893{ 7917{
7894 struct inode *inode; 7918 struct inode *inode;
7895 int err; 7919 int err;
@@ -7907,6 +7931,12 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
7907 set_nlink(inode, 1); 7931 set_nlink(inode, 1);
7908 btrfs_i_size_write(inode, 0); 7932 btrfs_i_size_write(inode, 0);
7909 7933
7934 err = btrfs_subvol_inherit_props(trans, new_root, parent_root);
7935 if (err)
7936 btrfs_err(new_root->fs_info,
7937 "error inheriting subvolume %llu properties: %d\n",
7938 new_root->root_key.objectid, err);
7939
7910 err = btrfs_update_inode(trans, new_root, inode); 7940 err = btrfs_update_inode(trans, new_root, inode);
7911 7941
7912 iput(inode); 7942 iput(inode);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index ed3edc283255..3970f32b2b80 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -56,6 +56,7 @@
56#include "rcu-string.h" 56#include "rcu-string.h"
57#include "send.h" 57#include "send.h"
58#include "dev-replace.h" 58#include "dev-replace.h"
59#include "props.h"
59#include "sysfs.h" 60#include "sysfs.h"
60 61
61static int btrfs_clone(struct inode *src, struct inode *inode, 62static int btrfs_clone(struct inode *src, struct inode *inode,
@@ -281,9 +282,25 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
281 if (flags & FS_NOCOMP_FL) { 282 if (flags & FS_NOCOMP_FL) {
282 ip->flags &= ~BTRFS_INODE_COMPRESS; 283 ip->flags &= ~BTRFS_INODE_COMPRESS;
283 ip->flags |= BTRFS_INODE_NOCOMPRESS; 284 ip->flags |= BTRFS_INODE_NOCOMPRESS;
285
286 ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0);
287 if (ret && ret != -ENODATA)
288 goto out_drop;
284 } else if (flags & FS_COMPR_FL) { 289 } else if (flags & FS_COMPR_FL) {
290 const char *comp;
291
285 ip->flags |= BTRFS_INODE_COMPRESS; 292 ip->flags |= BTRFS_INODE_COMPRESS;
286 ip->flags &= ~BTRFS_INODE_NOCOMPRESS; 293 ip->flags &= ~BTRFS_INODE_NOCOMPRESS;
294
295 if (root->fs_info->compress_type == BTRFS_COMPRESS_LZO)
296 comp = "lzo";
297 else
298 comp = "zlib";
299 ret = btrfs_set_prop(inode, "btrfs.compression",
300 comp, strlen(comp), 0);
301 if (ret)
302 goto out_drop;
303
287 } else { 304 } else {
288 ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS); 305 ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
289 } 306 }
@@ -502,7 +519,7 @@ static noinline int create_subvol(struct inode *dir,
502 519
503 btrfs_record_root_in_trans(trans, new_root); 520 btrfs_record_root_in_trans(trans, new_root);
504 521
505 ret = btrfs_create_subvol_root(trans, new_root, new_dirid); 522 ret = btrfs_create_subvol_root(trans, new_root, root, new_dirid);
506 if (ret) { 523 if (ret) {
507 /* We potentially lose an unused inode item here */ 524 /* We potentially lose an unused inode item here */
508 btrfs_abort_transaction(trans, root, ret); 525 btrfs_abort_transaction(trans, root, ret);
diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c
new file mode 100644
index 000000000000..129b1dd28527
--- /dev/null
+++ b/fs/btrfs/props.c
@@ -0,0 +1,427 @@
1/*
2 * Copyright (C) 2014 Filipe David Borba Manana <fdmanana@gmail.com>
3 *
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.
7 *
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.
12 *
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.
17 */
18
19#include <linux/hashtable.h>
20#include "props.h"
21#include "btrfs_inode.h"
22#include "hash.h"
23#include "transaction.h"
24#include "xattr.h"
25
26#define BTRFS_PROP_HANDLERS_HT_BITS 8
27static DEFINE_HASHTABLE(prop_handlers_ht, BTRFS_PROP_HANDLERS_HT_BITS);
28
29struct prop_handler {
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);
35 int inheritable;
36};
37
38static int prop_compression_validate(const char *value, size_t len);
39static int prop_compression_apply(struct inode *inode,
40 const char *value,
41 size_t len);
42static const char *prop_compression_extract(struct inode *inode);
43
44static struct prop_handler prop_handlers[] = {
45 {
46 .xattr_name = XATTR_BTRFS_PREFIX "compression",
47 .validate = prop_compression_validate,
48 .apply = prop_compression_apply,
49 .extract = prop_compression_extract,
50 .inheritable = 1
51 },
52 {
53 .xattr_name = NULL
54 }
55};
56
57void __init btrfs_props_init(void)
58{
59 struct prop_handler *p;
60
61 hash_init(prop_handlers_ht);
62
63 for (p = &prop_handlers[0]; p->xattr_name; p++) {
64 u64 h = btrfs_name_hash(p->xattr_name, strlen(p->xattr_name));
65
66 hash_add(prop_handlers_ht, &p->node, h);
67 }
68}
69
70static const struct hlist_head *find_prop_handlers_by_hash(const u64 hash)
71{
72 struct hlist_head *h;
73
74 h = &prop_handlers_ht[hash_min(hash, BTRFS_PROP_HANDLERS_HT_BITS)];
75 if (hlist_empty(h))
76 return NULL;
77
78 return h;
79}
80
81static const struct prop_handler *
82find_prop_handler(const char *name,
83 const struct hlist_head *handlers)
84{
85 struct prop_handler *h;
86
87 if (!handlers) {
88 u64 hash = btrfs_name_hash(name, strlen(name));
89
90 handlers = find_prop_handlers_by_hash(hash);
91 if (!handlers)
92 return NULL;
93 }
94
95 hlist_for_each_entry(h, handlers, node)
96 if (!strcmp(h->xattr_name, name))
97 return h;
98
99 return NULL;
100}
101
102static int __btrfs_set_prop(struct btrfs_trans_handle *trans,
103 struct inode *inode,
104 const char *name,
105 const char *value,
106 size_t value_len,
107 int flags)
108{
109 const struct prop_handler *handler;
110 int ret;
111
112 if (strlen(name) <= XATTR_BTRFS_PREFIX_LEN)
113 return -EINVAL;
114
115 handler = find_prop_handler(name, NULL);
116 if (!handler)
117 return -EINVAL;
118
119 if (value_len == 0) {
120 ret = __btrfs_setxattr(trans, inode, handler->xattr_name,
121 NULL, 0, flags);
122 if (ret)
123 return ret;
124
125 ret = handler->apply(inode, NULL, 0);
126 ASSERT(ret == 0);
127
128 return ret;
129 }
130
131 ret = handler->validate(value, value_len);
132 if (ret)
133 return ret;
134 ret = __btrfs_setxattr(trans, inode, handler->xattr_name,
135 value, value_len, flags);
136 if (ret)
137 return ret;
138 ret = handler->apply(inode, value, value_len);
139 if (ret) {
140 __btrfs_setxattr(trans, inode, handler->xattr_name,
141 NULL, 0, flags);
142 return ret;
143 }
144
145 set_bit(BTRFS_INODE_HAS_PROPS, &BTRFS_I(inode)->runtime_flags);
146
147 return 0;
148}
149
150int btrfs_set_prop(struct inode *inode,
151 const char *name,
152 const char *value,
153 size_t value_len,
154 int flags)
155{
156 return __btrfs_set_prop(NULL, inode, name, value, value_len, flags);
157}
158
159static int iterate_object_props(struct btrfs_root *root,
160 struct btrfs_path *path,
161 u64 objectid,
162 void (*iterator)(void *,
163 const struct prop_handler *,
164 const char *,
165 size_t),
166 void *ctx)
167{
168 int ret;
169 char *name_buf = NULL;
170 char *value_buf = NULL;
171 int name_buf_len = 0;
172 int value_buf_len = 0;
173
174 while (1) {
175 struct btrfs_key key;
176 struct btrfs_dir_item *di;
177 struct extent_buffer *leaf;
178 u32 total_len, cur, this_len;
179 int slot;
180 const struct hlist_head *handlers;
181
182 slot = path->slots[0];
183 leaf = path->nodes[0];
184
185 if (slot >= btrfs_header_nritems(leaf)) {
186 ret = btrfs_next_leaf(root, path);
187 if (ret < 0)
188 goto out;
189 else if (ret > 0)
190 break;
191 continue;
192 }
193
194 btrfs_item_key_to_cpu(leaf, &key, slot);
195 if (key.objectid != objectid)
196 break;
197 if (key.type != BTRFS_XATTR_ITEM_KEY)
198 break;
199
200 handlers = find_prop_handlers_by_hash(key.offset);
201 if (!handlers)
202 goto next_slot;
203
204 di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
205 cur = 0;
206 total_len = btrfs_item_size_nr(leaf, slot);
207
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;
213
214 this_len = sizeof(*di) + name_len + data_len;
215 name_ptr = (unsigned long)(di + 1);
216 data_ptr = name_ptr + name_len;
217
218 if (name_len <= XATTR_BTRFS_PREFIX_LEN ||
219 memcmp_extent_buffer(leaf, XATTR_BTRFS_PREFIX,
220 name_ptr,
221 XATTR_BTRFS_PREFIX_LEN))
222 goto next_dir_item;
223
224 if (name_len >= name_buf_len) {
225 kfree(name_buf);
226 name_buf_len = name_len + 1;
227 name_buf = kmalloc(name_buf_len, GFP_NOFS);
228 if (!name_buf) {
229 ret = -ENOMEM;
230 goto out;
231 }
232 }
233 read_extent_buffer(leaf, name_buf, name_ptr, name_len);
234 name_buf[name_len] = '\0';
235
236 handler = find_prop_handler(name_buf, handlers);
237 if (!handler)
238 goto next_dir_item;
239
240 if (data_len > value_buf_len) {
241 kfree(value_buf);
242 value_buf_len = data_len;
243 value_buf = kmalloc(data_len, GFP_NOFS);
244 if (!value_buf) {
245 ret = -ENOMEM;
246 goto out;
247 }
248 }
249 read_extent_buffer(leaf, value_buf, data_ptr, data_len);
250
251 iterator(ctx, handler, value_buf, data_len);
252next_dir_item:
253 cur += this_len;
254 di = (struct btrfs_dir_item *)((char *) di + this_len);
255 }
256
257next_slot:
258 path->slots[0]++;
259 }
260
261 ret = 0;
262out:
263 btrfs_release_path(path);
264 kfree(name_buf);
265 kfree(value_buf);
266
267 return ret;
268}
269
270static void inode_prop_iterator(void *ctx,
271 const struct prop_handler *handler,
272 const char *value,
273 size_t len)
274{
275 struct inode *inode = ctx;
276 struct btrfs_root *root = BTRFS_I(inode)->root;
277 int ret;
278
279 ret = handler->apply(inode, value, len);
280 if (unlikely(ret))
281 btrfs_warn(root->fs_info,
282 "error applying prop %s to ino %llu (root %llu): %d",
283 handler->xattr_name, btrfs_ino(inode),
284 root->root_key.objectid, ret);
285 else
286 set_bit(BTRFS_INODE_HAS_PROPS, &BTRFS_I(inode)->runtime_flags);
287}
288
289int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path)
290{
291 struct btrfs_root *root = BTRFS_I(inode)->root;
292 u64 ino = btrfs_ino(inode);
293 int ret;
294
295 ret = iterate_object_props(root, path, ino, inode_prop_iterator, inode);
296
297 return ret;
298}
299
300static int inherit_props(struct btrfs_trans_handle *trans,
301 struct inode *inode,
302 struct inode *parent)
303{
304 const struct prop_handler *h;
305 struct btrfs_root *root = BTRFS_I(inode)->root;
306 int ret;
307
308 if (!test_bit(BTRFS_INODE_HAS_PROPS,
309 &BTRFS_I(parent)->runtime_flags))
310 return 0;
311
312 for (h = &prop_handlers[0]; h->xattr_name; h++) {
313 const char *value;
314 u64 num_bytes;
315
316 if (!h->inheritable)
317 continue;
318
319 value = h->extract(parent);
320 if (!value)
321 continue;
322
323 num_bytes = btrfs_calc_trans_metadata_size(root, 1);
324 ret = btrfs_block_rsv_add(root, trans->block_rsv,
325 num_bytes, BTRFS_RESERVE_NO_FLUSH);
326 if (ret)
327 goto out;
328 ret = __btrfs_set_prop(trans, inode, h->xattr_name,
329 value, strlen(value), 0);
330 btrfs_block_rsv_release(root, trans->block_rsv, num_bytes);
331 if (ret)
332 goto out;
333 }
334 ret = 0;
335out:
336 return ret;
337}
338
339int btrfs_inode_inherit_props(struct btrfs_trans_handle *trans,
340 struct inode *inode,
341 struct inode *dir)
342{
343 if (!dir)
344 return 0;
345
346 return inherit_props(trans, inode, dir);
347}
348
349int btrfs_subvol_inherit_props(struct btrfs_trans_handle *trans,
350 struct btrfs_root *root,
351 struct btrfs_root *parent_root)
352{
353 struct btrfs_key key;
354 struct inode *parent_inode, *child_inode;
355 int ret;
356
357 key.objectid = BTRFS_FIRST_FREE_OBJECTID;
358 key.type = BTRFS_INODE_ITEM_KEY;
359 key.offset = 0;
360
361 parent_inode = btrfs_iget(parent_root->fs_info->sb, &key,
362 parent_root, NULL);
363 if (IS_ERR(parent_inode))
364 return PTR_ERR(parent_inode);
365
366 child_inode = btrfs_iget(root->fs_info->sb, &key, root, NULL);
367 if (IS_ERR(child_inode)) {
368 iput(parent_inode);
369 return PTR_ERR(child_inode);
370 }
371
372 ret = inherit_props(trans, child_inode, parent_inode);
373 iput(child_inode);
374 iput(parent_inode);
375
376 return ret;
377}
378
379static int prop_compression_validate(const char *value, size_t len)
380{
381 if (!strncmp("lzo", value, len))
382 return 0;
383 else if (!strncmp("zlib", value, len))
384 return 0;
385
386 return -EINVAL;
387}
388
389static int prop_compression_apply(struct inode *inode,
390 const char *value,
391 size_t len)
392{
393 int type;
394
395 if (len == 0) {
396 BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
397 BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS;
398 BTRFS_I(inode)->force_compress = BTRFS_COMPRESS_NONE;
399
400 return 0;
401 }
402
403 if (!strncmp("lzo", value, len))
404 type = BTRFS_COMPRESS_LZO;
405 else if (!strncmp("zlib", value, len))
406 type = BTRFS_COMPRESS_ZLIB;
407 else
408 return -EINVAL;
409
410 BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS;
411 BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS;
412 BTRFS_I(inode)->force_compress = type;
413
414 return 0;
415}
416
417static const char *prop_compression_extract(struct inode *inode)
418{
419 switch (BTRFS_I(inode)->force_compress) {
420 case BTRFS_COMPRESS_ZLIB:
421 return "zlib";
422 case BTRFS_COMPRESS_LZO:
423 return "lzo";
424 }
425
426 return NULL;
427}
diff --git a/fs/btrfs/props.h b/fs/btrfs/props.h
new file mode 100644
index 000000000000..100f18829d50
--- /dev/null
+++ b/fs/btrfs/props.h
@@ -0,0 +1,42 @@
1/*
2 * Copyright (C) 2014 Filipe David Borba Manana <fdmanana@gmail.com>
3 *
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.
7 *
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.
12 *
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.
17 */
18
19#ifndef __BTRFS_PROPS_H
20#define __BTRFS_PROPS_H
21
22#include "ctree.h"
23
24void __init btrfs_props_init(void);
25
26int btrfs_set_prop(struct inode *inode,
27 const char *name,
28 const char *value,
29 size_t value_len,
30 int flags);
31
32int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path);
33
34int btrfs_inode_inherit_props(struct btrfs_trans_handle *trans,
35 struct inode *inode,
36 struct inode *dir);
37
38int btrfs_subvol_inherit_props(struct btrfs_trans_handle *trans,
39 struct btrfs_root *root,
40 struct btrfs_root *parent_root);
41
42#endif
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 16d7fc751ba8..461e41cb8ca7 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -48,6 +48,7 @@
48#include "transaction.h" 48#include "transaction.h"
49#include "btrfs_inode.h" 49#include "btrfs_inode.h"
50#include "print-tree.h" 50#include "print-tree.h"
51#include "props.h"
51#include "xattr.h" 52#include "xattr.h"
52#include "volumes.h" 53#include "volumes.h"
53#include "export.h" 54#include "export.h"
@@ -1865,6 +1866,8 @@ static int __init init_btrfs_fs(void)
1865{ 1866{
1866 int err; 1867 int err;
1867 1868
1869 btrfs_props_init();
1870
1868 err = btrfs_init_sysfs(); 1871 err = btrfs_init_sysfs();
1869 if (err) 1872 if (err)
1870 return err; 1873 return err;
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index 05740b9789e4..4b33765add38 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -27,6 +27,7 @@
27#include "transaction.h" 27#include "transaction.h"
28#include "xattr.h" 28#include "xattr.h"
29#include "disk-io.h" 29#include "disk-io.h"
30#include "props.h"
30 31
31 32
32ssize_t __btrfs_getxattr(struct inode *inode, const char *name, 33ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
@@ -331,7 +332,8 @@ static bool btrfs_is_valid_xattr(const char *name)
331 XATTR_SECURITY_PREFIX_LEN) || 332 XATTR_SECURITY_PREFIX_LEN) ||
332 !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || 333 !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
333 !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || 334 !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
334 !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); 335 !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) ||
336 !strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN);
335} 337}
336 338
337ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, 339ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
@@ -373,6 +375,10 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
373 if (!btrfs_is_valid_xattr(name)) 375 if (!btrfs_is_valid_xattr(name))
374 return -EOPNOTSUPP; 376 return -EOPNOTSUPP;
375 377
378 if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
379 return btrfs_set_prop(dentry->d_inode, name,
380 value, size, flags);
381
376 if (size == 0) 382 if (size == 0)
377 value = ""; /* empty EA, do not remove */ 383 value = ""; /* empty EA, do not remove */
378 384
@@ -402,6 +408,10 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
402 if (!btrfs_is_valid_xattr(name)) 408 if (!btrfs_is_valid_xattr(name))
403 return -EOPNOTSUPP; 409 return -EOPNOTSUPP;
404 410
411 if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
412 return btrfs_set_prop(dentry->d_inode, name,
413 NULL, 0, XATTR_REPLACE);
414
405 return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0, 415 return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
406 XATTR_REPLACE); 416 XATTR_REPLACE);
407} 417}
diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h
index e4629b93bdd6..40bbc04b6f81 100644
--- a/include/uapi/linux/xattr.h
+++ b/include/uapi/linux/xattr.h
@@ -20,6 +20,9 @@
20#define XATTR_MAC_OSX_PREFIX "osx." 20#define XATTR_MAC_OSX_PREFIX "osx."
21#define XATTR_MAC_OSX_PREFIX_LEN (sizeof(XATTR_MAC_OSX_PREFIX) - 1) 21#define XATTR_MAC_OSX_PREFIX_LEN (sizeof(XATTR_MAC_OSX_PREFIX) - 1)
22 22
23#define XATTR_BTRFS_PREFIX "btrfs."
24#define XATTR_BTRFS_PREFIX_LEN (sizeof(XATTR_BTRFS_PREFIX) - 1)
25
23#define XATTR_SECURITY_PREFIX "security." 26#define XATTR_SECURITY_PREFIX "security."
24#define XATTR_SECURITY_PREFIX_LEN (sizeof(XATTR_SECURITY_PREFIX) - 1) 27#define XATTR_SECURITY_PREFIX_LEN (sizeof(XATTR_SECURITY_PREFIX) - 1)
25 28