diff options
Diffstat (limited to 'fs/ceph/xattr.c')
| -rw-r--r-- | fs/ceph/xattr.c | 33 |
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); |
