summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2009-12-19 11:43:39 +0000
committerdelphij <delphij@FreeBSD.org>2009-12-19 11:43:39 +0000
commit3cc7b7e8fb55b4f130d3395b733137304708d301 (patch)
tree562cbd7b999d9ef6a9f9e7172b4c40b56ae0833b /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
parent6d8f8050bf9d7cacd62498b78f7ed2b89002d798 (diff)
downloadFreeBSD-src-3cc7b7e8fb55b4f130d3395b733137304708d301.zip
FreeBSD-src-3cc7b7e8fb55b4f130d3395b733137304708d301.tar.gz
Apply fix Solaris bug 6462803 zfs snapshot -r failed because
filesystem was busy. Submitted by: mm Approved by: pjd MFC after: 2 weeks
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c57
1 files changed, 36 insertions, 21 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
index a7c2b37..4455fb8 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
@@ -502,6 +502,25 @@ zil_rollback_destroy(zilog_t *zilog, dmu_tx_t *tx)
tx, zh->zh_claim_txg);
}
+/*
+ * return true if the initial log block is not valid
+ */
+static boolean_t
+zil_empty(zilog_t *zilog)
+{
+ const zil_header_t *zh = zilog->zl_header;
+ arc_buf_t *abuf = NULL;
+
+ if (BP_IS_HOLE(&zh->zh_log))
+ return (B_TRUE);
+
+ if (zil_read_log_block(zilog, &zh->zh_log, &abuf) != 0)
+ return (B_TRUE);
+
+ VERIFY(arc_buf_remove_ref(abuf, &abuf) == 1);
+ return (B_FALSE);
+}
+
int
zil_claim(char *osname, void *txarg)
{
@@ -522,6 +541,21 @@ zil_claim(char *osname, void *txarg)
zh = zil_header_in_syncing_context(zilog);
/*
+ * Record here whether the zil has any records to replay.
+ * If the header block pointer is null or the block points
+ * to the stubby then we know there are no valid log records.
+ * We use the header to store this state as the the zilog gets
+ * freed later in dmu_objset_close().
+ * The flags (and the rest of the header fields) are cleared in
+ * zil_sync() as a result of a zil_destroy(), after replaying the log.
+ *
+ * Note, the intent log can be empty but still need the
+ * stubby to be claimed.
+ */
+ if (!zil_empty(zilog))
+ zh->zh_flags |= ZIL_REPLAY_NEEDED;
+
+ /*
* Claim all log blocks if we haven't already done so, and remember
* the highest claimed sequence number. This ensures that if we can
* read only part of the log now (e.g. due to a missing device),
@@ -1345,25 +1379,6 @@ zil_free(zilog_t *zilog)
}
/*
- * return true if the initial log block is not valid
- */
-static boolean_t
-zil_empty(zilog_t *zilog)
-{
- const zil_header_t *zh = zilog->zl_header;
- arc_buf_t *abuf = NULL;
-
- if (BP_IS_HOLE(&zh->zh_log))
- return (B_TRUE);
-
- if (zil_read_log_block(zilog, &zh->zh_log, &abuf) != 0)
- return (B_TRUE);
-
- VERIFY(arc_buf_remove_ref(abuf, &abuf) == 1);
- return (B_FALSE);
-}
-
-/*
* Open an intent log.
*/
zilog_t *
@@ -1418,7 +1433,7 @@ zil_suspend(zilog_t *zilog)
const zil_header_t *zh = zilog->zl_header;
mutex_enter(&zilog->zl_lock);
- if (zh->zh_claim_txg != 0) { /* unplayed log */
+ if (zh->zh_flags & ZIL_REPLAY_NEEDED) { /* unplayed log */
mutex_exit(&zilog->zl_lock);
return (EBUSY);
}
@@ -1645,7 +1660,7 @@ zil_replay(objset_t *os, void *arg, uint64_t *txgp,
const zil_header_t *zh = zilog->zl_header;
zil_replay_arg_t zr;
- if (zil_empty(zilog)) {
+ if ((zh->zh_flags & ZIL_REPLAY_NEEDED) == 0) {
zil_destroy(zilog, B_TRUE);
return;
}
OpenPOWER on IntegriCloud