mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-30 18:56:23 +03:00
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 <tuxoko@gmail.com>
Reviewed-by: Richard Laager <rlaager@wiktel.com>
Reviewed-by: Tim Chase <tim@chase2k.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #8640
Closes #8719
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user