diff options
author | Xiubo Li <xiubli@redhat.com> | 2022-08-31 12:13:28 +0800 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2022-10-04 19:18:08 +0200 |
commit | aa87052dd965a6094355fcc13d5abc3f5bebfbe4 (patch) | |
tree | 7e39eb55593ab7a5d55884b9b09ec7817d6a97b2 /fs | |
parent | bd04b9192e1ff6859d6b3906e91cfd5c9b0ad55b (diff) | |
download | linux-stable-aa87052dd965a6094355fcc13d5abc3f5bebfbe4.tar.gz linux-stable-aa87052dd965a6094355fcc13d5abc3f5bebfbe4.tar.bz2 linux-stable-aa87052dd965a6094355fcc13d5abc3f5bebfbe4.zip |
ceph: fix incorrectly showing the .snap size for stat
We should set the 'stat->size' to the real number of snapshots for
snapdirs.
Link: https://tracker.ceph.com/issues/57342
Signed-off-by: Xiubo Li <xiubli@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/inode.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index a5e2eb5704c9..9ebb7cee7978 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -2449,6 +2449,7 @@ int ceph_getattr(struct user_namespace *mnt_userns, const struct path *path, struct kstat *stat, u32 request_mask, unsigned int flags) { struct inode *inode = d_inode(path->dentry); + struct super_block *sb = inode->i_sb; struct ceph_inode_info *ci = ceph_inode(inode); u32 valid_mask = STATX_BASIC_STATS; int err = 0; @@ -2478,16 +2479,34 @@ int ceph_getattr(struct user_namespace *mnt_userns, const struct path *path, } if (ceph_snap(inode) == CEPH_NOSNAP) - stat->dev = inode->i_sb->s_dev; + stat->dev = 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)) + if (ceph_test_mount_opt(ceph_sb_to_client(sb), RBYTES)) { stat->size = ci->i_rbytes; - else + } else if (ceph_snap(inode) == CEPH_SNAPDIR) { + struct ceph_inode_info *pci; + struct ceph_snap_realm *realm; + struct inode *parent; + + parent = ceph_lookup_inode(sb, ceph_ino(inode)); + if (!parent) + return PTR_ERR(parent); + + pci = ceph_inode(parent); + spin_lock(&pci->i_ceph_lock); + realm = pci->i_snap_realm; + if (realm) + stat->size = realm->num_snaps; + else + stat->size = 0; + spin_unlock(&pci->i_ceph_lock); + iput(parent); + } else { stat->size = ci->i_files + ci->i_subdirs; + } stat->blocks = 0; stat->blksize = 65536; /* |