|
|
@@ -1011,6 +1011,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
|
|
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
|
|
struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
|
|
|
struct ceph_cap_flush *prealloc_cf = NULL;
|
|
|
+ struct ceph_buffer *old_blob = NULL;
|
|
|
int issued;
|
|
|
int err;
|
|
|
int dirty = 0;
|
|
|
@@ -1084,13 +1085,15 @@ retry:
|
|
|
struct ceph_buffer *blob;
|
|
|
|
|
|
spin_unlock(&ci->i_ceph_lock);
|
|
|
- dout(" preaallocating new blob size=%d\n", required_blob_size);
|
|
|
+ ceph_buffer_put(old_blob); /* Shouldn't be required */
|
|
|
+ dout(" pre-allocating new blob size=%d\n", required_blob_size);
|
|
|
blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
|
|
|
if (!blob)
|
|
|
goto do_sync_unlocked;
|
|
|
spin_lock(&ci->i_ceph_lock);
|
|
|
+ /* prealloc_blob can't be released while holding i_ceph_lock */
|
|
|
if (ci->i_xattrs.prealloc_blob)
|
|
|
- ceph_buffer_put(ci->i_xattrs.prealloc_blob);
|
|
|
+ old_blob = ci->i_xattrs.prealloc_blob;
|
|
|
ci->i_xattrs.prealloc_blob = blob;
|
|
|
goto retry;
|
|
|
}
|
|
|
@@ -1106,6 +1109,7 @@ retry:
|
|
|
}
|
|
|
|
|
|
spin_unlock(&ci->i_ceph_lock);
|
|
|
+ ceph_buffer_put(old_blob);
|
|
|
if (lock_snap_rwsem)
|
|
|
up_read(&mdsc->snap_rwsem);
|
|
|
if (dirty)
|