aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/xattr.c')
-rw-r--r--fs/btrfs/xattr.c204
1 files changed, 73 insertions, 131 deletions
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}