diff options
author | Chunwei Chen <[email protected]> | 2015-07-30 22:24:36 +0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2015-08-24 10:17:06 -0700 |
commit | 5475aada9474464f973788c1b2fc6216486fb303 (patch) | |
tree | f4b02aff6e841b47cad4894b40c7a1092ad0be3b /module/zfs/zfs_vnops.c | |
parent | 17888ae30d6111f1fe25087a256724ee9b1a0a84 (diff) |
Linux 4.1 compat: loop device on ZFS
Starting from Linux 4.1 allows iov_iter with bio_vec to be passed into
iter_read/iter_write. Notably, the loop device will pass bio_vec to backend
filesystem. However, current ZFS code assumes iovec without any check, so it
will always crash when using loop device.
With the restructured uio_t, we can safely pass bio_vec in uio_t with UIO_BVEC
set. The uio* functions are modified to handle bio_vec case separately.
The const uio_iov causes some warning in xuio related stuff, so explicit
convert them to non const.
Signed-off-by: Chunwei Chen <[email protected]>
Signed-off-by: Richard Yao <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #3511
Closes #3640
Diffstat (limited to 'module/zfs/zfs_vnops.c')
-rw-r--r-- | module/zfs/zfs_vnops.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 1d23d6db3..5e5f3c8db 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2015 by Chunwei Chen. All rights reserved. */ /* Portions Copyright 2007 Jeremy Teo */ @@ -591,10 +592,10 @@ zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr) int max_blksz = zsb->z_max_blksz; int error = 0; arc_buf_t *abuf; - iovec_t *aiov = NULL; + const iovec_t *aiov = NULL; xuio_t *xuio = NULL; int i_iov = 0; - iovec_t *iovp = uio->uio_iov; + const iovec_t *iovp = uio->uio_iov; int write_eof; int count = 0; sa_bulk_attr_t bulk[4]; @@ -714,6 +715,7 @@ zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr) if (xuio && abuf == NULL) { ASSERT(i_iov < iovcnt); + ASSERT3U(uio->uio_segflg, !=, UIO_BVEC); aiov = &iovp[i_iov]; abuf = dmu_xuio_arcbuf(xuio, i_iov); dmu_xuio_clear(xuio, i_iov); |