|
@@ -7391,39 +7391,30 @@ free_ordered:
|
|
|
}
|
|
|
|
|
|
static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb,
|
|
|
- const struct iovec *iov, loff_t offset,
|
|
|
- unsigned long nr_segs)
|
|
|
+ const struct iov_iter *iter, loff_t offset)
|
|
|
{
|
|
|
int seg;
|
|
|
int i;
|
|
|
- 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)iov[seg].iov_base;
|
|
|
- size = iov[seg].iov_len;
|
|
|
- end += size;
|
|
|
- if ((addr & blocksize_mask) || (size & blocksize_mask))
|
|
|
- goto out;
|
|
|
-
|
|
|
- /* If this is a write we don't need to check anymore */
|
|
|
- if (rw & WRITE)
|
|
|
- continue;
|
|
|
+ if (iov_iter_alignment(iter) & blocksize_mask)
|
|
|
+ goto out;
|
|
|
|
|
|
- /*
|
|
|
- * 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)
|
|
|
+ /* If this is a write we don't need to check anymore */
|
|
|
+ if (rw & WRITE)
|
|
|
+ return 0;
|
|
|
+ /*
|
|
|
+ * 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 (seg = 0; seg < iter->nr_segs; seg++) {
|
|
|
+ for (i = seg + 1; i < iter->nr_segs; i++) {
|
|
|
+ if (iter->iov[seg].iov_base == iter->iov[i].iov_base)
|
|
|
goto out;
|
|
|
}
|
|
|
}
|
|
@@ -7443,8 +7434,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
|
|
|
bool relock = false;
|
|
|
ssize_t ret;
|
|
|
|
|
|
- if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iter->iov,
|
|
|
- offset, iter->nr_segs))
|
|
|
+ if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iter, offset))
|
|
|
return 0;
|
|
|
|
|
|
atomic_inc(&inode->i_dio_count);
|