summaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorKotresh HR <khiremat@redhat.com>2021-11-10 23:30:21 +0530
committerIlya Dryomov <idryomov@gmail.com>2022-01-13 13:40:06 +0100
commit8e55ba8caae5cd380b1c9c81a426602a667e110e (patch)
tree34504e35db1145d0a16e17f87e1babd53c1f2608 /fs/ceph
parentadbed05ed62d1f3b6f6c5cb88ec52c1ffafc0fd9 (diff)
downloadlinux-stable-8e55ba8caae5cd380b1c9c81a426602a667e110e.tar.gz
linux-stable-8e55ba8caae5cd380b1c9c81a426602a667e110e.tar.bz2
linux-stable-8e55ba8caae5cd380b1c9c81a426602a667e110e.zip
ceph: Fix incorrect statfs report for small quota
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> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/quota.c14
-rw-r--r--fs/ceph/super.h1
2 files changed, 15 insertions, 0 deletions
diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c
index 620c691af40e..24ae13ea2241 100644
--- a/fs/ceph/quota.c
+++ b/fs/ceph/quota.c
@@ -494,10 +494,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) {
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index ec6b221e5b62..533189b537b2 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -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 */