]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ceph: add ceph_has_realms_with_quotas() check to ceph_quota_update_statfs()
authorViacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Thu, 9 Apr 2026 18:33:23 +0000 (11:33 -0700)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 11 May 2026 08:39:22 +0000 (10:39 +0200)
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>
fs/ceph/quota.c

index 4dc9426643e8346438759c6d3ff8af577a063ecb..053d5bf0c9f07c60de3607a97f68da539b828bd9 100644 (file)
@@ -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);