Fix mmap / libaio deadlock

Calling uiomove() in mappedread() under the page lock can result
in a deadlock if the user space page needs to be faulted in.

Resolve the issue by dropping the page lock before the uiomove().
The inode range lock protects against concurrent updates via
zfs_read() and zfs_write().

Reviewed-by: Albert Lee <trisk@forkgnu.org>
Reviewed-by: Chunwei Chen <david.chen@nutanix.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #7335
Closes #7339
This commit is contained in:
Brian Behlendorf
2018-03-28 10:19:22 -07:00
committed by Tony Hutter
parent 2deb4526ee
commit 63f3396233
14 changed files with 184 additions and 5 deletions
+1 -1
View File
@@ -398,6 +398,7 @@ mappedread(struct inode *ip, int nbytes, uio_t *uio)
pp = find_lock_page(mp, start >> PAGE_SHIFT);
if (pp) {
ASSERT(PageUptodate(pp));
unlock_page(pp);
pb = kmap(pp);
error = uiomove(pb + off, bytes, UIO_READ, uio);
@@ -407,7 +408,6 @@ mappedread(struct inode *ip, int nbytes, uio_t *uio)
flush_dcache_page(pp);
mark_page_accessed(pp);
unlock_page(pp);
put_page(pp);
} else {
error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),