提交 93a54bc4 编写于 作者: J Josef Bacik

Btrfs: check for duplicate iov_base's when doing dio reads

Apparently it is ok to submit a read to an IDE device with the same target page
for different offsets.  This is what Windows does under qemu.  The problem is
under DIO we expect them to be different buffers for checksumming reasons, and
so this sort of thing will result in checksum errors, when in reality the file
is fine.  So when reading, check to make sure that all iov bases are different,
and if they aren't fall back to buffered mode, since that will work out right.
Thanks,
Signed-off-by: NJosef Bacik <josef@redhat.com>
上级 16d299ac
...@@ -6207,6 +6207,7 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io ...@@ -6207,6 +6207,7 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
unsigned long nr_segs) unsigned long nr_segs)
{ {
int seg; int seg;
int i;
size_t size; size_t size;
unsigned long addr; unsigned long addr;
unsigned blocksize_mask = root->sectorsize - 1; unsigned blocksize_mask = root->sectorsize - 1;
...@@ -6223,6 +6224,20 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io ...@@ -6223,6 +6224,20 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
end += size; end += size;
if ((addr & blocksize_mask) || (size & blocksize_mask)) if ((addr & blocksize_mask) || (size & blocksize_mask))
goto out; goto out;
/* If this is a write we don't need to check anymore */
if (rw & WRITE)
continue;
/*
* Check to make sure we don't have duplicate iov_base's in this
* iovec, if so return EINVAL, otherwise we'll get csum errors
* when reading back.
*/
for (i = seg + 1; i < nr_segs; i++) {
if (iov[seg].iov_base == iov[i].iov_base)
goto out;
}
} }
retval = 0; retval = 0;
out: out:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册