aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zpl_file.c
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2019-05-08 10:04:04 -0700
committerGitHub <[email protected]>2019-05-08 10:04:04 -0700
commit515ddf65042e8eb772c3f38ed4556850a0c2fbf3 (patch)
tree4e6c28535d5f3fc991b941c781d01b91d6d11c58 /module/zfs/zpl_file.c
parent1f02ecc5a56d08b744b618c641505c451bd9b1e4 (diff)
Fix errant EFAULT during writes (#8719)
Commit 98bb45e resolved a deadlock which could occur when handling a page fault in zfs_write(). This change added the uio_fault_disable field to the uio structure but failed to initialize it to B_FALSE. This uninitialized field would cause uiomove_iov() to call __copy_from_user_inatomic() instead of copy_from_user() resulting in unexpected EFAULTs. Resolve the issue by fully initializing the uio, and clearing the uio_fault_disable flags after it's used in zfs_write(). Additionally, reorder the uio_t field assignments to match the order the fields are declared in the structure. Reviewed-by: Chunwei Chen <[email protected]> Reviewed-by: Richard Laager <[email protected]> Reviewed-by: Tim Chase <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #8640 Closes #8719
Diffstat (limited to 'module/zfs/zpl_file.c')
-rw-r--r--module/zfs/zpl_file.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/module/zfs/zpl_file.c b/module/zfs/zpl_file.c
index 731836c2c..acad4670d 100644
--- a/module/zfs/zpl_file.c
+++ b/module/zfs/zpl_file.c
@@ -246,17 +246,17 @@ zpl_read_common_iovec(struct inode *ip, const struct iovec *iovp, size_t count,
cred_t *cr, size_t skip)
{
ssize_t read;
- uio_t uio;
+ uio_t uio = { { 0 }, 0 };
int error;
fstrans_cookie_t cookie;
uio.uio_iov = iovp;
- uio.uio_skip = skip;
- uio.uio_resid = count;
uio.uio_iovcnt = nr_segs;
uio.uio_loffset = *ppos;
- uio.uio_limit = MAXOFFSET_T;
uio.uio_segflg = segment;
+ uio.uio_limit = MAXOFFSET_T;
+ uio.uio_resid = count;
+ uio.uio_skip = skip;
cookie = spl_fstrans_mark();
error = -zfs_read(ip, &uio, flags, cr);
@@ -356,7 +356,7 @@ zpl_write_common_iovec(struct inode *ip, const struct iovec *iovp, size_t count,
cred_t *cr, size_t skip)
{
ssize_t wrote;
- uio_t uio;
+ uio_t uio = { { 0 }, 0 };
int error;
fstrans_cookie_t cookie;
@@ -364,12 +364,12 @@ zpl_write_common_iovec(struct inode *ip, const struct iovec *iovp, size_t count,
*ppos = i_size_read(ip);
uio.uio_iov = iovp;
- uio.uio_skip = skip;
- uio.uio_resid = count;
uio.uio_iovcnt = nr_segs;
uio.uio_loffset = *ppos;
- uio.uio_limit = MAXOFFSET_T;
uio.uio_segflg = segment;
+ uio.uio_limit = MAXOFFSET_T;
+ uio.uio_resid = count;
+ uio.uio_skip = skip;
cookie = spl_fstrans_mark();
error = -zfs_write(ip, &uio, flags, cr);