summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2015-12-02 08:44:37 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-12-06 21:34:14 -0500
commit9172abbcd371f2f62903087bbd228f11d380b7b4 (patch)
treec9842dcce82d638b06ccdf7d0bb1e7dda17d54b5
parent98e9cb5711c68223f0e4d5201b9a6add255ec550 (diff)
btrfs: Use xattr handler infrastructure
Use the VFS xattr handler infrastructure and get rid of similar code in the filesystem. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/btrfs/inode.c8
-rw-r--r--fs/btrfs/xattr.c166
-rw-r--r--fs/btrfs/xattr.h2
3 files changed, 63 insertions, 113 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index d540fd70f6c6..4fb8d6e28b21 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -9994,7 +9994,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
9994 .setattr = btrfs_setattr, 9994 .setattr = btrfs_setattr,
9995 .mknod = btrfs_mknod, 9995 .mknod = btrfs_mknod,
9996 .setxattr = btrfs_setxattr, 9996 .setxattr = btrfs_setxattr,
9997 .getxattr = btrfs_getxattr, 9997 .getxattr = generic_getxattr,
9998 .listxattr = btrfs_listxattr, 9998 .listxattr = btrfs_listxattr,
9999 .removexattr = btrfs_removexattr, 9999 .removexattr = btrfs_removexattr,
10000 .permission = btrfs_permission, 10000 .permission = btrfs_permission,
@@ -10071,7 +10071,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
10071 .getattr = btrfs_getattr, 10071 .getattr = btrfs_getattr,
10072 .setattr = btrfs_setattr, 10072 .setattr = btrfs_setattr,
10073 .setxattr = btrfs_setxattr, 10073 .setxattr = btrfs_setxattr,
10074 .getxattr = btrfs_getxattr, 10074 .getxattr = generic_getxattr,
10075 .listxattr = btrfs_listxattr, 10075 .listxattr = btrfs_listxattr,
10076 .removexattr = btrfs_removexattr, 10076 .removexattr = btrfs_removexattr,
10077 .permission = btrfs_permission, 10077 .permission = btrfs_permission,
@@ -10085,7 +10085,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
10085 .setattr = btrfs_setattr, 10085 .setattr = btrfs_setattr,
10086 .permission = btrfs_permission, 10086 .permission = btrfs_permission,
10087 .setxattr = btrfs_setxattr, 10087 .setxattr = btrfs_setxattr,
10088 .getxattr = btrfs_getxattr, 10088 .getxattr = generic_getxattr,
10089 .listxattr = btrfs_listxattr, 10089 .listxattr = btrfs_listxattr,
10090 .removexattr = btrfs_removexattr, 10090 .removexattr = btrfs_removexattr,
10091 .get_acl = btrfs_get_acl, 10091 .get_acl = btrfs_get_acl,
@@ -10100,7 +10100,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
10100 .setattr = btrfs_setattr, 10100 .setattr = btrfs_setattr,
10101 .permission = btrfs_permission, 10101 .permission = btrfs_permission,
10102 .setxattr = btrfs_setxattr, 10102 .setxattr = btrfs_setxattr,
10103 .getxattr = btrfs_getxattr, 10103 .getxattr = generic_getxattr,
10104 .listxattr = btrfs_listxattr, 10104 .listxattr = btrfs_listxattr,
10105 .removexattr = btrfs_removexattr, 10105 .removexattr = btrfs_removexattr,
10106 .update_time = btrfs_update_time, 10106 .update_time = btrfs_update_time,
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index 1fcd7b6e7564..7cbef1a14fe1 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -351,137 +351,89 @@ err:
351 return ret; 351 return ret;
352} 352}
353 353
354/* 354static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
355 * List of handlers for synthetic system.* attributes. All real ondisk 355 struct dentry *dentry, const char *name,
356 * attributes are handled directly. 356 void *buffer, size_t size)
357 */
358const struct xattr_handler *btrfs_xattr_handlers[] = {
359#ifdef CONFIG_BTRFS_FS_POSIX_ACL
360 &posix_acl_access_xattr_handler,
361 &posix_acl_default_xattr_handler,
362#endif
363 NULL,
364};
365
366/*
367 * Check if the attribute is in a supported namespace.
368 *
369 * This is applied after the check for the synthetic attributes in the system
370 * namespace.
371 */
372static int btrfs_is_valid_xattr(const char *name)
373{ 357{
374 int len = strlen(name); 358 struct inode *inode = d_inode(dentry);
375 int prefixlen = 0;
376
377 if (!strncmp(name, XATTR_SECURITY_PREFIX,
378 XATTR_SECURITY_PREFIX_LEN))
379 prefixlen = XATTR_SECURITY_PREFIX_LEN;
380 else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
381 prefixlen = XATTR_SYSTEM_PREFIX_LEN;
382 else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
383 prefixlen = XATTR_TRUSTED_PREFIX_LEN;
384 else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
385 prefixlen = XATTR_USER_PREFIX_LEN;
386 else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
387 prefixlen = XATTR_BTRFS_PREFIX_LEN;
388 else
389 return -EOPNOTSUPP;
390
391 /*
392 * The name cannot consist of just prefix
393 */
394 if (len <= prefixlen)
395 return -EINVAL;
396 359
397 return 0; 360 name = xattr_full_name(handler, name);
361 return __btrfs_getxattr(inode, name, buffer, size);
398} 362}
399 363
400ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, 364static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
401 void *buffer, size_t size) 365 struct dentry *dentry, const char *name,
366 const void *buffer, size_t size,
367 int flags)
402{ 368{
403 int ret; 369 struct inode *inode = d_inode(dentry);
404 370
405 /* 371 name = xattr_full_name(handler, name);
406 * If this is a request for a synthetic attribute in the system.* 372 return __btrfs_setxattr(NULL, inode, name, buffer, size, flags);
407 * namespace use the generic infrastructure to resolve a handler 373}
408 * for it via sb->s_xattr.
409 */
410 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
411 return generic_getxattr(dentry, name, buffer, size);
412 374
413 ret = btrfs_is_valid_xattr(name); 375static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
414 if (ret) 376 struct dentry *dentry,
415 return ret; 377 const char *name, const void *value,
416 return __btrfs_getxattr(d_inode(dentry), name, buffer, size); 378 size_t size, int flags)
379{
380 name = xattr_full_name(handler, name);
381 return btrfs_set_prop(d_inode(dentry), name, value, size, flags);
417} 382}
418 383
384static const struct xattr_handler btrfs_security_xattr_handler = {
385 .prefix = XATTR_SECURITY_PREFIX,
386 .get = btrfs_xattr_handler_get,
387 .set = btrfs_xattr_handler_set,
388};
389
390static const struct xattr_handler btrfs_trusted_xattr_handler = {
391 .prefix = XATTR_TRUSTED_PREFIX,
392 .get = btrfs_xattr_handler_get,
393 .set = btrfs_xattr_handler_set,
394};
395
396static const struct xattr_handler btrfs_user_xattr_handler = {
397 .prefix = XATTR_USER_PREFIX,
398 .get = btrfs_xattr_handler_get,
399 .set = btrfs_xattr_handler_set,
400};
401
402static const struct xattr_handler btrfs_btrfs_xattr_handler = {
403 .prefix = XATTR_BTRFS_PREFIX,
404 .get = btrfs_xattr_handler_get,
405 .set = btrfs_xattr_handler_set_prop,
406};
407
408const struct xattr_handler *btrfs_xattr_handlers[] = {
409 &btrfs_security_xattr_handler,
410#ifdef CONFIG_BTRFS_FS_POSIX_ACL
411 &posix_acl_access_xattr_handler,
412 &posix_acl_default_xattr_handler,
413#endif
414 &btrfs_trusted_xattr_handler,
415 &btrfs_user_xattr_handler,
416 &btrfs_btrfs_xattr_handler,
417 NULL,
418};
419
419int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, 420int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
420 size_t size, int flags) 421 size_t size, int flags)
421{ 422{
422 struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root; 423 struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
423 int ret;
424 424
425 /*
426 * The permission on security.* and system.* is not checked
427 * in permission().
428 */
429 if (btrfs_root_readonly(root)) 425 if (btrfs_root_readonly(root))
430 return -EROFS; 426 return -EROFS;
431 427 return generic_setxattr(dentry, name, value, size, flags);
432 /*
433 * If this is a request for a synthetic attribute in the system.*
434 * namespace use the generic infrastructure to resolve a handler
435 * for it via sb->s_xattr.
436 */
437 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
438 return generic_setxattr(dentry, name, value, size, flags);
439
440 ret = btrfs_is_valid_xattr(name);
441 if (ret)
442 return ret;
443
444 if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
445 return btrfs_set_prop(d_inode(dentry), name,
446 value, size, flags);
447
448 if (size == 0)
449 value = ""; /* empty EA, do not remove */
450
451 return __btrfs_setxattr(NULL, d_inode(dentry), name, value, size,
452 flags);
453} 428}
454 429
455int btrfs_removexattr(struct dentry *dentry, const char *name) 430int btrfs_removexattr(struct dentry *dentry, const char *name)
456{ 431{
457 struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root; 432 struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
458 int ret;
459 433
460 /*
461 * The permission on security.* and system.* is not checked
462 * in permission().
463 */
464 if (btrfs_root_readonly(root)) 434 if (btrfs_root_readonly(root))
465 return -EROFS; 435 return -EROFS;
466 436 return generic_removexattr(dentry, name);
467 /*
468 * If this is a request for a synthetic attribute in the system.*
469 * namespace use the generic infrastructure to resolve a handler
470 * for it via sb->s_xattr.
471 */
472 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
473 return generic_removexattr(dentry, name);
474
475 ret = btrfs_is_valid_xattr(name);
476 if (ret)
477 return ret;
478
479 if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
480 return btrfs_set_prop(d_inode(dentry), name,
481 NULL, 0, XATTR_REPLACE);
482
483 return __btrfs_setxattr(NULL, d_inode(dentry), name, NULL, 0,
484 XATTR_REPLACE);
485} 437}
486 438
487static int btrfs_initxattrs(struct inode *inode, 439static int btrfs_initxattrs(struct inode *inode,
diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h
index 5049608d1388..96807b3d22f5 100644
--- a/fs/btrfs/xattr.h
+++ b/fs/btrfs/xattr.h
@@ -28,8 +28,6 @@ extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
28extern int __btrfs_setxattr(struct btrfs_trans_handle *trans, 28extern int __btrfs_setxattr(struct btrfs_trans_handle *trans,
29 struct inode *inode, const char *name, 29 struct inode *inode, const char *name,
30 const void *value, size_t size, int flags); 30 const void *value, size_t size, int flags);
31extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
32 void *buffer, size_t size);
33extern int btrfs_setxattr(struct dentry *dentry, const char *name, 31extern int btrfs_setxattr(struct dentry *dentry, const char *name,
34 const void *value, size_t size, int flags); 32 const void *value, size_t size, int flags);
35extern int btrfs_removexattr(struct dentry *dentry, const char *name); 33extern int btrfs_removexattr(struct dentry *dentry, const char *name);