aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph/xattr.c')
-rw-r--r--fs/ceph/xattr.c115
1 files changed, 89 insertions, 26 deletions
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index be661d8f532a..a55ec37378c6 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -6,16 +6,33 @@
6#include <linux/ceph/decode.h> 6#include <linux/ceph/decode.h>
7 7
8#include <linux/xattr.h> 8#include <linux/xattr.h>
9#include <linux/posix_acl_xattr.h>
9#include <linux/slab.h> 10#include <linux/slab.h>
10 11
11#define XATTR_CEPH_PREFIX "ceph." 12#define XATTR_CEPH_PREFIX "ceph."
12#define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1) 13#define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1)
13 14
15static int __remove_xattr(struct ceph_inode_info *ci,
16 struct ceph_inode_xattr *xattr);
17
18/*
19 * List of handlers for synthetic system.* attributes. Other
20 * attributes are handled directly.
21 */
22const struct xattr_handler *ceph_xattr_handlers[] = {
23#ifdef CONFIG_CEPH_FS_POSIX_ACL
24 &posix_acl_access_xattr_handler,
25 &posix_acl_default_xattr_handler,
26#endif
27 NULL,
28};
29
14static bool ceph_is_valid_xattr(const char *name) 30static bool ceph_is_valid_xattr(const char *name)
15{ 31{
16 return !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) || 32 return !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) ||
17 !strncmp(name, XATTR_SECURITY_PREFIX, 33 !strncmp(name, XATTR_SECURITY_PREFIX,
18 XATTR_SECURITY_PREFIX_LEN) || 34 XATTR_SECURITY_PREFIX_LEN) ||
35 !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
19 !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || 36 !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
20 !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); 37 !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
21} 38}
@@ -305,8 +322,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode,
305static int __set_xattr(struct ceph_inode_info *ci, 322static int __set_xattr(struct ceph_inode_info *ci,
306 const char *name, int name_len, 323 const char *name, int name_len,
307 const char *val, int val_len, 324 const char *val, int val_len,
308 int dirty, 325 int flags, int update_xattr,
309 int should_free_name, int should_free_val,
310 struct ceph_inode_xattr **newxattr) 326 struct ceph_inode_xattr **newxattr)
311{ 327{
312 struct rb_node **p; 328 struct rb_node **p;
@@ -335,12 +351,31 @@ static int __set_xattr(struct ceph_inode_info *ci,
335 xattr = NULL; 351 xattr = NULL;
336 } 352 }
337 353
354 if (update_xattr) {
355 int err = 0;
356 if (xattr && (flags & XATTR_CREATE))
357 err = -EEXIST;
358 else if (!xattr && (flags & XATTR_REPLACE))
359 err = -ENODATA;
360 if (err) {
361 kfree(name);
362 kfree(val);
363 return err;
364 }
365 if (update_xattr < 0) {
366 if (xattr)
367 __remove_xattr(ci, xattr);
368 kfree(name);
369 return 0;
370 }
371 }
372
338 if (!xattr) { 373 if (!xattr) {
339 new = 1; 374 new = 1;
340 xattr = *newxattr; 375 xattr = *newxattr;
341 xattr->name = name; 376 xattr->name = name;
342 xattr->name_len = name_len; 377 xattr->name_len = name_len;
343 xattr->should_free_name = should_free_name; 378 xattr->should_free_name = update_xattr;
344 379
345 ci->i_xattrs.count++; 380 ci->i_xattrs.count++;
346 dout("__set_xattr count=%d\n", ci->i_xattrs.count); 381 dout("__set_xattr count=%d\n", ci->i_xattrs.count);
@@ -350,7 +385,7 @@ static int __set_xattr(struct ceph_inode_info *ci,
350 if (xattr->should_free_val) 385 if (xattr->should_free_val)
351 kfree((void *)xattr->val); 386 kfree((void *)xattr->val);
352 387
353 if (should_free_name) { 388 if (update_xattr) {
354 kfree((void *)name); 389 kfree((void *)name);
355 name = xattr->name; 390 name = xattr->name;
356 } 391 }
@@ -365,8 +400,8 @@ static int __set_xattr(struct ceph_inode_info *ci,
365 xattr->val = ""; 400 xattr->val = "";
366 401
367 xattr->val_len = val_len; 402 xattr->val_len = val_len;
368 xattr->dirty = dirty; 403 xattr->dirty = update_xattr;
369 xattr->should_free_val = (val && should_free_val); 404 xattr->should_free_val = (val && update_xattr);
370 405
371 if (new) { 406 if (new) {
372 rb_link_node(&xattr->node, parent, p); 407 rb_link_node(&xattr->node, parent, p);
@@ -428,7 +463,7 @@ static int __remove_xattr(struct ceph_inode_info *ci,
428 struct ceph_inode_xattr *xattr) 463 struct ceph_inode_xattr *xattr)
429{ 464{
430 if (!xattr) 465 if (!xattr)
431 return -EOPNOTSUPP; 466 return -ENODATA;
432 467
433 rb_erase(&xattr->node, &ci->i_xattrs.index); 468 rb_erase(&xattr->node, &ci->i_xattrs.index);
434 469
@@ -574,7 +609,7 @@ start:
574 p += len; 609 p += len;
575 610
576 err = __set_xattr(ci, name, namelen, val, len, 611 err = __set_xattr(ci, name, namelen, val, len,
577 0, 0, 0, &xattrs[numattr]); 612 0, 0, &xattrs[numattr]);
578 613
579 if (err < 0) 614 if (err < 0)
580 goto bad; 615 goto bad;
@@ -663,10 +698,9 @@ void __ceph_build_xattrs_blob(struct ceph_inode_info *ci)
663 } 698 }
664} 699}
665 700
666ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value, 701ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
667 size_t size) 702 size_t size)
668{ 703{
669 struct inode *inode = dentry->d_inode;
670 struct ceph_inode_info *ci = ceph_inode(inode); 704 struct ceph_inode_info *ci = ceph_inode(inode);
671 int err; 705 int err;
672 struct ceph_inode_xattr *xattr; 706 struct ceph_inode_xattr *xattr;
@@ -675,7 +709,6 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value,
675 if (!ceph_is_valid_xattr(name)) 709 if (!ceph_is_valid_xattr(name))
676 return -ENODATA; 710 return -ENODATA;
677 711
678
679 /* let's see if a virtual xattr was requested */ 712 /* let's see if a virtual xattr was requested */
680 vxattr = ceph_match_vxattr(inode, name); 713 vxattr = ceph_match_vxattr(inode, name);
681 if (vxattr && !(vxattr->exists_cb && !vxattr->exists_cb(ci))) { 714 if (vxattr && !(vxattr->exists_cb && !vxattr->exists_cb(ci))) {
@@ -725,6 +758,15 @@ out:
725 return err; 758 return err;
726} 759}
727 760
761ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value,
762 size_t size)
763{
764 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
765 return generic_getxattr(dentry, name, value, size);
766
767 return __ceph_getxattr(dentry->d_inode, name, value, size);
768}
769
728ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) 770ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
729{ 771{
730 struct inode *inode = dentry->d_inode; 772 struct inode *inode = dentry->d_inode;
@@ -829,6 +871,9 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
829 871
830 dout("setxattr value=%.*s\n", (int)size, value); 872 dout("setxattr value=%.*s\n", (int)size, value);
831 873
874 if (!value)
875 flags |= CEPH_XATTR_REMOVE;
876
832 /* do request */ 877 /* do request */
833 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR, 878 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR,
834 USE_AUTH_MDS); 879 USE_AUTH_MDS);
@@ -863,15 +908,15 @@ out:
863 return err; 908 return err;
864} 909}
865 910
866int ceph_setxattr(struct dentry *dentry, const char *name, 911int __ceph_setxattr(struct dentry *dentry, const char *name,
867 const void *value, size_t size, int flags) 912 const void *value, size_t size, int flags)
868{ 913{
869 struct inode *inode = dentry->d_inode; 914 struct inode *inode = dentry->d_inode;
870 struct ceph_vxattr *vxattr; 915 struct ceph_vxattr *vxattr;
871 struct ceph_inode_info *ci = ceph_inode(inode); 916 struct ceph_inode_info *ci = ceph_inode(inode);
872 int issued; 917 int issued;
873 int err; 918 int err;
874 int dirty; 919 int dirty = 0;
875 int name_len = strlen(name); 920 int name_len = strlen(name);
876 int val_len = size; 921 int val_len = size;
877 char *newname = NULL; 922 char *newname = NULL;
@@ -879,9 +924,6 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
879 struct ceph_inode_xattr *xattr = NULL; 924 struct ceph_inode_xattr *xattr = NULL;
880 int required_blob_size; 925 int required_blob_size;
881 926
882 if (ceph_snap(inode) != CEPH_NOSNAP)
883 return -EROFS;
884
885 if (!ceph_is_valid_xattr(name)) 927 if (!ceph_is_valid_xattr(name))
886 return -EOPNOTSUPP; 928 return -EOPNOTSUPP;
887 929
@@ -935,12 +977,14 @@ retry:
935 goto retry; 977 goto retry;
936 } 978 }
937 979
938 err = __set_xattr(ci, newname, name_len, newval, 980 err = __set_xattr(ci, newname, name_len, newval, val_len,
939 val_len, 1, 1, 1, &xattr); 981 flags, value ? 1 : -1, &xattr);
940 982
941 dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); 983 if (!err) {
942 ci->i_xattrs.dirty = true; 984 dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
943 inode->i_ctime = CURRENT_TIME; 985 ci->i_xattrs.dirty = true;
986 inode->i_ctime = CURRENT_TIME;
987 }
944 988
945 spin_unlock(&ci->i_ceph_lock); 989 spin_unlock(&ci->i_ceph_lock);
946 if (dirty) 990 if (dirty)
@@ -958,6 +1002,18 @@ out:
958 return err; 1002 return err;
959} 1003}
960 1004
1005int ceph_setxattr(struct dentry *dentry, const char *name,
1006 const void *value, size_t size, int flags)
1007{
1008 if (ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
1009 return -EROFS;
1010
1011 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
1012 return generic_setxattr(dentry, name, value, size, flags);
1013
1014 return __ceph_setxattr(dentry, name, value, size, flags);
1015}
1016
961static int ceph_send_removexattr(struct dentry *dentry, const char *name) 1017static int ceph_send_removexattr(struct dentry *dentry, const char *name)
962{ 1018{
963 struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); 1019 struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
@@ -984,7 +1040,7 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name)
984 return err; 1040 return err;
985} 1041}
986 1042
987int ceph_removexattr(struct dentry *dentry, const char *name) 1043int __ceph_removexattr(struct dentry *dentry, const char *name)
988{ 1044{
989 struct inode *inode = dentry->d_inode; 1045 struct inode *inode = dentry->d_inode;
990 struct ceph_vxattr *vxattr; 1046 struct ceph_vxattr *vxattr;
@@ -994,9 +1050,6 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
994 int required_blob_size; 1050 int required_blob_size;
995 int dirty; 1051 int dirty;
996 1052
997 if (ceph_snap(inode) != CEPH_NOSNAP)
998 return -EROFS;
999
1000 if (!ceph_is_valid_xattr(name)) 1053 if (!ceph_is_valid_xattr(name))
1001 return -EOPNOTSUPP; 1054 return -EOPNOTSUPP;
1002 1055
@@ -1053,3 +1106,13 @@ out:
1053 return err; 1106 return err;
1054} 1107}
1055 1108
1109int ceph_removexattr(struct dentry *dentry, const char *name)
1110{
1111 if (ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
1112 return -EROFS;
1113
1114 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
1115 return generic_removexattr(dentry, name);
1116
1117 return __ceph_removexattr(dentry, name);
1118}