summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h13
-rw-r--r--fs/xfs/xfs_log.c131
2 files changed, 82 insertions, 62 deletions
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h
index 79bb79853c9f..e5f97c69b320 100644
--- a/fs/xfs/libxfs/xfs_log_format.h
+++ b/fs/xfs/libxfs/xfs_log_format.h
@@ -77,6 +77,19 @@ static inline uint xlog_get_cycle(char *ptr)
#define XLOG_UNMOUNT_TYPE 0x556e /* Un for Unmount */
+/*
+ * Log item for unmount records.
+ *
+ * The unmount record used to have a string "Unmount filesystem--" in the
+ * data section where the "Un" was really a magic number (XLOG_UNMOUNT_TYPE).
+ * We just write the magic number now; see xfs_log_unmount_write.
+ */
+struct xfs_unmount_log_format {
+ uint16_t magic; /* XLOG_UNMOUNT_TYPE */
+ uint16_t pad1;
+ uint32_t pad2; /* may as well make it 64 bits */
+};
+
/* Region types for iovec's i_type */
#define XLOG_REG_TYPE_BFORMAT 1
#define XLOG_REG_TYPE_BCHUNK 2
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 5e56f3b93d4b..bac586cbc54e 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -826,6 +826,74 @@ xfs_log_mount_cancel(
* deallocation must not be done until source-end.
*/
+/* Actually write the unmount record to disk. */
+static void
+xfs_log_write_unmount_record(
+ struct xfs_mount *mp)
+{
+ /* the data section must be 32 bit size aligned */
+ struct xfs_unmount_log_format magic = {
+ .magic = XLOG_UNMOUNT_TYPE,
+ };
+ struct xfs_log_iovec reg = {
+ .i_addr = &magic,
+ .i_len = sizeof(magic),
+ .i_type = XLOG_REG_TYPE_UNMOUNT,
+ };
+ struct xfs_log_vec vec = {
+ .lv_niovecs = 1,
+ .lv_iovecp = &reg,
+ };
+ struct xlog *log = mp->m_log;
+ struct xlog_in_core *iclog;
+ struct xlog_ticket *tic = NULL;
+ xfs_lsn_t lsn;
+ int error;
+
+ error = xfs_log_reserve(mp, 600, 1, &tic, XFS_LOG, 0);
+ if (error)
+ goto out_err;
+
+ /* remove inited flag, and account for space used */
+ tic->t_flags = 0;
+ tic->t_curr_res -= sizeof(magic);
+ error = xlog_write(log, &vec, tic, &lsn, NULL, XLOG_UNMOUNT_TRANS);
+ /*
+ * At this point, we're umounting anyway, so there's no point in
+ * transitioning log state to IOERROR. Just continue...
+ */
+out_err:
+ if (error)
+ xfs_alert(mp, "%s: unmount record failed", __func__);
+
+ spin_lock(&log->l_icloglock);
+ iclog = log->l_iclog;
+ atomic_inc(&iclog->ic_refcnt);
+ xlog_state_want_sync(log, iclog);
+ spin_unlock(&log->l_icloglock);
+ error = xlog_state_release_iclog(log, iclog);
+
+ spin_lock(&log->l_icloglock);
+ switch (iclog->ic_state) {
+ default:
+ if (!XLOG_FORCED_SHUTDOWN(log)) {
+ xlog_wait(&iclog->ic_force_wait, &log->l_icloglock);
+ break;
+ }
+ /* fall through */
+ case XLOG_STATE_ACTIVE:
+ case XLOG_STATE_DIRTY:
+ spin_unlock(&log->l_icloglock);
+ break;
+ }
+
+ if (tic) {
+ trace_xfs_log_umount_write(log, tic);
+ xlog_ungrant_log_space(log, tic);
+ xfs_log_ticket_put(tic);
+ }
+}
+
/*
* Unmount record used to have a string "Unmount filesystem--" in the
* data section where the "Un" was really a magic number (XLOG_UNMOUNT_TYPE).
@@ -842,8 +910,6 @@ xfs_log_unmount_write(xfs_mount_t *mp)
#ifdef DEBUG
xlog_in_core_t *first_iclog;
#endif
- xlog_ticket_t *tic = NULL;
- xfs_lsn_t lsn;
int error;
/*
@@ -870,66 +936,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
} while (iclog != first_iclog);
#endif
if (! (XLOG_FORCED_SHUTDOWN(log))) {
- error = xfs_log_reserve(mp, 600, 1, &tic, XFS_LOG, 0);
- if (!error) {
- /* the data section must be 32 bit size aligned */
- struct {
- uint16_t magic;
- uint16_t pad1;
- uint32_t pad2; /* may as well make it 64 bits */
- } magic = {
- .magic = XLOG_UNMOUNT_TYPE,
- };
- struct xfs_log_iovec reg = {
- .i_addr = &magic,
- .i_len = sizeof(magic),
- .i_type = XLOG_REG_TYPE_UNMOUNT,
- };
- struct xfs_log_vec vec = {
- .lv_niovecs = 1,
- .lv_iovecp = &reg,
- };
-
- /* remove inited flag, and account for space used */
- tic->t_flags = 0;
- tic->t_curr_res -= sizeof(magic);
- error = xlog_write(log, &vec, tic, &lsn,
- NULL, XLOG_UNMOUNT_TRANS);
- /*
- * At this point, we're umounting anyway,
- * so there's no point in transitioning log state
- * to IOERROR. Just continue...
- */
- }
-
- if (error)
- xfs_alert(mp, "%s: unmount record failed", __func__);
-
-
- spin_lock(&log->l_icloglock);
- iclog = log->l_iclog;
- atomic_inc(&iclog->ic_refcnt);
- xlog_state_want_sync(log, iclog);
- spin_unlock(&log->l_icloglock);
- error = xlog_state_release_iclog(log, iclog);
-
- spin_lock(&log->l_icloglock);
- if (!(iclog->ic_state == XLOG_STATE_ACTIVE ||
- iclog->ic_state == XLOG_STATE_DIRTY)) {
- if (!XLOG_FORCED_SHUTDOWN(log)) {
- xlog_wait(&iclog->ic_force_wait,
- &log->l_icloglock);
- } else {
- spin_unlock(&log->l_icloglock);
- }
- } else {
- spin_unlock(&log->l_icloglock);
- }
- if (tic) {
- trace_xfs_log_umount_write(log, tic);
- xlog_ungrant_log_space(log, tic);
- xfs_log_ticket_put(tic);
- }
+ xfs_log_write_unmount_record(mp);
} else {
/*
* We're already in forced_shutdown mode, couldn't