]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
gfs2: Fix fallocate chunk size
authorAndreas Gruenbacher <agruenba@redhat.com>
Tue, 20 Feb 2018 15:03:24 +0000 (08:03 -0700)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Mon, 27 Aug 2018 14:40:05 +0000 (16:40 +0200)
BugLink: http://bugs.launchpad.net/bugs/1786352
[ Upstream commit 174d1232ebc84fcde8f5889d1171c9c7e74a10a7 ]

The chunk size of allocations in __gfs2_fallocate is calculated
incorrectly.  The size can collapse, causing __gfs2_fallocate to
allocate one block at a time, which is very inefficient.  This needs
fixing in two places:

In gfs2_quota_lock_check, always set ap->allowed to UINT_MAX to indicate
that there is no quota limit.  This fixes callers that rely on
ap->allowed to be set even when quotas are off.

In __gfs2_fallocate, reset max_blks to UINT_MAX in each iteration of the
loop to make sure that allocation limits from one resource group won't
spill over into another resource group.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
fs/gfs2/file.c
fs/gfs2/quota.h

index 58705ef8643a21993eb674519e66ba208a11c476..0d29944a38e0151e156899b8caf8cdaf7ce68177 100644 (file)
@@ -807,7 +807,7 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_alloc_parms ap = { .aflags = 0, };
        unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
-       loff_t bytes, max_bytes, max_blks = UINT_MAX;
+       loff_t bytes, max_bytes, max_blks;
        int error;
        const loff_t pos = offset;
        const loff_t count = len;
@@ -859,7 +859,8 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
                        return error;
                /* ap.allowed tells us how many blocks quota will allow
                 * us to write. Check if this reduces max_blks */
-               if (ap.allowed && ap.allowed < max_blks)
+               max_blks = UINT_MAX;
+               if (ap.allowed)
                        max_blks = ap.allowed;
 
                error = gfs2_inplace_reserve(ip, &ap);
index 5e47c935a51518d51e771cb0a2fd379e37523526..836f29480be6719c61dc2380a42b8556c6c88a99 100644 (file)
@@ -45,6 +45,8 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip,
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        int ret;
+
+       ap->allowed = UINT_MAX; /* Assume we are permitted a whole lot */
        if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
                return 0;
        ret = gfs2_quota_lock(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);