|
27 | 27 | #include "xattr.h"
|
28 | 28 | #include "disk-io.h"
|
29 | 29 |
|
30 |
| -static 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 |
| - |
41 |
| -struct 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 |
| - */ |
59 |
| -static 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 |
| - |
70 |
| -static 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 |
|
92 |
| -ssize_t btrfs_xattr_get(struct inode *inode, int name_index, |
93 |
| - const char *attr_name, void *buffer, size_t size) |
| 31 | +ssize_t __btrfs_getxattr(struct inode *inode, const char *name, |
| 32 | + void *buffer, size_t size) |
94 | 33 | {
|
95 | 34 | struct btrfs_dir_item *di;
|
96 | 35 | struct btrfs_root *root = BTRFS_I(inode)->root;
|
97 | 36 | struct btrfs_path *path;
|
98 | 37 | struct extent_buffer *leaf;
|
99 |
| - struct xattr_handler *handler = btrfs_xattr_handler(name_index); |
100 | 38 | int ret = 0;
|
101 | 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 | 41 | path = btrfs_alloc_path();
|
111 |
| - if (!path) { |
112 |
| - kfree(name); |
| 42 | + if (!path) |
113 | 43 | return -ENOMEM;
|
114 |
| - } |
115 | 44 |
|
116 | 45 | /* lookup the xattr by name */
|
117 | 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 | 69 | ret = btrfs_dir_data_len(leaf, di);
|
141 | 70 |
|
142 | 71 | out:
|
143 |
| - kfree(name); |
144 | 72 | btrfs_free_path(path);
|
145 | 73 | return ret;
|
146 | 74 | }
|
147 | 75 |
|
148 |
| -int btrfs_xattr_set(struct inode *inode, int name_index, |
149 |
| - const char *attr_name, const void *value, size_t size, |
150 |
| - int flags) |
| 76 | +int __btrfs_setxattr(struct inode *inode, const char *name, |
| 77 | + const void *value, size_t size, int flags) |
151 | 78 | {
|
152 | 79 | struct btrfs_dir_item *di;
|
153 | 80 | struct btrfs_root *root = BTRFS_I(inode)->root;
|
154 | 81 | struct btrfs_trans_handle *trans;
|
155 | 82 | struct btrfs_path *path;
|
156 |
| - struct xattr_handler *handler = btrfs_xattr_handler(name_index); |
157 |
| - char *name; |
158 | 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 | 85 | path = btrfs_alloc_path();
|
166 |
| - if (!path) { |
167 |
| - kfree(name); |
| 86 | + if (!path) |
168 | 87 | return -ENOMEM;
|
169 |
| - } |
170 | 88 |
|
171 | 89 | trans = btrfs_start_transaction(root, 1);
|
172 | 90 | btrfs_set_trans_block_group(trans, inode);
|
@@ -221,9 +139,7 @@ int btrfs_xattr_set(struct inode *inode, int name_index,
|
221 | 139 | }
|
222 | 140 |
|
223 | 141 | btrfs_end_transaction(trans, root);
|
224 |
| - kfree(name); |
225 | 142 | btrfs_free_path(path);
|
226 |
| - |
227 | 143 | return ret;
|
228 | 144 | }
|
229 | 145 |
|
@@ -329,51 +245,77 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
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 | + */ |
| 251 | +struct 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) \ |
335 |
| -static int btrfs_xattr_##name##_get(struct inode *inode, \ |
336 |
| - const char *name, void *value, \ |
337 |
| - size_t size) \ |
338 |
| -{ \ |
339 |
| - if (*name == '\0') \ |
340 |
| - return -EINVAL; \ |
341 |
| - return btrfs_xattr_get(inode, index, name, value, size); \ |
342 |
| -} \ |
343 |
| -static 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); \ |
| 265 | +static bool btrfs_is_valid_xattr(const char *name) |
| 266 | +{ |
| 267 | + return !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) || |
| 268 | + !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || |
| 269 | + !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || |
| 270 | + !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); |
350 | 271 | }
|
351 | 272 |
|
352 |
| -BTRFS_XATTR_SETGET_FUNCS(security, BTRFS_XATTR_INDEX_SECURITY); |
353 |
| -BTRFS_XATTR_SETGET_FUNCS(system, BTRFS_XATTR_INDEX_SYSTEM); |
354 |
| -BTRFS_XATTR_SETGET_FUNCS(user, BTRFS_XATTR_INDEX_USER); |
355 |
| -BTRFS_XATTR_SETGET_FUNCS(trusted, BTRFS_XATTR_INDEX_TRUSTED); |
| 273 | +ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, |
| 274 | + void *buffer, size_t size) |
| 275 | +{ |
| 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 |
|
357 |
| -struct xattr_handler btrfs_xattr_security_handler = { |
358 |
| - .prefix = XATTR_SECURITY_PREFIX, |
359 |
| - .get = btrfs_xattr_security_get, |
360 |
| - .set = btrfs_xattr_security_set, |
361 |
| -}; |
| 284 | + if (!btrfs_is_valid_xattr(name)) |
| 285 | + return -EOPNOTSUPP; |
| 286 | + return __btrfs_getxattr(dentry->d_inode, name, buffer, size); |
| 287 | +} |
362 | 288 |
|
363 |
| -struct xattr_handler btrfs_xattr_system_handler = { |
364 |
| - .prefix = XATTR_SYSTEM_PREFIX, |
365 |
| - .get = btrfs_xattr_system_get, |
366 |
| - .set = btrfs_xattr_system_set, |
367 |
| -}; |
| 289 | +int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
| 290 | + size_t size, int flags) |
| 291 | +{ |
| 292 | + /* |
| 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 |
|
369 |
| -struct xattr_handler btrfs_xattr_user_handler = { |
370 |
| - .prefix = XATTR_USER_PREFIX, |
371 |
| - .get = btrfs_xattr_user_get, |
372 |
| - .set = btrfs_xattr_user_set, |
373 |
| -}; |
| 300 | + if (!btrfs_is_valid_xattr(name)) |
| 301 | + return -EOPNOTSUPP; |
374 | 302 |
|
375 |
| -struct xattr_handler btrfs_xattr_trusted_handler = { |
376 |
| - .prefix = XATTR_TRUSTED_PREFIX, |
377 |
| - .get = btrfs_xattr_trusted_get, |
378 |
| - .set = btrfs_xattr_trusted_set, |
379 |
| -}; |
| 303 | + if (size == 0) |
| 304 | + value = ""; /* empty EA, do not remove */ |
| 305 | + return __btrfs_setxattr(dentry->d_inode, name, value, size, flags); |
| 306 | +} |
| 307 | + |
| 308 | +int 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 | +} |
0 commit comments