summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViacheslav Dubeyko <Slava.Dubeyko@ibm.com>2026-04-09 21:33:23 +0300
committerIlya Dryomov <idryomov@gmail.com>2026-05-11 11:39:22 +0300
commit10d9be401108a0fc8b3bc99ba07bdee8fff875ac (patch)
treec1f99e94a0b8b25ced95bc8da214474768fbc93c
parent821365487aa58d06bda65c676ba215d506ba9768 (diff)
downloadlinux-10d9be401108a0fc8b3bc99ba07bdee8fff875ac.tar.xz
ceph: add ceph_has_realms_with_quotas() check to ceph_quota_update_statfs()
When MDS rejects a session, remove_session_caps() -> __ceph_remove_cap() -> ceph_change_snap_realm() clears i_snap_realm for every inode that loses its last cap. The realm is restored once caps are re-granted after reconnect. It is not a real error and this patch changes pr_err_ratelimited_client() on doutc(). Every quota methods ceph_quota_is_max_files_exceeded(), ceph_quota_is_max_bytes_exceeded(), ceph_quota_is_max_bytes_approaching() calls ceph_has_realms_with_quotas() check. This patch adds the missing ceph_has_realms_with_quotas() call into ceph_quota_update_statfs(). [ idryomov: add braces around both arms of multiline ifs ] Signed-off-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com> Reviewed-by: Alex Markuze <amarkuze@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r--fs/ceph/quota.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c
index 4dc9426643e8..053d5bf0c9f0 100644
--- a/fs/ceph/quota.c
+++ b/fs/ceph/quota.c
@@ -228,12 +228,19 @@ static int get_quota_realm(struct ceph_mds_client *mdsc, struct inode *inode,
restart:
realm = ceph_inode(inode)->i_snap_realm;
- if (realm)
+ if (realm) {
ceph_get_snap_realm(mdsc, realm);
- else
- pr_err_ratelimited_client(cl,
- "%p %llx.%llx null i_snap_realm\n",
- inode, ceph_vinop(inode));
+ } else {
+ /*
+ * i_snap_realm is NULL when all caps have been released, e.g.
+ * after an MDS session rejection. This is a transient state;
+ * the realm will be restored once caps are re-granted.
+ * Treat it as "no quota realm found".
+ */
+ doutc(cl, "%p %llx.%llx null i_snap_realm\n",
+ inode, ceph_vinop(inode));
+ }
+
while (realm) {
bool has_inode;
@@ -340,12 +347,19 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
down_read(&mdsc->snap_rwsem);
restart:
realm = ceph_inode(inode)->i_snap_realm;
- if (realm)
+ if (realm) {
ceph_get_snap_realm(mdsc, realm);
- else
- pr_err_ratelimited_client(cl,
- "%p %llx.%llx null i_snap_realm\n",
- inode, ceph_vinop(inode));
+ } else {
+ /*
+ * i_snap_realm is NULL when all caps have been released, e.g.
+ * after an MDS session rejection. This is a transient state;
+ * the realm will be restored once caps are re-granted.
+ * Treat it as "quota not exceeded".
+ */
+ doutc(cl, "%p %llx.%llx null i_snap_realm\n",
+ inode, ceph_vinop(inode));
+ }
+
while (realm) {
bool has_inode;
@@ -496,6 +510,9 @@ bool ceph_quota_update_statfs(struct ceph_fs_client *fsc, struct kstatfs *buf)
u64 total = 0, used, free;
bool is_updated = false;
+ if (!ceph_has_realms_with_quotas(d_inode(fsc->sb->s_root)))
+ return false;
+
down_read(&mdsc->snap_rwsem);
get_quota_realm(mdsc, d_inode(fsc->sb->s_root), QUOTA_GET_MAX_BYTES,
&realm, true);