aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/xattr.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-13 13:29:21 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-13 13:29:21 -0500
commit1a52bb0b686844021597d190e562ab55d1210104 (patch)
tree7edf13509869a6a7f1f488a679f15ff6c3057c54 /fs/ceph/xattr.c
parent8638094e956a47dbb9a25166705a91e9a0981d52 (diff)
parent83eb26af0db71f2dfe551405c55d982288fa6178 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: ceph: ensure prealloc_blob is in place when removing xattr rbd: initialize snap_rwsem in rbd_add() ceph: enable/disable dentry complete flags via mount option vfs: export symbol d_find_any_alias() ceph: always initialize the dentry in open_root_dentry() libceph: remove useless return value for osd_client __send_request() ceph: avoid iput() while holding spinlock in ceph_dir_fsync ceph: avoid useless dget/dput in encode_fh ceph: dereference pointer after checking for NULL crush: fix force for non-root TAKE ceph: remove unnecessary d_fsdata conditional checks ceph: Use kmemdup rather than duplicating its implementation Fix up conflicts in fs/ceph/super.c (d_alloc_root() failure handling vs always initialize the dentry in open_root_dentry)
Diffstat (limited to 'fs/ceph/xattr.c')
-rw-r--r--fs/ceph/xattr.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index a5e36e4488a7..857214ae8c08 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -818,6 +818,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
818 struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); 818 struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode);
819 int issued; 819 int issued;
820 int err; 820 int err;
821 int required_blob_size;
821 int dirty; 822 int dirty;
822 823
823 if (ceph_snap(inode) != CEPH_NOSNAP) 824 if (ceph_snap(inode) != CEPH_NOSNAP)
@@ -833,14 +834,34 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
833 return -EOPNOTSUPP; 834 return -EOPNOTSUPP;
834 } 835 }
835 836
837 err = -ENOMEM;
836 spin_lock(&ci->i_ceph_lock); 838 spin_lock(&ci->i_ceph_lock);
837 __build_xattrs(inode); 839 __build_xattrs(inode);
840retry:
838 issued = __ceph_caps_issued(ci, NULL); 841 issued = __ceph_caps_issued(ci, NULL);
839 dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); 842 dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued));
840 843
841 if (!(issued & CEPH_CAP_XATTR_EXCL)) 844 if (!(issued & CEPH_CAP_XATTR_EXCL))
842 goto do_sync; 845 goto do_sync;
843 846
847 required_blob_size = __get_required_blob_size(ci, 0, 0);
848
849 if (!ci->i_xattrs.prealloc_blob ||
850 required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) {
851 struct ceph_buffer *blob;
852
853 spin_unlock(&ci->i_ceph_lock);
854 dout(" preaallocating new blob size=%d\n", required_blob_size);
855 blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
856 if (!blob)
857 goto out;
858 spin_lock(&ci->i_ceph_lock);
859 if (ci->i_xattrs.prealloc_blob)
860 ceph_buffer_put(ci->i_xattrs.prealloc_blob);
861 ci->i_xattrs.prealloc_blob = blob;
862 goto retry;
863 }
864
844 err = __remove_xattr_by_name(ceph_inode(inode), name); 865 err = __remove_xattr_by_name(ceph_inode(inode), name);
845 dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); 866 dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
846 ci->i_xattrs.dirty = true; 867 ci->i_xattrs.dirty = true;
@@ -853,6 +874,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
853do_sync: 874do_sync:
854 spin_unlock(&ci->i_ceph_lock); 875 spin_unlock(&ci->i_ceph_lock);
855 err = ceph_send_removexattr(dentry, name); 876 err = ceph_send_removexattr(dentry, name);
877out:
856 return err; 878 return err;
857} 879}
858 880