diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2014-02-11 00:01:19 -0500 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2014-02-17 15:37:05 -0500 |
commit | fbc0b970ddfab4b35dad27ebaae712af680bdc7e (patch) | |
tree | 2120c4d11018e7090fc76158453f11d7a0939d3f /fs/ceph | |
parent | 0ec1d15ec6ed513ab2cc86c67d94761d71228a32 (diff) |
ceph: properly handle XATTR_CREATE and XATTR_REPLACE
return -EEXIST if XATTR_CREATE is set and xattr alread exists.
return -ENODATA if XATTR_REPLACE is set but xattr does not exist.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/xattr.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 898b6565ad3e..28f9793b9167 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c | |||
@@ -319,8 +319,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode, | |||
319 | static int __set_xattr(struct ceph_inode_info *ci, | 319 | static int __set_xattr(struct ceph_inode_info *ci, |
320 | const char *name, int name_len, | 320 | const char *name, int name_len, |
321 | const char *val, int val_len, | 321 | const char *val, int val_len, |
322 | int dirty, | 322 | int flags, int update_xattr, |
323 | int should_free_name, int should_free_val, | ||
324 | struct ceph_inode_xattr **newxattr) | 323 | struct ceph_inode_xattr **newxattr) |
325 | { | 324 | { |
326 | struct rb_node **p; | 325 | struct rb_node **p; |
@@ -349,12 +348,25 @@ static int __set_xattr(struct ceph_inode_info *ci, | |||
349 | xattr = NULL; | 348 | xattr = NULL; |
350 | } | 349 | } |
351 | 350 | ||
351 | if (update_xattr) { | ||
352 | int err = 0; | ||
353 | if (xattr && (flags & XATTR_CREATE)) | ||
354 | err = -EEXIST; | ||
355 | else if (!xattr && (flags & XATTR_REPLACE)) | ||
356 | err = -ENODATA; | ||
357 | if (err) { | ||
358 | kfree(name); | ||
359 | kfree(val); | ||
360 | return err; | ||
361 | } | ||
362 | } | ||
363 | |||
352 | if (!xattr) { | 364 | if (!xattr) { |
353 | new = 1; | 365 | new = 1; |
354 | xattr = *newxattr; | 366 | xattr = *newxattr; |
355 | xattr->name = name; | 367 | xattr->name = name; |
356 | xattr->name_len = name_len; | 368 | xattr->name_len = name_len; |
357 | xattr->should_free_name = should_free_name; | 369 | xattr->should_free_name = update_xattr; |
358 | 370 | ||
359 | ci->i_xattrs.count++; | 371 | ci->i_xattrs.count++; |
360 | dout("__set_xattr count=%d\n", ci->i_xattrs.count); | 372 | dout("__set_xattr count=%d\n", ci->i_xattrs.count); |
@@ -364,7 +376,7 @@ static int __set_xattr(struct ceph_inode_info *ci, | |||
364 | if (xattr->should_free_val) | 376 | if (xattr->should_free_val) |
365 | kfree((void *)xattr->val); | 377 | kfree((void *)xattr->val); |
366 | 378 | ||
367 | if (should_free_name) { | 379 | if (update_xattr) { |
368 | kfree((void *)name); | 380 | kfree((void *)name); |
369 | name = xattr->name; | 381 | name = xattr->name; |
370 | } | 382 | } |
@@ -379,8 +391,8 @@ static int __set_xattr(struct ceph_inode_info *ci, | |||
379 | xattr->val = ""; | 391 | xattr->val = ""; |
380 | 392 | ||
381 | xattr->val_len = val_len; | 393 | xattr->val_len = val_len; |
382 | xattr->dirty = dirty; | 394 | xattr->dirty = update_xattr; |
383 | xattr->should_free_val = (val && should_free_val); | 395 | xattr->should_free_val = (val && update_xattr); |
384 | 396 | ||
385 | if (new) { | 397 | if (new) { |
386 | rb_link_node(&xattr->node, parent, p); | 398 | rb_link_node(&xattr->node, parent, p); |
@@ -588,7 +600,7 @@ start: | |||
588 | p += len; | 600 | p += len; |
589 | 601 | ||
590 | err = __set_xattr(ci, name, namelen, val, len, | 602 | err = __set_xattr(ci, name, namelen, val, len, |
591 | 0, 0, 0, &xattrs[numattr]); | 603 | 0, 0, &xattrs[numattr]); |
592 | 604 | ||
593 | if (err < 0) | 605 | if (err < 0) |
594 | goto bad; | 606 | goto bad; |
@@ -892,7 +904,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name, | |||
892 | struct ceph_inode_info *ci = ceph_inode(inode); | 904 | struct ceph_inode_info *ci = ceph_inode(inode); |
893 | int issued; | 905 | int issued; |
894 | int err; | 906 | int err; |
895 | int dirty; | 907 | int dirty = 0; |
896 | int name_len = strlen(name); | 908 | int name_len = strlen(name); |
897 | int val_len = size; | 909 | int val_len = size; |
898 | char *newname = NULL; | 910 | char *newname = NULL; |
@@ -954,11 +966,13 @@ retry: | |||
954 | } | 966 | } |
955 | 967 | ||
956 | err = __set_xattr(ci, newname, name_len, newval, | 968 | err = __set_xattr(ci, newname, name_len, newval, |
957 | val_len, 1, 1, 1, &xattr); | 969 | val_len, flags, 1, &xattr); |
958 | 970 | ||
959 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); | 971 | if (!err) { |
960 | ci->i_xattrs.dirty = true; | 972 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); |
961 | inode->i_ctime = CURRENT_TIME; | 973 | ci->i_xattrs.dirty = true; |
974 | inode->i_ctime = CURRENT_TIME; | ||
975 | } | ||
962 | 976 | ||
963 | spin_unlock(&ci->i_ceph_lock); | 977 | spin_unlock(&ci->i_ceph_lock); |
964 | if (dirty) | 978 | if (dirty) |