Skip to content

Commit dd02ea9

Browse files
committed
client: account for mixed quotas in statfs
In statfs, when the quota root for a dir is discovered, it uses that dir to base values for max_files and max_bytes. This can be an issue when a dir is found with only one of two potential quota fields. Take for instance, a dir with only max_files set and parent dir has only max_bytes set. During a statfs call, it will then use the max_files value for provided dir, but does not have a value for max_bytes. In this case, this behavior will cause the size of the filesystem to be displayed. Instead, find the quota root for max_files and max_bytes separately. This will allow for mixed quotas to inherit missing values from its parent. In the above example, max_files from current dir and max_bytes from parent dir will be displayed. Fixes: https://tracker.ceph.com/issues/73487 Signed-off-by: Christopher Hoffman <[email protected]>
1 parent d1afa98 commit dd02ea9

File tree

1 file changed

+9
-8
lines changed

1 file changed

+9
-8
lines changed

src/client/Client.cc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12661,9 +12661,10 @@ int Client::_statfs(Inode *in, struct statvfs *stbuf,
1266112661
// Usually quota_root will == root_ancestor, but if the mount root has no
1266212662
// quota but we can see a parent of it that does have a quota, we'll
1266312663
// respect that one instead.
12664-
InodeRef quota_root = in->quota.is_enabled() ? in : get_quota_root(in, perms);
12664+
InodeRef qr_bytes = in->quota.is_enabled(QUOTA_MAX_BYTES) ? in : get_quota_root(in, perms, QUOTA_MAX_BYTES);
12665+
InodeRef qr_files = in->quota.is_enabled(QUOTA_MAX_FILES) ? in : get_quota_root(in, perms, QUOTA_MAX_FILES);
1266512666

12666-
total_files_on_fs = quota_root->rstat.rfiles + quota_root->rstat.rsubdirs;
12667+
total_files_on_fs = qr_files->rstat.rfiles + qr_files->rstat.rsubdirs;
1266712668

1266812669
if (rval < 0) {
1266912670
ldout(cct, 1) << "underlying call to statfs returned error: "
@@ -12693,32 +12694,32 @@ int Client::_statfs(Inode *in, struct statvfs *stbuf,
1269312694

1269412695
// get_quota_root should always give us something if client quotas are
1269512696
// enabled
12696-
ceph_assert(cct->_conf.get_val<bool>("client_quota") == false || quota_root != nullptr);
12697+
ceph_assert(cct->_conf.get_val<bool>("client_quota") == false || qr_bytes != nullptr);
1269712698

1269812699
/* If bytes quota is set on a directory and conf option "client quota df"
1269912700
* is also set, available space = quota limit - used space. Else,
1270012701
* available space = total space - used space. */
12701-
if (quota_root && cct->_conf->client_quota_df && quota_root->quota.max_bytes) {
12702+
if (qr_bytes && cct->_conf->client_quota_df && qr_bytes->quota.max_bytes) {
1270212703

1270312704
// Skip the getattr if any sessions are stale, as we don't want to
1270412705
// block `df` if this client has e.g. been evicted, or if the MDS cluster
1270512706
// is unhealthy.
1270612707
if (!_any_stale_sessions()) {
12707-
int r = _getattr(quota_root, 0, perms, true);
12708+
int r = _getattr(qr_bytes, 0, perms, true);
1270812709
if (r != 0) {
1270912710
// Ignore return value: error getting latest inode metadata is not a good
1271012711
// reason to break "df".
1271112712
lderr(cct) << "Error in getattr on quota root 0x"
12712-
<< std::hex << quota_root->ino << std::dec
12713+
<< std::hex << qr_bytes->ino << std::dec
1271312714
<< " statfs result may be outdated" << dendl;
1271412715
}
1271512716
}
1271612717

1271712718
// Special case: if there is a size quota set on the Inode acting
1271812719
// as the root for this client mount, then report the quota status
1271912720
// as the filesystem statistics.
12720-
const fsblkcnt_t total = quota_root->quota.max_bytes >> CEPH_BLOCK_SHIFT;
12721-
const fsblkcnt_t used = quota_root->rstat.rbytes >> CEPH_BLOCK_SHIFT;
12721+
const fsblkcnt_t total = qr_bytes->quota.max_bytes >> CEPH_BLOCK_SHIFT;
12722+
const fsblkcnt_t used = qr_bytes->rstat.rbytes >> CEPH_BLOCK_SHIFT;
1272212723
// It is possible for a quota to be exceeded: arithmetic here must
1272312724
// handle case where used > total.
1272412725
const fsblkcnt_t free = total > used ? total - used : 0;

0 commit comments

Comments
 (0)