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 2d1208f964eb..edafc28883af 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6153,6 +6153,7 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
6153 unsigned long nr_segs) 6153 unsigned long nr_segs)
6154{ 6154{
6155 int seg; 6155 int seg;
6156 int i;
6156 size_t size; 6157 size_t size;
6157 unsigned long addr; 6158 unsigned long addr;
6158 unsigned blocksize_mask = root->sectorsize - 1; 6159 unsigned blocksize_mask = root->sectorsize - 1;
@@ -6167,8 +6168,22 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
6167 addr = (unsigned long)iov[seg].iov_base; 6168 addr = (unsigned long)iov[seg].iov_base;
6168 size = iov[seg].iov_len; 6169 size = iov[seg].iov_len;
6169 end += size; 6170 end += size;
6170 if ((addr & blocksize_mask) || (size & blocksize_mask)) 6171 if ((addr & blocksize_mask) || (size & blocksize_mask))
6171 goto out; 6172 goto out;
6173
6174 /* If this is a write we don't need to check anymore */
6175 if (rw & WRITE)
6176 continue;
6177
6178 /*
6179 * Check to make sure we don't have duplicate iov_base's in this
6180 * iovec, if so return EINVAL, otherwise we'll get csum errors
6181 * when reading back.
6182 */
6183 for (i = seg + 1; i < nr_segs; i++) {
6184 if (iov[seg].iov_base == iov[i].iov_base)
6185 goto out;
6186 }
6172 } 6187 }
6173 retval = 0; 6188 retval = 0;
6174out: 6189out: