diff options
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r-- | fs/ceph/inode.c | 85 |
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. */ | ||
2270 | static 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 | */ |
2273 | int ceph_getattr(const struct path *path, struct kstat *stat, | 2294 | int 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 | } |