GFS2: Fix fstrim boundary conditions
authorAbhijith Das <adas@redhat.com>
Wed, 19 Jun 2013 21:03:29 +0000 (17:03 -0400)
committerSteven Whitehouse <swhiteho@redhat.com>
Wed, 19 Jun 2013 20:41:26 +0000 (21:41 +0100)
This patch correctly distinguishes two boundary conditions:

1. When the given range is entire within the unaccounted space between
   two rgrps, and
2. The range begins beyond the end of the filesystem

Also fix the unit of the returned value r.len (total trimming) to be in bytes
instead of the (incorrect) 512 byte blocks

With this patch, GFS2 passes multiple iterations of all the relevant xfstests
(251, 260, 288) with different fs block sizes.

Signed-off-by: Abhi Das <adas@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
fs/gfs2/rgrp.c

index 9809156e3d044e9ca4c39dd9b58c69105f282ab0..69317435faa723c9288d390407d9343fb6bf1096 100644 (file)
@@ -1288,13 +1288,15 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
        minlen = max_t(u64, r.minlen,
                       q->limits.discard_granularity) >> bs_shift;
 
+       if (end <= start || minlen > sdp->sd_max_rg_data)
+               return -EINVAL;
+
        rgd = gfs2_blk2rgrpd(sdp, start, 0);
-       rgd_end = gfs2_blk2rgrpd(sdp, end - 1, 0);
+       rgd_end = gfs2_blk2rgrpd(sdp, end, 0);
 
-       if (end <= start ||
-           minlen > sdp->sd_max_rg_data ||
-           start > rgd_end->rd_data0 + rgd_end->rd_data)
-               return -EINVAL;
+       if ((gfs2_rgrpd_get_first(sdp) == gfs2_rgrpd_get_next(rgd_end))
+           && (start > rgd_end->rd_data0 + rgd_end->rd_data))
+               return -EINVAL; /* start is beyond the end of the fs */
 
        while (1) {
 
@@ -1336,7 +1338,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
        }
 
 out:
-       r.len = trimmed << 9;
+       r.len = trimmed << bs_shift;
        if (copy_to_user(argp, &r, sizeof(r)))
                return -EFAULT;