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>
This commit is contained in:
Yan, Zheng 2014-02-11 13:01:19 +08:00 committed by Sage Weil
parent 0ec1d15ec6
commit fbc0b970dd
1 changed files with 26 additions and 12 deletions

View File

@ -319,8 +319,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode,
static int __set_xattr(struct ceph_inode_info *ci,
const char *name, int name_len,
const char *val, int val_len,
int dirty,
int should_free_name, int should_free_val,
int flags, int update_xattr,
struct ceph_inode_xattr **newxattr)
{
struct rb_node **p;
@ -349,12 +348,25 @@ static int __set_xattr(struct ceph_inode_info *ci,
xattr = NULL;
}
if (update_xattr) {
int err = 0;
if (xattr && (flags & XATTR_CREATE))
err = -EEXIST;
else if (!xattr && (flags & XATTR_REPLACE))
err = -ENODATA;
if (err) {
kfree(name);
kfree(val);
return err;
}
}
if (!xattr) {
new = 1;
xattr = *newxattr;
xattr->name = name;
xattr->name_len = name_len;
xattr->should_free_name = should_free_name;
xattr->should_free_name = update_xattr;
ci->i_xattrs.count++;
dout("__set_xattr count=%d\n", ci->i_xattrs.count);
@ -364,7 +376,7 @@ static int __set_xattr(struct ceph_inode_info *ci,
if (xattr->should_free_val)
kfree((void *)xattr->val);
if (should_free_name) {
if (update_xattr) {
kfree((void *)name);
name = xattr->name;
}
@ -379,8 +391,8 @@ static int __set_xattr(struct ceph_inode_info *ci,
xattr->val = "";
xattr->val_len = val_len;
xattr->dirty = dirty;
xattr->should_free_val = (val && should_free_val);
xattr->dirty = update_xattr;
xattr->should_free_val = (val && update_xattr);
if (new) {
rb_link_node(&xattr->node, parent, p);
@ -588,7 +600,7 @@ start:
p += len;
err = __set_xattr(ci, name, namelen, val, len,
0, 0, 0, &xattrs[numattr]);
0, 0, &xattrs[numattr]);
if (err < 0)
goto bad;
@ -892,7 +904,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name,
struct ceph_inode_info *ci = ceph_inode(inode);
int issued;
int err;
int dirty;
int dirty = 0;
int name_len = strlen(name);
int val_len = size;
char *newname = NULL;
@ -954,11 +966,13 @@ retry:
}
err = __set_xattr(ci, newname, name_len, newval,
val_len, 1, 1, 1, &xattr);
val_len, flags, 1, &xattr);
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
ci->i_xattrs.dirty = true;
inode->i_ctime = CURRENT_TIME;
if (!err) {
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
ci->i_xattrs.dirty = true;
inode->i_ctime = CURRENT_TIME;
}
spin_unlock(&ci->i_ceph_lock);
if (dirty)