summaryrefslogtreecommitdiff
path: root/fs/ceph/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph/xattr.c')
-rw-r--r--fs/ceph/xattr.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 537165db4519..e773be07f767 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -249,8 +249,7 @@ static ssize_t ceph_vxattrcb_dir_rbytes(struct ceph_inode_info *ci, char *val,
static ssize_t ceph_vxattrcb_dir_rctime(struct ceph_inode_info *ci, char *val,
size_t size)
{
- return ceph_fmt_xattr(val, size, "%lld.%09ld", ci->i_rctime.tv_sec,
- ci->i_rctime.tv_nsec);
+ return ceph_fmt_xattr(val, size, "%ptSp", &ci->i_rctime);
}
/* dir pin */
@@ -307,8 +306,7 @@ static bool ceph_vxattrcb_snap_btime_exists(struct ceph_inode_info *ci)
static ssize_t ceph_vxattrcb_snap_btime(struct ceph_inode_info *ci, char *val,
size_t size)
{
- return ceph_fmt_xattr(val, size, "%lld.%09ld", ci->i_snap_btime.tv_sec,
- ci->i_snap_btime.tv_nsec);
+ return ceph_fmt_xattr(val, size, "%ptSp", &ci->i_snap_btime);
}
static ssize_t ceph_vxattrcb_cluster_fsid(struct ceph_inode_info *ci,
@@ -821,15 +819,15 @@ start:
xattr_version = ci->i_xattrs.version;
spin_unlock(&ci->i_ceph_lock);
- xattrs = kcalloc(numattr, sizeof(struct ceph_inode_xattr *),
- GFP_NOFS);
+ xattrs = kzalloc_objs(struct ceph_inode_xattr *, numattr,
+ GFP_NOFS);
err = -ENOMEM;
if (!xattrs)
goto bad_lock;
for (i = 0; i < numattr; i++) {
- xattrs[i] = kmalloc(sizeof(struct ceph_inode_xattr),
- GFP_NOFS);
+ xattrs[i] = kmalloc_obj(struct ceph_inode_xattr,
+ GFP_NOFS);
if (!xattrs[i])
goto bad_lock;
}
@@ -1222,7 +1220,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
goto out;
}
- xattr = kmalloc(sizeof(struct ceph_inode_xattr), GFP_NOFS);
+ xattr = kmalloc_obj(struct ceph_inode_xattr, GFP_NOFS);
if (!xattr)
goto out;
@@ -1256,6 +1254,22 @@ retry:
ceph_vinop(inode), name, ceph_cap_string(issued));
__build_xattrs(inode);
+ /*
+ * __build_xattrs() may have released and reacquired i_ceph_lock,
+ * during which handle_cap_grant() could have replaced i_xattrs.blob
+ * with a newer MDS-provided blob and bumped i_xattrs.version. If that
+ * caused __build_xattrs() to rebuild the rb-tree from the new blob,
+ * count/names_size/vals_size may now be larger than when
+ * required_blob_size was computed above. Recompute it here so the
+ * prealloc_blob size check below reflects the current tree state.
+ */
+ required_blob_size = __get_required_blob_size(ci, name_len, val_len);
+ if (required_blob_size > mdsc->mdsmap->m_max_xattr_size) {
+ doutc(cl, "sync (size too large): %d > %llu\n",
+ required_blob_size, mdsc->mdsmap->m_max_xattr_size);
+ goto do_sync;
+ }
+
if (!ci->i_xattrs.prealloc_blob ||
required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) {
struct ceph_buffer *blob;
@@ -1296,6 +1310,7 @@ retry:
do_sync:
spin_unlock(&ci->i_ceph_lock);
+ ceph_buffer_put(old_blob);
do_sync_unlocked:
if (lock_snap_rwsem)
up_read(&mdsc->snap_rwsem);