+ return xfs_log_release_iclog(mp, commit_iclog);
+}
+
+
+/*
+ * xfs_trans_commit
+ *
+ * Commit the given transaction to the log a/synchronously.
+ *
+ * XFS disk error handling mechanism is not based on a typical
+ * transaction abort mechanism. Logically after the filesystem
+ * gets marked 'SHUTDOWN', we can't let any new transactions
+ * be durable - ie. committed to disk - because some metadata might
+ * be inconsistent. In such cases, this returns an error, and the
+ * caller may assume that all locked objects joined to the transaction
+ * have already been unlocked as if the commit had succeeded.
+ * Do not reference the transaction structure after this call.
+ */
+ /*ARGSUSED*/
+int
+_xfs_trans_commit(
+ xfs_trans_t *tp,
+ uint flags,
+ int *log_flushed)
+{
+ xfs_mount_t *mp = tp->t_mountp;
+ xfs_lsn_t commit_lsn = -1;
+ int error;
+ int log_flags = 0;
+ int sync = tp->t_flags & XFS_TRANS_SYNC;
+ int shutdown;
+
+ /*
+ * Determine whether this commit is releasing a permanent
+ * log reservation or not.
+ */
+ if (flags & XFS_TRANS_RELEASE_LOG_RES) {
+ ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
+ log_flags = XFS_LOG_REL_PERM_RESERV;
+ }
+
+ /*
+ * If there is nothing to be logged by the transaction,
+ * then unlock all of the items associated with the
+ * transaction and free the transaction structure.
+ * Also make sure to return any reserved blocks to
+ * the free pool.
+ */
+shut_us_down:
+ shutdown = XFS_FORCED_SHUTDOWN(mp) ? EIO : 0;
+ if (!(tp->t_flags & XFS_TRANS_DIRTY) || shutdown) {
+ xfs_trans_unreserve_and_mod_sb(tp);
+ /*
+ * It is indeed possible for the transaction to be
+ * not dirty but the dqinfo portion to be. All that
+ * means is that we have some (non-persistent) quota
+ * reservations that need to be unreserved.
+ */
+ xfs_trans_unreserve_and_mod_dquots(tp);
+ if (tp->t_ticket) {
+ commit_lsn = xfs_log_done(mp, tp->t_ticket,
+ NULL, log_flags);
+ if (commit_lsn == -1 && !shutdown)
+ shutdown = XFS_ERROR(EIO);
+ }
+ current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
+ xfs_trans_free_items(tp, shutdown? XFS_TRANS_ABORT : 0);
+ xfs_trans_free_busy(tp);
+ xfs_trans_free(tp);
+ XFS_STATS_INC(xs_trans_empty);
+ return (shutdown);
+ }
+ ASSERT(tp->t_ticket != NULL);
+
+ /*
+ * If we need to update the superblock, then do it now.
+ */
+ if (tp->t_flags & XFS_TRANS_SB_DIRTY)
+ xfs_trans_apply_sb_deltas(tp);
+ xfs_trans_apply_dquot_deltas(tp);
+
+ error = xfs_trans_commit_iclog(mp, tp, &commit_lsn, flags);
+ if (error == ENOMEM) {
+ xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
+ goto shut_us_down;
+ }