|
@@ -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 = ®,
|
|
|
+ };
|
|
|
+ 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 = ®,
|
|
|
- };
|
|
|
-
|
|
|
- /* 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
|