mgr/volumes: fix stale bytes_used in subvolume/subvolumegroup info

SubvolumeBase.info() and Group.info() currently get bytes_used from
statx(CEPH_STATX_SIZE) on the subvolume directory.
Client::statx_to_mask() does not set CEPH_STAT_RSTAT for this mask, so
the getattr is not forced to the auth MDS. It can be served by a replica
or short-circuited from cached Fs caps, occasionally returning a stale
size (including 0) while ceph.dir.rbytes on the same directory is
already non-zero.

Read bytes_used from the ceph.dir.rbytes vxattr instead, falling back to
the statx size on cephfs.NoData. This path forces CEPH_STAT_RSTAT and is
routed to the auth MDS.

Fixes: https://tracker.ceph.com/issues/78671
Signed-off-by: Li Sheng <lishenggle@gmail.com>
This commit is contained in:
Li Sheng 2026-07-25 10:10:19 +08:00 committed by shengli
parent 165d47959c
commit db41957413
2 changed files with 22 additions and 2 deletions

View File

@ -115,7 +115,17 @@ class Group(GroupTemplate):
| cephfs.CEPH_STATX_UID | cephfs.CEPH_STATX_GID | cephfs.CEPH_STATX_MODE
| cephfs.CEPH_STATX_ATIME | cephfs.CEPH_STATX_MTIME | cephfs.CEPH_STATX_CTIME,
cephfs.AT_SYMLINK_NOFOLLOW)
usedbytes = st["size"]
# Fetch 'ceph.dir.rbytes' vxattr instead of relying on statx size
# (rstat of a dir); the getxattr path forces a getattr with the
# rstat mask which is routed to the auth MDS, whereas statx may be
# satisfied from stale cache or a replica MDS in multi-active
# setups, occasionally reporting 0.
try:
usedbytes = int(self.fs.getxattr(self.path,
'ceph.dir.rbytes'
).decode('utf-8'))
except cephfs.NoData:
usedbytes = st["size"]
try:
nsize = int(self.fs.getxattr(self.path, 'ceph.quota.max_bytes').decode('utf-8'))
except cephfs.NoData:

View File

@ -561,7 +561,17 @@ class SubvolumeBase(object):
| cephfs.CEPH_STATX_MTIME
| cephfs.CEPH_STATX_CTIME,
cephfs.AT_SYMLINK_NOFOLLOW)
usedbytes = st["size"]
# Fetch 'ceph.dir.rbytes' vxattr instead of relying on statx size
# (rstat of a dir); the getxattr path forces a getattr with the
# rstat mask which is routed to the auth MDS, whereas statx may be
# satisfied from stale cache or a replica MDS in multi-active
# setups, occasionally reporting 0.
try:
usedbytes = int(self.fs.getxattr(subvolpath,
'ceph.dir.rbytes'
).decode('utf-8'))
except cephfs.NoData:
usedbytes = st["size"]
try:
nsize = int(self.fs.getxattr(subvolpath,
'ceph.quota.max_bytes'