aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--module/zfs/txg.c9
-rw-r--r--module/zfs/zpl_file.c10
-rw-r--r--module/zfs/zvol.c28
3 files changed, 42 insertions, 5 deletions
diff --git a/module/zfs/txg.c b/module/zfs/txg.c
index c234567d7..aefda6f69 100644
--- a/module/zfs/txg.c
+++ b/module/zfs/txg.c
@@ -382,6 +382,15 @@ txg_sync_thread(dsl_pool_t *dp)
callb_cpr_t cpr;
uint64_t start, delta;
+#ifdef _KERNEL
+ /*
+ * Annotate this process with a flag that indicates that it is
+ * unsafe to use KM_SLEEP during memory allocations due to the
+ * potential for a deadlock. KM_PUSHPAGE should be used instead.
+ */
+ current->flags |= PF_NOFS;
+#endif /* _KERNEL */
+
txg_thread_enter(tx, &cpr);
start = delta = 0;
diff --git a/module/zfs/zpl_file.c b/module/zfs/zpl_file.c
index 2e9f72ad1..9c27b7f1d 100644
--- a/module/zfs/zpl_file.c
+++ b/module/zfs/zpl_file.c
@@ -357,8 +357,16 @@ zpl_putpage(struct page *pp, struct writeback_control *wbc, void *data)
ASSERT(PageLocked(pp));
ASSERT(!PageWriteback(pp));
-
+ ASSERT(!(current->flags & PF_NOFS));
+
+ /*
+ * Annotate this call path with a flag that indicates that it is
+ * unsafe to use KM_SLEEP during memory allocations due to the
+ * potential for a deadlock. KM_PUSHPAGE should be used instead.
+ */
+ current->flags |= PF_NOFS;
(void) zfs_putpage(mapping->host, pp, wbc);
+ current->flags &= ~PF_NOFS;
return (0);
}
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index 07bda6dba..60ff64ebe 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -540,6 +540,14 @@ zvol_write(void *arg)
dmu_tx_t *tx;
rl_t *rl;
+ /*
+ * Annotate this call path with a flag that indicates that it is
+ * unsafe to use KM_SLEEP during memory allocations due to the
+ * potential for a deadlock. KM_PUSHPAGE should be used instead.
+ */
+ ASSERT(!(current->flags & PF_NOFS));
+ current->flags |= PF_NOFS;
+
if (req->cmd_flags & VDEV_REQ_FLUSH)
zil_commit(zv->zv_zilog, ZVOL_OBJ);
@@ -548,7 +556,7 @@ zvol_write(void *arg)
*/
if (size == 0) {
blk_end_request(req, 0, size);
- return;
+ goto out;
}
rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_WRITER);
@@ -562,7 +570,7 @@ zvol_write(void *arg)
dmu_tx_abort(tx);
zfs_range_unlock(rl);
blk_end_request(req, -error, size);
- return;
+ goto out;
}
error = dmu_write_req(zv->zv_objset, ZVOL_OBJ, req, tx);
@@ -578,6 +586,8 @@ zvol_write(void *arg)
zil_commit(zv->zv_zilog, ZVOL_OBJ);
blk_end_request(req, -error, size);
+out:
+ current->flags &= ~PF_NOFS;
}
#ifdef HAVE_BLK_QUEUE_DISCARD
@@ -592,14 +602,22 @@ zvol_discard(void *arg)
int error;
rl_t *rl;
+ /*
+ * Annotate this call path with a flag that indicates that it is
+ * unsafe to use KM_SLEEP during memory allocations due to the
+ * potential for a deadlock. KM_PUSHPAGE should be used instead.
+ */
+ ASSERT(!(current->flags & PF_NOFS));
+ current->flags |= PF_NOFS;
+
if (offset + size > zv->zv_volsize) {
blk_end_request(req, -EIO, size);
- return;
+ goto out;
}
if (size == 0) {
blk_end_request(req, 0, size);
- return;
+ goto out;
}
rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_WRITER);
@@ -613,6 +631,8 @@ zvol_discard(void *arg)
zfs_range_unlock(rl);
blk_end_request(req, -error, size);
+out:
+ current->flags &= ~PF_NOFS;
}
#endif /* HAVE_BLK_QUEUE_DISCARD */