提交 428bb68a 编写于 作者: J Jeff Layton 提交者: Ilya Dryomov

ceph: properly handle granular statx requests

cephfs can benefit from statx. We can have the client just request caps
sufficient for the needed attributes and leave off the rest.

Also, recognize when AT_STATX_DONT_SYNC is set, and just scrape the
inode without doing any call in that case. Force a call to the MDS in
the event that AT_STATX_FORCE_SYNC is set.

Link: http://tracker.ceph.com/issues/39258Signed-off-by: NJeff Layton <jlayton@kernel.org>
Reviewed-by: N"Yan, Zheng" <zyan@redhat.com>
Reviewed-by: NDavid Howells <dhowells@redhat.com>
Reviewed-by: NSage Weil <sage@redhat.com>
Signed-off-by: NIlya Dryomov <idryomov@gmail.com>
上级 ffb61c55
...@@ -2269,43 +2269,72 @@ int ceph_permission(struct inode *inode, int mask) ...@@ -2269,43 +2269,72 @@ int ceph_permission(struct inode *inode, int mask)
return err; return err;
} }
/* Craft a mask of needed caps given a set of requested statx attrs. */
static int statx_to_caps(u32 want)
{
int mask = 0;
if (want & (STATX_MODE|STATX_UID|STATX_GID|STATX_CTIME))
mask |= CEPH_CAP_AUTH_SHARED;
if (want & (STATX_NLINK|STATX_CTIME))
mask |= CEPH_CAP_LINK_SHARED;
if (want & (STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_SIZE|
STATX_BLOCKS))
mask |= CEPH_CAP_FILE_SHARED;
if (want & (STATX_CTIME))
mask |= CEPH_CAP_XATTR_SHARED;
return mask;
}
/* /*
* Get all attributes. Hopefully somedata we'll have a statlite() * Get all the attributes. If we have sufficient caps for the requested attrs,
* and can limit the fields we require to be accurate. * then we can avoid talking to the MDS at all.
*/ */
int ceph_getattr(const struct path *path, struct kstat *stat, int ceph_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags) u32 request_mask, unsigned int flags)
{ {
struct inode *inode = d_inode(path->dentry); struct inode *inode = d_inode(path->dentry);
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
int err; int err = 0;
err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL, false); /* Skip the getattr altogether if we're asked not to sync */
if (!err) { if (!(flags & AT_STATX_DONT_SYNC)) {
generic_fillattr(inode, stat); err = ceph_do_getattr(inode, statx_to_caps(request_mask),
stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino); flags & AT_STATX_FORCE_SYNC);
if (ceph_snap(inode) == CEPH_NOSNAP) if (err)
stat->dev = inode->i_sb->s_dev; return err;
}
generic_fillattr(inode, stat);
stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino);
if (ceph_snap(inode) == CEPH_NOSNAP)
stat->dev = inode->i_sb->s_dev;
else
stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev : 0;
if (S_ISDIR(inode->i_mode)) {
if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb),
RBYTES))
stat->size = ci->i_rbytes;
else else
stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev : 0; stat->size = ci->i_files + ci->i_subdirs;
stat->blocks = 0;
if (S_ISDIR(inode->i_mode)) { stat->blksize = 65536;
if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), /*
RBYTES)) * Some applications rely on the number of st_nlink
stat->size = ci->i_rbytes; * value on directories to be either 0 (if unlinked)
else * or 2 + number of subdirectories.
stat->size = ci->i_files + ci->i_subdirs; */
stat->blocks = 0; if (stat->nlink == 1)
stat->blksize = 65536; /* '.' + '..' + subdirs */
/* stat->nlink = 1 + 1 + ci->i_subdirs;
* Some applications rely on the number of st_nlink
* value on directories to be either 0 (if unlinked)
* or 2 + number of subdirectories.
*/
if (stat->nlink == 1)
/* '.' + '..' + subdirs */
stat->nlink = 1 + 1 + ci->i_subdirs;
}
} }
/* Mask off any higher bits (e.g. btime) until we have support */
stat->result_mask = request_mask & STATX_BASIC_STATS;
return err; return err;
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册