Btrfs: allow unaligned DIO
In order to support DIO that isn't aligned to the filesystem blocksize, we fall back to buffered for any unaligned DIOs. Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
933b585f70
commit
5a5f79b570
@ -5722,6 +5722,32 @@ free_ordered:
|
|||||||
bio_endio(bio, ret);
|
bio_endio(bio, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)iov[seg].iov_base;
|
||||||
|
size = iov[seg].iov_len;
|
||||||
|
end += size;
|
||||||
|
if ((addr & blocksize_mask) || (size & blocksize_mask))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
out:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
|
static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
|
||||||
const struct iovec *iov, loff_t offset,
|
const struct iovec *iov, loff_t offset,
|
||||||
unsigned long nr_segs)
|
unsigned long nr_segs)
|
||||||
@ -5736,6 +5762,11 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
|
|||||||
int write_bits = 0;
|
int write_bits = 0;
|
||||||
size_t count = iov_length(iov, nr_segs);
|
size_t count = iov_length(iov, nr_segs);
|
||||||
|
|
||||||
|
if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov,
|
||||||
|
offset, nr_segs)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
lockstart = offset;
|
lockstart = offset;
|
||||||
lockend = offset + count - 1;
|
lockend = offset + count - 1;
|
||||||
|
|
||||||
@ -5784,9 +5815,10 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
|
|||||||
free_extent_state(cached_state);
|
free_extent_state(cached_state);
|
||||||
cached_state = NULL;
|
cached_state = NULL;
|
||||||
|
|
||||||
ret = __blockdev_direct_IO(rw, iocb, inode, NULL, iov, offset, nr_segs,
|
ret = __blockdev_direct_IO(rw, iocb, inode,
|
||||||
btrfs_get_blocks_direct, NULL,
|
BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
|
||||||
btrfs_submit_direct, 0);
|
iov, offset, nr_segs, btrfs_get_blocks_direct, NULL,
|
||||||
|
btrfs_submit_direct, 0);
|
||||||
|
|
||||||
if (ret < 0 && ret != -EIOCBQUEUED) {
|
if (ret < 0 && ret != -EIOCBQUEUED) {
|
||||||
clear_extent_bit(&BTRFS_I(inode)->io_tree, offset,
|
clear_extent_bit(&BTRFS_I(inode)->io_tree, offset,
|
||||||
|
Loading…
Reference in New Issue
Block a user