diff options
Diffstat (limited to 'fs/ceph/xattr.c')
| -rw-r--r-- | fs/ceph/xattr.c | 54 |
1 files changed, 40 insertions, 14 deletions
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 898b6565ad3e..a55ec37378c6 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c | |||
| @@ -12,6 +12,9 @@ | |||
| 12 | #define XATTR_CEPH_PREFIX "ceph." | 12 | #define XATTR_CEPH_PREFIX "ceph." |
| 13 | #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1) | 13 | #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1) |
| 14 | 14 | ||
| 15 | static int __remove_xattr(struct ceph_inode_info *ci, | ||
| 16 | struct ceph_inode_xattr *xattr); | ||
| 17 | |||
| 15 | /* | 18 | /* |
| 16 | * List of handlers for synthetic system.* attributes. Other | 19 | * List of handlers for synthetic system.* attributes. Other |
| 17 | * attributes are handled directly. | 20 | * attributes are handled directly. |
| @@ -319,8 +322,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode, | |||
| 319 | static int __set_xattr(struct ceph_inode_info *ci, | 322 | static int __set_xattr(struct ceph_inode_info *ci, |
| 320 | const char *name, int name_len, | 323 | const char *name, int name_len, |
| 321 | const char *val, int val_len, | 324 | const char *val, int val_len, |
| 322 | int dirty, | 325 | int flags, int update_xattr, |
| 323 | int should_free_name, int should_free_val, | ||
| 324 | struct ceph_inode_xattr **newxattr) | 326 | struct ceph_inode_xattr **newxattr) |
| 325 | { | 327 | { |
| 326 | struct rb_node **p; | 328 | struct rb_node **p; |
| @@ -349,12 +351,31 @@ static int __set_xattr(struct ceph_inode_info *ci, | |||
| 349 | xattr = NULL; | 351 | xattr = NULL; |
| 350 | } | 352 | } |
| 351 | 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 | |||
| 352 | if (!xattr) { | 373 | if (!xattr) { |
| 353 | new = 1; | 374 | new = 1; |
| 354 | xattr = *newxattr; | 375 | xattr = *newxattr; |
| 355 | xattr->name = name; | 376 | xattr->name = name; |
| 356 | xattr->name_len = name_len; | 377 | xattr->name_len = name_len; |
| 357 | xattr->should_free_name = should_free_name; | 378 | xattr->should_free_name = update_xattr; |
| 358 | 379 | ||
| 359 | ci->i_xattrs.count++; | 380 | ci->i_xattrs.count++; |
| 360 | dout("__set_xattr count=%d\n", ci->i_xattrs.count); | 381 | dout("__set_xattr count=%d\n", ci->i_xattrs.count); |
| @@ -364,7 +385,7 @@ static int __set_xattr(struct ceph_inode_info *ci, | |||
| 364 | if (xattr->should_free_val) | 385 | if (xattr->should_free_val) |
| 365 | kfree((void *)xattr->val); | 386 | kfree((void *)xattr->val); |
| 366 | 387 | ||
| 367 | if (should_free_name) { | 388 | if (update_xattr) { |
| 368 | kfree((void *)name); | 389 | kfree((void *)name); |
| 369 | name = xattr->name; | 390 | name = xattr->name; |
| 370 | } | 391 | } |
| @@ -379,8 +400,8 @@ static int __set_xattr(struct ceph_inode_info *ci, | |||
| 379 | xattr->val = ""; | 400 | xattr->val = ""; |
| 380 | 401 | ||
| 381 | xattr->val_len = val_len; | 402 | xattr->val_len = val_len; |
| 382 | xattr->dirty = dirty; | 403 | xattr->dirty = update_xattr; |
| 383 | xattr->should_free_val = (val && should_free_val); | 404 | xattr->should_free_val = (val && update_xattr); |
| 384 | 405 | ||
| 385 | if (new) { | 406 | if (new) { |
| 386 | rb_link_node(&xattr->node, parent, p); | 407 | rb_link_node(&xattr->node, parent, p); |
| @@ -442,7 +463,7 @@ static int __remove_xattr(struct ceph_inode_info *ci, | |||
| 442 | struct ceph_inode_xattr *xattr) | 463 | struct ceph_inode_xattr *xattr) |
| 443 | { | 464 | { |
| 444 | if (!xattr) | 465 | if (!xattr) |
| 445 | return -EOPNOTSUPP; | 466 | return -ENODATA; |
| 446 | 467 | ||
| 447 | rb_erase(&xattr->node, &ci->i_xattrs.index); | 468 | rb_erase(&xattr->node, &ci->i_xattrs.index); |
| 448 | 469 | ||
| @@ -588,7 +609,7 @@ start: | |||
| 588 | p += len; | 609 | p += len; |
| 589 | 610 | ||
| 590 | err = __set_xattr(ci, name, namelen, val, len, | 611 | err = __set_xattr(ci, name, namelen, val, len, |
| 591 | 0, 0, 0, &xattrs[numattr]); | 612 | 0, 0, &xattrs[numattr]); |
| 592 | 613 | ||
| 593 | if (err < 0) | 614 | if (err < 0) |
| 594 | goto bad; | 615 | goto bad; |
| @@ -850,6 +871,9 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name, | |||
| 850 | 871 | ||
| 851 | dout("setxattr value=%.*s\n", (int)size, value); | 872 | dout("setxattr value=%.*s\n", (int)size, value); |
| 852 | 873 | ||
| 874 | if (!value) | ||
| 875 | flags |= CEPH_XATTR_REMOVE; | ||
| 876 | |||
| 853 | /* do request */ | 877 | /* do request */ |
| 854 | req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR, | 878 | req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR, |
| 855 | USE_AUTH_MDS); | 879 | USE_AUTH_MDS); |
| @@ -892,7 +916,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name, | |||
| 892 | struct ceph_inode_info *ci = ceph_inode(inode); | 916 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 893 | int issued; | 917 | int issued; |
| 894 | int err; | 918 | int err; |
| 895 | int dirty; | 919 | int dirty = 0; |
| 896 | int name_len = strlen(name); | 920 | int name_len = strlen(name); |
| 897 | int val_len = size; | 921 | int val_len = size; |
| 898 | char *newname = NULL; | 922 | char *newname = NULL; |
| @@ -953,12 +977,14 @@ retry: | |||
| 953 | goto retry; | 977 | goto retry; |
| 954 | } | 978 | } |
| 955 | 979 | ||
| 956 | err = __set_xattr(ci, newname, name_len, newval, | 980 | err = __set_xattr(ci, newname, name_len, newval, val_len, |
| 957 | val_len, 1, 1, 1, &xattr); | 981 | flags, value ? 1 : -1, &xattr); |
| 958 | 982 | ||
| 959 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); | 983 | if (!err) { |
| 960 | ci->i_xattrs.dirty = true; | 984 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); |
| 961 | inode->i_ctime = CURRENT_TIME; | 985 | ci->i_xattrs.dirty = true; |
| 986 | inode->i_ctime = CURRENT_TIME; | ||
| 987 | } | ||
| 962 | 988 | ||
| 963 | spin_unlock(&ci->i_ceph_lock); | 989 | spin_unlock(&ci->i_ceph_lock); |
| 964 | if (dirty) | 990 | if (dirty) |
