diff options
author | Brian Behlendorf <[email protected]> | 2019-05-08 10:04:04 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2019-05-08 10:04:04 -0700 |
commit | 515ddf65042e8eb772c3f38ed4556850a0c2fbf3 (patch) | |
tree | 4e6c28535d5f3fc991b941c781d01b91d6d11c58 /module/zfs/zvol.c | |
parent | 1f02ecc5a56d08b744b618c641505c451bd9b1e4 (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/zvol.c')
-rw-r--r-- | module/zfs/zvol.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index a77339d7f..c29f65f67 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -727,12 +727,12 @@ static void uio_from_bio(uio_t *uio, struct bio *bio) { uio->uio_bvec = &bio->bi_io_vec[BIO_BI_IDX(bio)]; - uio->uio_skip = BIO_BI_SKIP(bio); - uio->uio_resid = BIO_BI_SIZE(bio); uio->uio_iovcnt = bio->bi_vcnt - BIO_BI_IDX(bio); uio->uio_loffset = BIO_BI_SECTOR(bio) << 9; - uio->uio_limit = MAXOFFSET_T; uio->uio_segflg = UIO_BVEC; + uio->uio_limit = MAXOFFSET_T; + uio->uio_resid = BIO_BI_SIZE(bio); + uio->uio_skip = BIO_BI_SKIP(bio); } static void @@ -742,7 +742,7 @@ zvol_write(void *arg) zv_request_t *zvr = arg; struct bio *bio = zvr->bio; - uio_t uio; + uio_t uio = { { 0 }, 0 }; uio_from_bio(&uio, bio); zvol_state_t *zv = zvr->zv; @@ -897,7 +897,7 @@ zvol_read(void *arg) zv_request_t *zvr = arg; struct bio *bio = zvr->bio; - uio_t uio; + uio_t uio = { { 0 }, 0 }; uio_from_bio(&uio, bio); zvol_state_t *zv = zvr->zv; |