aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/acl.c20
-rw-r--r--fs/btrfs/inode.c19
-rw-r--r--fs/btrfs/xattr.c204
-rw-r--r--fs/btrfs/xattr.h31
4 files changed, 104 insertions, 170 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 2f865311460c..867eaf1f8efb 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -42,17 +42,18 @@ static void btrfs_update_cached_acl(struct inode *inode,
42 42
43static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) 43static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
44{ 44{
45 int size, name_index; 45 int size;
46 const char *name;
46 char *value = NULL; 47 char *value = NULL;
47 struct posix_acl *acl = NULL, **p_acl; 48 struct posix_acl *acl = NULL, **p_acl;
48 49
49 switch (type) { 50 switch (type) {
50 case ACL_TYPE_ACCESS: 51 case ACL_TYPE_ACCESS:
51 name_index = BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS; 52 name = POSIX_ACL_XATTR_ACCESS;
52 p_acl = &BTRFS_I(inode)->i_acl; 53 p_acl = &BTRFS_I(inode)->i_acl;
53 break; 54 break;
54 case ACL_TYPE_DEFAULT: 55 case ACL_TYPE_DEFAULT:
55 name_index = BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT; 56 name = POSIX_ACL_XATTR_DEFAULT;
56 p_acl = &BTRFS_I(inode)->i_default_acl; 57 p_acl = &BTRFS_I(inode)->i_default_acl;
57 break; 58 break;
58 default: 59 default:
@@ -68,12 +69,12 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
68 return acl; 69 return acl;
69 70
70 71
71 size = btrfs_xattr_get(inode, name_index, "", NULL, 0); 72 size = __btrfs_getxattr(inode, name, "", 0);
72 if (size > 0) { 73 if (size > 0) {
73 value = kzalloc(size, GFP_NOFS); 74 value = kzalloc(size, GFP_NOFS);
74 if (!value) 75 if (!value)
75 return ERR_PTR(-ENOMEM); 76 return ERR_PTR(-ENOMEM);
76 size = btrfs_xattr_get(inode, name_index, "", value, size); 77 size = __btrfs_getxattr(inode, name, value, size);
77 if (size > 0) { 78 if (size > 0) {
78 acl = posix_acl_from_xattr(value, size); 79 acl = posix_acl_from_xattr(value, size);
79 btrfs_update_cached_acl(inode, p_acl, acl); 80 btrfs_update_cached_acl(inode, p_acl, acl);
@@ -110,7 +111,8 @@ static int btrfs_xattr_get_acl(struct inode *inode, int type,
110 */ 111 */
111static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 112static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
112{ 113{
113 int ret, name_index = 0, size = 0; 114 int ret, size = 0;
115 const char *name;
114 struct posix_acl **p_acl; 116 struct posix_acl **p_acl;
115 char *value = NULL; 117 char *value = NULL;
116 mode_t mode; 118 mode_t mode;
@@ -130,13 +132,13 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
130 return ret; 132 return ret;
131 ret = 0; 133 ret = 0;
132 inode->i_mode = mode; 134 inode->i_mode = mode;
133 name_index = BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS; 135 name = POSIX_ACL_XATTR_ACCESS;
134 p_acl = &BTRFS_I(inode)->i_acl; 136 p_acl = &BTRFS_I(inode)->i_acl;
135 break; 137 break;
136 case ACL_TYPE_DEFAULT: 138 case ACL_TYPE_DEFAULT:
137 if (!S_ISDIR(inode->i_mode)) 139 if (!S_ISDIR(inode->i_mode))
138 return acl ? -EINVAL : 0; 140 return acl ? -EINVAL : 0;
139 name_index = BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT; 141 name = POSIX_ACL_XATTR_DEFAULT;
140 p_acl = &BTRFS_I(inode)->i_default_acl; 142 p_acl = &BTRFS_I(inode)->i_default_acl;
141 break; 143 break;
142 default: 144 default:
@@ -156,7 +158,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
156 goto out; 158 goto out;
157 } 159 }
158 160
159 ret = btrfs_xattr_set(inode, name_index, "", value, size, 0); 161 ret = __btrfs_setxattr(inode, name, value, size, 0);
160 162
161out: 163out:
162 if (value) 164 if (value)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 10f26f445328..43d3f2649ca3 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -45,6 +45,7 @@
45#include "print-tree.h" 45#include "print-tree.h"
46#include "volumes.h" 46#include "volumes.h"
47#include "ordered-data.h" 47#include "ordered-data.h"
48#include "xattr.h"
48 49
49struct btrfs_iget_args { 50struct btrfs_iget_args {
50 u64 ino; 51 u64 ino;
@@ -3667,10 +3668,10 @@ static struct inode_operations btrfs_dir_inode_operations = {
3667 .symlink = btrfs_symlink, 3668 .symlink = btrfs_symlink,
3668 .setattr = btrfs_setattr, 3669 .setattr = btrfs_setattr,
3669 .mknod = btrfs_mknod, 3670 .mknod = btrfs_mknod,
3670 .setxattr = generic_setxattr, 3671 .setxattr = btrfs_setxattr,
3671 .getxattr = generic_getxattr, 3672 .getxattr = btrfs_getxattr,
3672 .listxattr = btrfs_listxattr, 3673 .listxattr = btrfs_listxattr,
3673 .removexattr = generic_removexattr, 3674 .removexattr = btrfs_removexattr,
3674 .permission = btrfs_permission, 3675 .permission = btrfs_permission,
3675}; 3676};
3676static struct inode_operations btrfs_dir_ro_inode_operations = { 3677static struct inode_operations btrfs_dir_ro_inode_operations = {
@@ -3728,20 +3729,20 @@ static struct inode_operations btrfs_file_inode_operations = {
3728 .truncate = btrfs_truncate, 3729 .truncate = btrfs_truncate,
3729 .getattr = btrfs_getattr, 3730 .getattr = btrfs_getattr,
3730 .setattr = btrfs_setattr, 3731 .setattr = btrfs_setattr,
3731 .setxattr = generic_setxattr, 3732 .setxattr = btrfs_setxattr,
3732 .getxattr = generic_getxattr, 3733 .getxattr = btrfs_getxattr,
3733 .listxattr = btrfs_listxattr, 3734 .listxattr = btrfs_listxattr,
3734 .removexattr = generic_removexattr, 3735 .removexattr = btrfs_removexattr,
3735 .permission = btrfs_permission, 3736 .permission = btrfs_permission,
3736}; 3737};
3737static struct inode_operations btrfs_special_inode_operations = { 3738static struct inode_operations btrfs_special_inode_operations = {
3738 .getattr = btrfs_getattr, 3739 .getattr = btrfs_getattr,
3739 .setattr = btrfs_setattr, 3740 .setattr = btrfs_setattr,
3740 .permission = btrfs_permission, 3741 .permission = btrfs_permission,
3741 .setxattr = generic_setxattr, 3742 .setxattr = btrfs_setxattr,
3742 .getxattr = generic_getxattr, 3743 .getxattr = btrfs_getxattr,
3743 .listxattr = btrfs_listxattr, 3744 .listxattr = btrfs_listxattr,
3744 .removexattr = generic_removexattr, 3745 .removexattr = btrfs_removexattr,
3745}; 3746};
3746static struct inode_operations btrfs_symlink_inode_operations = { 3747static struct inode_operations btrfs_symlink_inode_operations = {
3747 .readlink = generic_readlink, 3748 .readlink = generic_readlink,
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index fdfece41dd16..adb4b32a9d51 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -27,91 +27,20 @@
27#include "xattr.h" 27#include "xattr.h"
28#include "disk-io.h" 28#include "disk-io.h"
29 29
30static struct xattr_handler *btrfs_xattr_handler_map[] = {
31 [BTRFS_XATTR_INDEX_USER] = &btrfs_xattr_user_handler,
32#ifdef CONFIG_FS_POSIX_ACL
33 [BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &btrfs_xattr_acl_access_handler,
34 [BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &btrfs_xattr_acl_default_handler,
35#endif
36 [BTRFS_XATTR_INDEX_TRUSTED] = &btrfs_xattr_trusted_handler,
37 [BTRFS_XATTR_INDEX_SECURITY] = &btrfs_xattr_security_handler,
38 [BTRFS_XATTR_INDEX_SYSTEM] = &btrfs_xattr_system_handler,
39};
40
41struct xattr_handler *btrfs_xattr_handlers[] = {
42 &btrfs_xattr_user_handler,
43#ifdef CONFIG_FS_POSIX_ACL
44 &btrfs_xattr_acl_access_handler,
45 &btrfs_xattr_acl_default_handler,
46#endif
47 &btrfs_xattr_trusted_handler,
48 &btrfs_xattr_security_handler,
49 &btrfs_xattr_system_handler,
50 NULL,
51};
52
53/*
54 * @param name_index - the index for the xattr handler
55 * @return the xattr_handler if we found it, NULL otherwise
56 *
57 * use this if we know the type of the xattr already
58 */
59static struct xattr_handler *btrfs_xattr_handler(int name_index)
60{
61 struct xattr_handler *handler = NULL;
62
63 if (name_index >= 0 &&
64 name_index < ARRAY_SIZE(btrfs_xattr_handler_map))
65 handler = btrfs_xattr_handler_map[name_index];
66
67 return handler;
68}
69
70static inline char *get_name(const char *name, int name_index)
71{
72 char *ret = NULL;
73 struct xattr_handler *handler = btrfs_xattr_handler(name_index);
74 int prefix_len;
75
76 if (!handler)
77 return ret;
78
79 prefix_len = strlen(handler->prefix);
80
81 ret = kmalloc(strlen(name) + prefix_len + 1, GFP_KERNEL);
82 if (!ret)
83 return ret;
84
85 memcpy(ret, handler->prefix, prefix_len);
86 memcpy(ret+prefix_len, name, strlen(name));
87 ret[prefix_len + strlen(name)] = '\0';
88
89 return ret;
90}
91 30
92ssize_t btrfs_xattr_get(struct inode *inode, int name_index, 31ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
93 const char *attr_name, void *buffer, size_t size) 32 void *buffer, size_t size)
94{ 33{
95 struct btrfs_dir_item *di; 34 struct btrfs_dir_item *di;
96 struct btrfs_root *root = BTRFS_I(inode)->root; 35 struct btrfs_root *root = BTRFS_I(inode)->root;
97 struct btrfs_path *path; 36 struct btrfs_path *path;
98 struct extent_buffer *leaf; 37 struct extent_buffer *leaf;
99 struct xattr_handler *handler = btrfs_xattr_handler(name_index);
100 int ret = 0; 38 int ret = 0;
101 unsigned long data_ptr; 39 unsigned long data_ptr;
102 char *name;
103
104 if (!handler)
105 return -EOPNOTSUPP;
106 name = get_name(attr_name, name_index);
107 if (!name)
108 return -ENOMEM;
109 40
110 path = btrfs_alloc_path(); 41 path = btrfs_alloc_path();
111 if (!path) { 42 if (!path)
112 kfree(name);
113 return -ENOMEM; 43 return -ENOMEM;
114 }
115 44
116 /* lookup the xattr by name */ 45 /* lookup the xattr by name */
117 di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, 46 di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name,
@@ -140,33 +69,22 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index,
140 ret = btrfs_dir_data_len(leaf, di); 69 ret = btrfs_dir_data_len(leaf, di);
141 70
142out: 71out:
143 kfree(name);
144 btrfs_free_path(path); 72 btrfs_free_path(path);
145 return ret; 73 return ret;
146} 74}
147 75
148int btrfs_xattr_set(struct inode *inode, int name_index, 76int __btrfs_setxattr(struct inode *inode, const char *name,
149 const char *attr_name, const void *value, size_t size, 77 const void *value, size_t size, int flags)
150 int flags)
151{ 78{
152 struct btrfs_dir_item *di; 79 struct btrfs_dir_item *di;
153 struct btrfs_root *root = BTRFS_I(inode)->root; 80 struct btrfs_root *root = BTRFS_I(inode)->root;
154 struct btrfs_trans_handle *trans; 81 struct btrfs_trans_handle *trans;
155 struct btrfs_path *path; 82 struct btrfs_path *path;
156 struct xattr_handler *handler = btrfs_xattr_handler(name_index);
157 char *name;
158 int ret = 0, mod = 0; 83 int ret = 0, mod = 0;
159 if (!handler)
160 return -EOPNOTSUPP;
161 name = get_name(attr_name, name_index);
162 if (!name)
163 return -ENOMEM;
164 84
165 path = btrfs_alloc_path(); 85 path = btrfs_alloc_path();
166 if (!path) { 86 if (!path)
167 kfree(name);
168 return -ENOMEM; 87 return -ENOMEM;
169 }
170 88
171 trans = btrfs_start_transaction(root, 1); 89 trans = btrfs_start_transaction(root, 1);
172 btrfs_set_trans_block_group(trans, inode); 90 btrfs_set_trans_block_group(trans, inode);
@@ -221,9 +139,7 @@ out:
221 } 139 }
222 140
223 btrfs_end_transaction(trans, root); 141 btrfs_end_transaction(trans, root);
224 kfree(name);
225 btrfs_free_path(path); 142 btrfs_free_path(path);
226
227 return ret; 143 return ret;
228} 144}
229 145
@@ -329,51 +245,77 @@ err:
329} 245}
330 246
331/* 247/*
332 * Handler functions 248 * List of handlers for synthetic system.* attributes. All real ondisk
249 * attributes are handled directly.
250 */
251struct xattr_handler *btrfs_xattr_handlers[] = {
252#ifdef CONFIG_FS_POSIX_ACL
253 &btrfs_xattr_acl_access_handler,
254 &btrfs_xattr_acl_default_handler,
255#endif
256 NULL,
257};
258
259/*
260 * Check if the attribute is in a supported namespace.
261 *
262 * This applied after the check for the synthetic attributes in the system
263 * namespace.
333 */ 264 */
334#define BTRFS_XATTR_SETGET_FUNCS(name, index) \ 265static bool btrfs_is_valid_xattr(const char *name)
335static int btrfs_xattr_##name##_get(struct inode *inode, \ 266{
336 const char *name, void *value, \ 267 return !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
337 size_t size) \ 268 !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
338{ \ 269 !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
339 if (*name == '\0') \ 270 !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
340 return -EINVAL; \
341 return btrfs_xattr_get(inode, index, name, value, size); \
342} \
343static int btrfs_xattr_##name##_set(struct inode *inode, \
344 const char *name, const void *value,\
345 size_t size, int flags) \
346{ \
347 if (*name == '\0') \
348 return -EINVAL; \
349 return btrfs_xattr_set(inode, index, name, value, size, flags); \
350} 271}
351 272
352BTRFS_XATTR_SETGET_FUNCS(security, BTRFS_XATTR_INDEX_SECURITY); 273ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
353BTRFS_XATTR_SETGET_FUNCS(system, BTRFS_XATTR_INDEX_SYSTEM); 274 void *buffer, size_t size)
354BTRFS_XATTR_SETGET_FUNCS(user, BTRFS_XATTR_INDEX_USER); 275{
355BTRFS_XATTR_SETGET_FUNCS(trusted, BTRFS_XATTR_INDEX_TRUSTED); 276 /*
277 * If this is a request for a synthetic attribute in the system.*
278 * namespace use the generic infrastructure to resolve a handler
279 * for it via sb->s_xattr.
280 */
281 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
282 return generic_getxattr(dentry, name, buffer, size);
356 283
357struct xattr_handler btrfs_xattr_security_handler = { 284 if (!btrfs_is_valid_xattr(name))
358 .prefix = XATTR_SECURITY_PREFIX, 285 return -EOPNOTSUPP;
359 .get = btrfs_xattr_security_get, 286 return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
360 .set = btrfs_xattr_security_set, 287}
361};
362 288
363struct xattr_handler btrfs_xattr_system_handler = { 289int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
364 .prefix = XATTR_SYSTEM_PREFIX, 290 size_t size, int flags)
365 .get = btrfs_xattr_system_get, 291{
366 .set = btrfs_xattr_system_set, 292 /*
367}; 293 * If this is a request for a synthetic attribute in the system.*
294 * namespace use the generic infrastructure to resolve a handler
295 * for it via sb->s_xattr.
296 */
297 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
298 return generic_setxattr(dentry, name, value, size, flags);
368 299
369struct xattr_handler btrfs_xattr_user_handler = { 300 if (!btrfs_is_valid_xattr(name))
370 .prefix = XATTR_USER_PREFIX, 301 return -EOPNOTSUPP;
371 .get = btrfs_xattr_user_get,
372 .set = btrfs_xattr_user_set,
373};
374 302
375struct xattr_handler btrfs_xattr_trusted_handler = { 303 if (size == 0)
376 .prefix = XATTR_TRUSTED_PREFIX, 304 value = ""; /* empty EA, do not remove */
377 .get = btrfs_xattr_trusted_get, 305 return __btrfs_setxattr(dentry->d_inode, name, value, size, flags);
378 .set = btrfs_xattr_trusted_set, 306}
379}; 307
308int btrfs_removexattr(struct dentry *dentry, const char *name)
309{
310 /*
311 * If this is a request for a synthetic attribute in the system.*
312 * namespace use the generic infrastructure to resolve a handler
313 * for it via sb->s_xattr.
314 */
315 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
316 return generic_removexattr(dentry, name);
317
318 if (!btrfs_is_valid_xattr(name))
319 return -EOPNOTSUPP;
320 return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
321}
diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h
index 825e55bd4960..5b1d08f8e68d 100644
--- a/fs/btrfs/xattr.h
+++ b/fs/btrfs/xattr.h
@@ -20,31 +20,20 @@
20#define __XATTR__ 20#define __XATTR__
21 21
22#include <linux/xattr.h> 22#include <linux/xattr.h>
23#include "ctree.h"
24 23
25/* Name indexes */
26enum {
27 BTRFS_XATTR_INDEX_USER,
28 BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS,
29 BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT,
30 BTRFS_XATTR_INDEX_TRUSTED,
31 BTRFS_XATTR_INDEX_SECURITY,
32 BTRFS_XATTR_INDEX_SYSTEM,
33 BTRFS_XATTR_INDEX_END,
34};
35
36extern struct xattr_handler btrfs_xattr_user_handler;
37extern struct xattr_handler btrfs_xattr_trusted_handler;
38extern struct xattr_handler btrfs_xattr_acl_access_handler; 24extern struct xattr_handler btrfs_xattr_acl_access_handler;
39extern struct xattr_handler btrfs_xattr_acl_default_handler; 25extern struct xattr_handler btrfs_xattr_acl_default_handler;
40extern struct xattr_handler btrfs_xattr_security_handler;
41extern struct xattr_handler btrfs_xattr_system_handler;
42
43extern struct xattr_handler *btrfs_xattr_handlers[]; 26extern struct xattr_handler *btrfs_xattr_handlers[];
44 27
45ssize_t btrfs_xattr_get(struct inode *inode, int name_index, const char *name, 28extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
46 void *buffer, size_t size); 29 void *buffer, size_t size);
47int btrfs_xattr_set(struct inode *inode, int name_index, const char *name, 30extern int __btrfs_setxattr(struct inode *inode, const char *name,
48 const void *value, size_t size, int flags); 31 const void *value, size_t size, int flags);
32
33extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
34 void *buffer, size_t size);
35extern int btrfs_setxattr(struct dentry *dentry, const char *name,
36 const void *value, size_t size, int flags);
37extern int btrfs_removexattr(struct dentry *dentry, const char *name);
49 38
50#endif /* __XATTR__ */ 39#endif /* __XATTR__ */