]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
btrfs: btrfs_direct_IO_bvec() needs to check for sector alignment
authorDave Kleikamp <dave.kleikamp@oracle.com>
Thu, 22 Mar 2012 22:19:44 +0000 (17:19 -0500)
committerDave Kleikamp <dave.kleikamp@oracle.com>
Thu, 22 Mar 2012 22:31:01 +0000 (17:31 -0500)
I left out a vital piece of btrfs_direct_IO_bvec(). I didn't think
check_direct_IO() was needed, but it is. This patch creates its
equivalent, check_direct_IO_bvec().

Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
fs/btrfs/inode.c

index 66f1f56c107d49a3580953fff6f159fd61a9af57..39d9353d56e75b3704ee5a52e83392f6b7b5d7c3 100644 (file)
@@ -6126,6 +6126,33 @@ out:
        return retval;
 }
 
+static ssize_t check_direct_IO_bvec(struct btrfs_root *root, int rw,
+                                   struct kiocb *iocb, struct bio_vec *bvec,
+                                   loff_t offset, unsigned long nr_segs)
+{
+       int seg;
+       size_t size;
+       unsigned long addr;
+       unsigned blocksize_mask = root->sectorsize - 1;
+       ssize_t retval = -EINVAL;
+       loff_t end = offset;
+
+       if (offset & blocksize_mask)
+               goto out;
+
+       /* Check the memory alignment.  Blocks cannot straddle pages */
+       for (seg = 0; seg < nr_segs; seg++) {
+               addr = (unsigned long)bvec[seg].bv_offset;
+               size = bvec[seg].bv_len;
+               end += size;
+               if ((addr & blocksize_mask) || (size & blocksize_mask))
+                       goto out;
+       }
+       retval = 0;
+out:
+       return retval;
+}
+
 static ssize_t btrfs_pre_direct_IO(int writing,  loff_t offset, size_t count,
                                   struct inode *inode, int *write_bits)
 {
@@ -6246,6 +6273,10 @@ static ssize_t btrfs_direct_IO_bvec(int rw, struct kiocb *iocb,
        int write_bits = 0;
        size_t count = bvec_length(bvec, bvec_len);
 
+       if (check_direct_IO_bvec(BTRFS_I(inode)->root, rw, iocb, bvec,
+                                offset, bvec_len))
+               return 0;
+
        ret = btrfs_pre_direct_IO(writing, offset, count, inode, &write_bits);
        if (ret)
                return ret;