aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorJeff Layton <jlayton@kernel.org>2019-04-11 15:27:03 -0400
committerIlya Dryomov <idryomov@gmail.com>2019-05-07 13:22:37 -0400
commit428bb68ad99b9f03c35d7b34d60be54faf954181 (patch)
tree407595528606e046f860f73bdfd0b3d88a935b15 /fs/ceph
parentffb61c55b2501c3dcd266856e25430ae8e3753d6 (diff)
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/39258 Signed-off-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: "Yan, Zheng" <zyan@redhat.com> Reviewed-by: David Howells <dhowells@redhat.com> Reviewed-by: Sage Weil <sage@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/inode.c85
1 files changed, 57 insertions, 28 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index c2feb310ac1e..cf50d835b93f 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -2269,43 +2269,72 @@ int ceph_permission(struct inode *inode, int mask)
2269 return err; 2269 return err;
2270} 2270}
2271 2271
2272/* Craft a mask of needed caps given a set of requested statx attrs. */
2273static int statx_to_caps(u32 want)
2274{
2275 int mask = 0;
2276
2277 if (want & (STATX_MODE|STATX_UID|STATX_GID|STATX_CTIME))
2278 mask |= CEPH_CAP_AUTH_SHARED;
2279
2280 if (want & (STATX_NLINK|STATX_CTIME))
2281 mask |= CEPH_CAP_LINK_SHARED;
2282
2283 if (want & (STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_SIZE|
2284 STATX_BLOCKS))
2285 mask |= CEPH_CAP_FILE_SHARED;
2286
2287 if (want & (STATX_CTIME))
2288 mask |= CEPH_CAP_XATTR_SHARED;
2289
2290 return mask;
2291}
2292
2272/* 2293/*
2273 * Get all attributes. Hopefully somedata we'll have a statlite() 2294 * Get all the attributes. If we have sufficient caps for the requested attrs,
2274 * and can limit the fields we require to be accurate. 2295 * then we can avoid talking to the MDS at all.
2275 */ 2296 */
2276int ceph_getattr(const struct path *path, struct kstat *stat, 2297int ceph_getattr(const struct path *path, struct kstat *stat,
2277 u32 request_mask, unsigned int flags) 2298 u32 request_mask, unsigned int flags)
2278{ 2299{
2279 struct inode *inode = d_inode(path->dentry); 2300 struct inode *inode = d_inode(path->dentry);
2280 struct ceph_inode_info *ci = ceph_inode(inode); 2301 struct ceph_inode_info *ci = ceph_inode(inode);
2281 int err; 2302 int err = 0;
2282 2303
2283 err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL, false); 2304 /* Skip the getattr altogether if we're asked not to sync */
2284 if (!err) { 2305 if (!(flags & AT_STATX_DONT_SYNC)) {
2285 generic_fillattr(inode, stat); 2306 err = ceph_do_getattr(inode, statx_to_caps(request_mask),
2286 stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino); 2307 flags & AT_STATX_FORCE_SYNC);
2287 if (ceph_snap(inode) == CEPH_NOSNAP) 2308 if (err)
2288 stat->dev = inode->i_sb->s_dev; 2309 return err;
2310 }
2311
2312 generic_fillattr(inode, stat);
2313 stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino);
2314 if (ceph_snap(inode) == CEPH_NOSNAP)
2315 stat->dev = inode->i_sb->s_dev;
2316 else
2317 stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev : 0;
2318
2319 if (S_ISDIR(inode->i_mode)) {
2320 if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb),
2321 RBYTES))
2322 stat->size = ci->i_rbytes;
2289 else 2323 else
2290 stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev : 0; 2324 stat->size = ci->i_files + ci->i_subdirs;
2291 2325 stat->blocks = 0;
2292 if (S_ISDIR(inode->i_mode)) { 2326 stat->blksize = 65536;
2293 if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), 2327 /*
2294 RBYTES)) 2328 * Some applications rely on the number of st_nlink
2295 stat->size = ci->i_rbytes; 2329 * value on directories to be either 0 (if unlinked)
2296 else 2330 * or 2 + number of subdirectories.
2297 stat->size = ci->i_files + ci->i_subdirs; 2331 */
2298 stat->blocks = 0; 2332 if (stat->nlink == 1)
2299 stat->blksize = 65536; 2333 /* '.' + '..' + subdirs */
2300 /* 2334 stat->nlink = 1 + 1 + ci->i_subdirs;
2301 * Some applications rely on the number of st_nlink
2302 * value on directories to be either 0 (if unlinked)
2303 * or 2 + number of subdirectories.
2304 */
2305 if (stat->nlink == 1)
2306 /* '.' + '..' + subdirs */
2307 stat->nlink = 1 + 1 + ci->i_subdirs;
2308 }
2309 } 2335 }
2336
2337 /* Mask off any higher bits (e.g. btime) until we have support */
2338 stat->result_mask = request_mask & STATX_BASIC_STATS;
2310 return err; 2339 return err;
2311} 2340}