]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
ceph: Fix incorrect statfs report for small quota
authorKotresh HR <khiremat@redhat.com>
Wed, 10 Nov 2021 18:00:21 +0000 (23:30 +0530)
committerJeff Layton <jlayton@kernel.org>
Mon, 15 Nov 2021 11:45:55 +0000 (06:45 -0500)
Problem:
The statfs reports incorrect free/available space
for quota less then CEPH_BLOCK size (4M).

Solution:
For quota less than CEPH_BLOCK size, smaller block
size of 4K is used. But if quota is less than 4K,
it is decided to go with binary use/free of 4K
block. For quota size less than 4K size, report the
total=used=4K,free=0 when quota is full and
total=free=4K,used=0 otherwise.

Signed-off-by: Kotresh HR <khiremat@redhat.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
fs/ceph/quota.c
fs/ceph/super.h

index d1158c40bb0c6d68e8e696b764826abdb4c8867b..a338a3ec0dc4ebbd21c7c12479a843ad4a3c9d26 100644 (file)
@@ -497,10 +497,24 @@ bool ceph_quota_update_statfs(struct ceph_fs_client *fsc, struct kstatfs *buf)
                if (ci->i_max_bytes) {
                        total = ci->i_max_bytes >> CEPH_BLOCK_SHIFT;
                        used = ci->i_rbytes >> CEPH_BLOCK_SHIFT;
+                       /* For quota size less than 4MB, use 4KB block size */
+                       if (!total) {
+                               total = ci->i_max_bytes >> CEPH_4K_BLOCK_SHIFT;
+                               used = ci->i_rbytes >> CEPH_4K_BLOCK_SHIFT;
+                               buf->f_frsize = 1 << CEPH_4K_BLOCK_SHIFT;
+                       }
                        /* It is possible for a quota to be exceeded.
                         * Report 'zero' in that case
                         */
                        free = total > used ? total - used : 0;
+                       /* For quota size less than 4KB, report the
+                        * total=used=4KB,free=0 when quota is full
+                        * and total=free=4KB, used=0 otherwise */
+                       if (!total) {
+                               total = 1;
+                               free = ci->i_max_bytes > ci->i_rbytes ? 1 : 0;
+                               buf->f_frsize = 1 << CEPH_4K_BLOCK_SHIFT;
+                       }
                }
                spin_unlock(&ci->i_ceph_lock);
                if (total) {
index c232ed8e8a371d408c7af3ab2fa2a7048cac123c..65cbde64b8384f15f586d8053cb860abc07629cb 100644 (file)
@@ -32,6 +32,7 @@
  * large volume sizes on 32-bit machines. */
 #define CEPH_BLOCK_SHIFT   22  /* 4 MB */
 #define CEPH_BLOCK         (1 << CEPH_BLOCK_SHIFT)
+#define CEPH_4K_BLOCK_SHIFT 12  /* 4 KB */
 
 #define CEPH_MOUNT_OPT_CLEANRECOVER    (1<<1) /* auto reonnect (clean mode) after blocklisted */
 #define CEPH_MOUNT_OPT_DIRSTAT         (1<<4) /* `cat dirname` for stats */