aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/inode.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 24310c9cb14f..00d59c6a9769 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6207,6 +6207,7 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
6207 unsigned long nr_segs) 6207 unsigned long nr_segs)
6208{ 6208{
6209 int seg; 6209 int seg;
6210 int i;
6210 size_t size; 6211 size_t size;
6211 unsigned long addr; 6212 unsigned long addr;
6212 unsigned blocksize_mask = root->sectorsize - 1; 6213 unsigned blocksize_mask = root->sectorsize - 1;
@@ -6221,8 +6222,22 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
6221 addr = (unsigned long)iov[seg].iov_base; 6222 addr = (unsigned long)iov[seg].iov_base;
6222 size = iov[seg].iov_len; 6223 size = iov[seg].iov_len;
6223 end += size; 6224 end += size;
6224 if ((addr & blocksize_mask) || (size & blocksize_mask)) 6225 if ((addr & blocksize_mask) || (size & blocksize_mask))
6225 goto out; 6226 goto out;
6227
6228 /* If this is a write we don't need to check anymore */
6229 if (rw & WRITE)
6230 continue;
6231
6232 /*
6233 * Check to make sure we don't have duplicate iov_base's in this
6234 * iovec, if so return EINVAL, otherwise we'll get csum errors
6235 * when reading back.
6236 */
6237 for (i = seg + 1; i < nr_segs; i++) {
6238 if (iov[seg].iov_base == iov[i].iov_base)
6239 goto out;
6240 }
6226 } 6241 }
6227 retval = 0; 6242 retval = 0;
6228out: 6243out: