forked from Minki/linux
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:
parent
0ec1d15ec6
commit
fbc0b970dd
@ -319,8 +319,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode,
|
|||||||
static int __set_xattr(struct ceph_inode_info *ci,
|
static int __set_xattr(struct ceph_inode_info *ci,
|
||||||
const char *name, int name_len,
|
const char *name, int name_len,
|
||||||
const char *val, int val_len,
|
const char *val, int val_len,
|
||||||
int dirty,
|
int flags, int update_xattr,
|
||||||
int should_free_name, int should_free_val,
|
|
||||||
struct ceph_inode_xattr **newxattr)
|
struct ceph_inode_xattr **newxattr)
|
||||||
{
|
{
|
||||||
struct rb_node **p;
|
struct rb_node **p;
|
||||||
@ -349,12 +348,25 @@ static int __set_xattr(struct ceph_inode_info *ci,
|
|||||||
xattr = NULL;
|
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) {
|
if (!xattr) {
|
||||||
new = 1;
|
new = 1;
|
||||||
xattr = *newxattr;
|
xattr = *newxattr;
|
||||||
xattr->name = name;
|
xattr->name = name;
|
||||||
xattr->name_len = name_len;
|
xattr->name_len = name_len;
|
||||||
xattr->should_free_name = should_free_name;
|
xattr->should_free_name = update_xattr;
|
||||||
|
|
||||||
ci->i_xattrs.count++;
|
ci->i_xattrs.count++;
|
||||||
dout("__set_xattr count=%d\n", 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)
|
if (xattr->should_free_val)
|
||||||
kfree((void *)xattr->val);
|
kfree((void *)xattr->val);
|
||||||
|
|
||||||
if (should_free_name) {
|
if (update_xattr) {
|
||||||
kfree((void *)name);
|
kfree((void *)name);
|
||||||
name = xattr->name;
|
name = xattr->name;
|
||||||
}
|
}
|
||||||
@ -379,8 +391,8 @@ static int __set_xattr(struct ceph_inode_info *ci,
|
|||||||
xattr->val = "";
|
xattr->val = "";
|
||||||
|
|
||||||
xattr->val_len = val_len;
|
xattr->val_len = val_len;
|
||||||
xattr->dirty = dirty;
|
xattr->dirty = update_xattr;
|
||||||
xattr->should_free_val = (val && should_free_val);
|
xattr->should_free_val = (val && update_xattr);
|
||||||
|
|
||||||
if (new) {
|
if (new) {
|
||||||
rb_link_node(&xattr->node, parent, p);
|
rb_link_node(&xattr->node, parent, p);
|
||||||
@ -588,7 +600,7 @@ start:
|
|||||||
p += len;
|
p += len;
|
||||||
|
|
||||||
err = __set_xattr(ci, name, namelen, val, len,
|
err = __set_xattr(ci, name, namelen, val, len,
|
||||||
0, 0, 0, &xattrs[numattr]);
|
0, 0, &xattrs[numattr]);
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -892,7 +904,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name,
|
|||||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||||
int issued;
|
int issued;
|
||||||
int err;
|
int err;
|
||||||
int dirty;
|
int dirty = 0;
|
||||||
int name_len = strlen(name);
|
int name_len = strlen(name);
|
||||||
int val_len = size;
|
int val_len = size;
|
||||||
char *newname = NULL;
|
char *newname = NULL;
|
||||||
@ -954,11 +966,13 @@ retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = __set_xattr(ci, newname, name_len, newval,
|
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);
|
if (!err) {
|
||||||
ci->i_xattrs.dirty = true;
|
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
|
||||||
inode->i_ctime = CURRENT_TIME;
|
ci->i_xattrs.dirty = true;
|
||||||
|
inode->i_ctime = CURRENT_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
if (dirty)
|
if (dirty)
|
||||||
|
Loading…
Reference in New Issue
Block a user