aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph/inode.c')
-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 35dae6d5493a..f85355bf49c4 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -2266,43 +2266,72 @@ int ceph_permission(struct inode *inode, int mask)
2266 return err; 2266 return err;
2267} 2267}
2268 2268
2269/* Craft a mask of needed caps given a set of requested statx attrs. */
2270static int statx_to_caps(u32 want)
2271{
2272 int mask = 0;
2273
2274 if (want & (STATX_MODE|STATX_UID|STATX_GID|STATX_CTIME))
2275 mask |= CEPH_CAP_AUTH_SHARED;
2276
2277 if (want & (STATX_NLINK|STATX_CTIME))
2278 mask |= CEPH_CAP_LINK_SHARED;
2279
2280 if (want & (STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_SIZE|
2281 STATX_BLOCKS))
2282 mask |= CEPH_CAP_FILE_SHARED;
2283
2284 if (want & (STATX_CTIME))
2285 mask |= CEPH_CAP_XATTR_SHARED;
2286
2287 return mask;
2288}
2289
2269/* 2290/*
2270 * Get all attributes. Hopefully somedata we'll have a statlite() 2291 * Get all the attributes. If we have sufficient caps for the requested attrs,
2271 * and can limit the fields we require to be accurate. 2292 * then we can avoid talking to the MDS at all.
2272 */ 2293 */
2273int ceph_getattr(const struct path *path, struct kstat *stat, 2294int ceph_getattr(const struct path *path, struct kstat *stat,
2274 u32 request_mask, unsigned int flags) 2295 u32 request_mask, unsigned int flags)
2275{ 2296{
2276 struct inode *inode = d_inode(path->dentry); 2297 struct inode *inode = d_inode(path->dentry);
2277 struct ceph_inode_info *ci = ceph_inode(inode); 2298 struct ceph_inode_info *ci = ceph_inode(inode);
2278 int err; 2299 int err = 0;
2279 2300
2280 err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL, false); 2301 /* Skip the getattr altogether if we're asked not to sync */
2281 if (!err) { 2302 if (!(flags & AT_STATX_DONT_SYNC)) {
2282 generic_fillattr(inode, stat); 2303 err = ceph_do_getattr(inode, statx_to_caps(request_mask),
2283 stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino); 2304 flags & AT_STATX_FORCE_SYNC);
2284 if (ceph_snap(inode) == CEPH_NOSNAP) 2305 if (err)
2285 stat->dev = inode->i_sb->s_dev; 2306 return err;
2307 }
2308
2309 generic_fillattr(inode, stat);
2310 stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino);
2311 if (ceph_snap(inode) == CEPH_NOSNAP)
2312 stat->dev = inode->i_sb->s_dev;
2313 else
2314 stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev : 0;
2315
2316 if (S_ISDIR(inode->i_mode)) {
2317 if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb),
2318 RBYTES))
2319 stat->size = ci->i_rbytes;
2286 else 2320 else
2287 stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev : 0; 2321 stat->size = ci->i_files + ci->i_subdirs;
2288 2322 stat->blocks = 0;
2289 if (S_ISDIR(inode->i_mode)) { 2323 stat->blksize = 65536;
2290 if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), 2324 /*
2291 RBYTES)) 2325 * Some applications rely on the number of st_nlink
2292 stat->size = ci->i_rbytes; 2326 * value on directories to be either 0 (if unlinked)
2293 else 2327 * or 2 + number of subdirectories.
2294 stat->size = ci->i_files + ci->i_subdirs; 2328 */
2295 stat->blocks = 0; 2329 if (stat->nlink == 1)
2296 stat->blksize = 65536; 2330 /* '.' + '..' + subdirs */
2297 /* 2331 stat->nlink = 1 + 1 + ci->i_subdirs;
2298 * Some applications rely on the number of st_nlink
2299 * value on directories to be either 0 (if unlinked)
2300 * or 2 + number of subdirectories.
2301 */
2302 if (stat->nlink == 1)
2303 /* '.' + '..' + subdirs */
2304 stat->nlink = 1 + 1 + ci->i_subdirs;
2305 }
2306 } 2332 }
2333
2334 /* Mask off any higher bits (e.g. btime) until we have support */
2335 stat->result_mask = request_mask & STATX_BASIC_STATS;
2307 return err; 2336 return err;
2308} 2337}