xfs: cleanup up xfs_log_force calling conventions
[safe/jmp/linux-2.6] / fs / xfs / xfs_log.c
index 20118dd..4f16be4 100644 (file)
@@ -79,11 +79,6 @@ STATIC int  xlog_state_release_iclog(xlog_t          *log,
 STATIC void xlog_state_switch_iclogs(xlog_t            *log,
                                     xlog_in_core_t *iclog,
                                     int                eventual_size);
-STATIC int  xlog_state_sync(xlog_t                     *log,
-                           xfs_lsn_t                   lsn,
-                           uint                        flags,
-                           int                         *log_flushed);
-STATIC int  xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed);
 STATIC void xlog_state_want_sync(xlog_t        *log, xlog_in_core_t *iclog);
 
 /* local functions to manipulate grant head */
@@ -296,65 +291,6 @@ xfs_log_done(xfs_mount_t   *mp,
        return lsn;
 }      /* xfs_log_done */
 
-
-/*
- * Force the in-core log to disk.  If flags == XFS_LOG_SYNC,
- *     the force is done synchronously.
- *
- * Asynchronous forces are implemented by setting the WANT_SYNC
- * bit in the appropriate in-core log and then returning.
- *
- * Synchronous forces are implemented with a signal variable. All callers
- * to force a given lsn to disk will wait on a the sv attached to the
- * specific in-core log.  When given in-core log finally completes its
- * write to disk, that thread will wake up all threads waiting on the
- * sv.
- */
-int
-_xfs_log_force(
-       xfs_mount_t     *mp,
-       xfs_lsn_t       lsn,
-       uint            flags,
-       int             *log_flushed)
-{
-       xlog_t          *log = mp->m_log;
-       int             dummy;
-
-       if (!log_flushed)
-               log_flushed = &dummy;
-
-       ASSERT(flags & XFS_LOG_FORCE);
-
-       XFS_STATS_INC(xs_log_force);
-
-       if (log->l_flags & XLOG_IO_ERROR)
-               return XFS_ERROR(EIO);
-       if (lsn == 0)
-               return xlog_state_sync_all(log, flags, log_flushed);
-       else
-               return xlog_state_sync(log, lsn, flags, log_flushed);
-}      /* _xfs_log_force */
-
-/*
- * Wrapper for _xfs_log_force(), to be used when caller doesn't care
- * about errors or whether the log was flushed or not. This is the normal
- * interface to use when trying to unpin items or move the log forward.
- */
-void
-xfs_log_force(
-       xfs_mount_t     *mp,
-       xfs_lsn_t       lsn,
-       uint            flags)
-{
-       int     error;
-       error = _xfs_log_force(mp, lsn, flags, NULL);
-       if (error) {
-               xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: "
-                       "error %d returned.", error);
-       }
-}
-
-
 /*
  * Attaches a new iclog I/O completion callback routine during
  * transaction commit.  If the log is in error state, a non-zero
@@ -601,7 +537,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
        if (mp->m_flags & XFS_MOUNT_RDONLY)
                return 0;
 
-       error = _xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC, NULL);
+       error = _xfs_log_force(mp, XFS_LOG_SYNC, NULL);
        ASSERT(error || !(XLOG_FORCED_SHUTDOWN(log)));
 
 #ifdef DEBUG
@@ -2853,7 +2789,6 @@ xlog_state_switch_iclogs(xlog_t           *log,
        log->l_iclog = iclog->ic_next;
 }      /* xlog_state_switch_iclogs */
 
-
 /*
  * Write out all data in the in-core log as of this exact moment in time.
  *
@@ -2881,11 +2816,17 @@ xlog_state_switch_iclogs(xlog_t         *log,
  *        b) when we return from flushing out this iclog, it is still
  *             not in the active nor dirty state.
  */
-STATIC int
-xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed)
+int
+_xfs_log_force(
+       struct xfs_mount        *mp,
+       uint                    flags,
+       int                     *log_flushed)
 {
-       xlog_in_core_t  *iclog;
-       xfs_lsn_t       lsn;
+       struct log              *log = mp->m_log;
+       struct xlog_in_core     *iclog;
+       xfs_lsn_t               lsn;
+
+       XFS_STATS_INC(xs_log_force);
 
        spin_lock(&log->l_icloglock);
 
@@ -2931,7 +2872,9 @@ xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed)
 
                                if (xlog_state_release_iclog(log, iclog))
                                        return XFS_ERROR(EIO);
-                               *log_flushed = 1;
+
+                               if (log_flushed)
+                                       *log_flushed = 1;
                                spin_lock(&log->l_icloglock);
                                if (be64_to_cpu(iclog->ic_header.h_lsn) == lsn &&
                                    iclog->ic_state != XLOG_STATE_DIRTY)
@@ -2975,19 +2918,37 @@ maybe_sleep:
                 */
                if (iclog->ic_state & XLOG_STATE_IOERROR)
                        return XFS_ERROR(EIO);
-               *log_flushed = 1;
-
+               if (log_flushed)
+                       *log_flushed = 1;
        } else {
 
 no_sleep:
                spin_unlock(&log->l_icloglock);
        }
        return 0;
-}      /* xlog_state_sync_all */
+}
 
+/*
+ * Wrapper for _xfs_log_force(), to be used when caller doesn't care
+ * about errors or whether the log was flushed or not. This is the normal
+ * interface to use when trying to unpin items or move the log forward.
+ */
+void
+xfs_log_force(
+       xfs_mount_t     *mp,
+       uint            flags)
+{
+       int     error;
+
+       error = _xfs_log_force(mp, flags, NULL);
+       if (error) {
+               xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: "
+                       "error %d returned.", error);
+       }
+}
 
 /*
- * Used by code which implements synchronous log forces.
+ * Force the in-core log to disk for a specific LSN.
  *
  * Find in-core log with lsn.
  *     If it is in the DIRTY state, just return.
@@ -2995,109 +2956,142 @@ no_sleep:
  *             state and go to sleep or return.
  *     If it is in any other state, go to sleep or return.
  *
- * If filesystem activity goes to zero, the iclog will get flushed only by
- * bdflush().
+ * Synchronous forces are implemented with a signal variable. All callers
+ * to force a given lsn to disk will wait on a the sv attached to the
+ * specific in-core log.  When given in-core log finally completes its
+ * write to disk, that thread will wake up all threads waiting on the
+ * sv.
  */
-STATIC int
-xlog_state_sync(xlog_t   *log,
-               xfs_lsn_t lsn,
-               uint      flags,
-               int       *log_flushed)
+int
+_xfs_log_force_lsn(
+       struct xfs_mount        *mp,
+       xfs_lsn_t               lsn,
+       uint                    flags,
+       int                     *log_flushed)
 {
-    xlog_in_core_t     *iclog;
-    int                        already_slept = 0;
-
-try_again:
-    spin_lock(&log->l_icloglock);
-    iclog = log->l_iclog;
+       struct log              *log = mp->m_log;
+       struct xlog_in_core     *iclog;
+       int                     already_slept = 0;
 
-    if (iclog->ic_state & XLOG_STATE_IOERROR) {
-           spin_unlock(&log->l_icloglock);
-           return XFS_ERROR(EIO);
-    }
+       ASSERT(lsn != 0);
 
-    do {
-       if (be64_to_cpu(iclog->ic_header.h_lsn) != lsn) {
-               iclog = iclog->ic_next;
-               continue;
-       }
+       XFS_STATS_INC(xs_log_force);
 
-       if (iclog->ic_state == XLOG_STATE_DIRTY) {
+try_again:
+       spin_lock(&log->l_icloglock);
+       iclog = log->l_iclog;
+       if (iclog->ic_state & XLOG_STATE_IOERROR) {
                spin_unlock(&log->l_icloglock);
-               return 0;
+               return XFS_ERROR(EIO);
        }
 
-       if (iclog->ic_state == XLOG_STATE_ACTIVE) {
-               /*
-                * We sleep here if we haven't already slept (e.g.
-                * this is the first time we've looked at the correct
-                * iclog buf) and the buffer before us is going to
-                * be sync'ed. The reason for this is that if we
-                * are doing sync transactions here, by waiting for
-                * the previous I/O to complete, we can allow a few
-                * more transactions into this iclog before we close
-                * it down.
-                *
-                * Otherwise, we mark the buffer WANT_SYNC, and bump
-                * up the refcnt so we can release the log (which drops
-                * the ref count).  The state switch keeps new transaction
-                * commits from using this buffer.  When the current commits
-                * finish writing into the buffer, the refcount will drop to
-                * zero and the buffer will go out then.
-                */
-               if (!already_slept &&
-                   (iclog->ic_prev->ic_state & (XLOG_STATE_WANT_SYNC |
-                                                XLOG_STATE_SYNCING))) {
-                       ASSERT(!(iclog->ic_state & XLOG_STATE_IOERROR));
-                       XFS_STATS_INC(xs_log_force_sleep);
-                       sv_wait(&iclog->ic_prev->ic_write_wait, PSWP,
-                               &log->l_icloglock, s);
-                       *log_flushed = 1;
-                       already_slept = 1;
-                       goto try_again;
-               } else {
+       do {
+               if (be64_to_cpu(iclog->ic_header.h_lsn) != lsn) {
+                       iclog = iclog->ic_next;
+                       continue;
+               }
+
+               if (iclog->ic_state == XLOG_STATE_DIRTY) {
+                       spin_unlock(&log->l_icloglock);
+                       return 0;
+               }
+
+               if (iclog->ic_state == XLOG_STATE_ACTIVE) {
+                       /*
+                        * We sleep here if we haven't already slept (e.g.
+                        * this is the first time we've looked at the correct
+                        * iclog buf) and the buffer before us is going to
+                        * be sync'ed. The reason for this is that if we
+                        * are doing sync transactions here, by waiting for
+                        * the previous I/O to complete, we can allow a few
+                        * more transactions into this iclog before we close
+                        * it down.
+                        *
+                        * Otherwise, we mark the buffer WANT_SYNC, and bump
+                        * up the refcnt so we can release the log (which
+                        * drops the ref count).  The state switch keeps new
+                        * transaction commits from using this buffer.  When
+                        * the current commits finish writing into the buffer,
+                        * the refcount will drop to zero and the buffer will
+                        * go out then.
+                        */
+                       if (!already_slept &&
+                           (iclog->ic_prev->ic_state &
+                            (XLOG_STATE_WANT_SYNC | XLOG_STATE_SYNCING))) {
+                               ASSERT(!(iclog->ic_state & XLOG_STATE_IOERROR));
+
+                               XFS_STATS_INC(xs_log_force_sleep);
+
+                               sv_wait(&iclog->ic_prev->ic_write_wait,
+                                       PSWP, &log->l_icloglock, s);
+                               if (log_flushed)
+                                       *log_flushed = 1;
+                               already_slept = 1;
+                               goto try_again;
+                       }
                        atomic_inc(&iclog->ic_refcnt);
                        xlog_state_switch_iclogs(log, iclog, 0);
                        spin_unlock(&log->l_icloglock);
                        if (xlog_state_release_iclog(log, iclog))
                                return XFS_ERROR(EIO);
-                       *log_flushed = 1;
+                       if (log_flushed)
+                               *log_flushed = 1;
                        spin_lock(&log->l_icloglock);
                }
-       }
 
-       if ((flags & XFS_LOG_SYNC) && /* sleep */
-           !(iclog->ic_state & (XLOG_STATE_ACTIVE | XLOG_STATE_DIRTY))) {
+               if ((flags & XFS_LOG_SYNC) && /* sleep */
+                   !(iclog->ic_state &
+                     (XLOG_STATE_ACTIVE | XLOG_STATE_DIRTY))) {
+                       /*
+                        * Don't wait on completion if we know that we've
+                        * gotten a log write error.
+                        */
+                       if (iclog->ic_state & XLOG_STATE_IOERROR) {
+                               spin_unlock(&log->l_icloglock);
+                               return XFS_ERROR(EIO);
+                       }
+                       XFS_STATS_INC(xs_log_force_sleep);
+                       sv_wait(&iclog->ic_force_wait, PSWP, &log->l_icloglock, s);
+                       /*
+                        * No need to grab the log lock here since we're
+                        * only deciding whether or not to return EIO
+                        * and the memory read should be atomic.
+                        */
+                       if (iclog->ic_state & XLOG_STATE_IOERROR)
+                               return XFS_ERROR(EIO);
 
-               /*
-                * Don't wait on completion if we know that we've
-                * gotten a log write error.
-                */
-               if (iclog->ic_state & XLOG_STATE_IOERROR) {
+                       if (log_flushed)
+                               *log_flushed = 1;
+               } else {                /* just return */
                        spin_unlock(&log->l_icloglock);
-                       return XFS_ERROR(EIO);
                }
-               XFS_STATS_INC(xs_log_force_sleep);
-               sv_wait(&iclog->ic_force_wait, PSWP, &log->l_icloglock, s);
-               /*
-                * No need to grab the log lock here since we're
-                * only deciding whether or not to return EIO
-                * and the memory read should be atomic.
-                */
-               if (iclog->ic_state & XLOG_STATE_IOERROR)
-                       return XFS_ERROR(EIO);
-               *log_flushed = 1;
-       } else {                /* just return */
-               spin_unlock(&log->l_icloglock);
-       }
-       return 0;
 
-    } while (iclog != log->l_iclog);
+               return 0;
+       } while (iclog != log->l_iclog);
 
-    spin_unlock(&log->l_icloglock);
-    return 0;
-}      /* xlog_state_sync */
+       spin_unlock(&log->l_icloglock);
+       return 0;
+}
+
+/*
+ * Wrapper for _xfs_log_force_lsn(), to be used when caller doesn't care
+ * about errors or whether the log was flushed or not. This is the normal
+ * interface to use when trying to unpin items or move the log forward.
+ */
+void
+xfs_log_force_lsn(
+       xfs_mount_t     *mp,
+       xfs_lsn_t       lsn,
+       uint            flags)
+{
+       int     error;
 
+       error = _xfs_log_force_lsn(mp, lsn, flags, NULL);
+       if (error) {
+               xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: "
+                       "error %d returned.", error);
+       }
+}
 
 /*
  * Called when we want to mark the current iclog as being ready to sync to
@@ -3462,7 +3456,6 @@ xfs_log_force_umount(
        xlog_ticket_t   *tic;
        xlog_t          *log;
        int             retval;
-       int             dummy;
 
        log = mp->m_log;
 
@@ -3536,13 +3529,14 @@ xfs_log_force_umount(
        }
        spin_unlock(&log->l_grant_lock);
 
-       if (! (log->l_iclog->ic_state & XLOG_STATE_IOERROR)) {
+       if (!(log->l_iclog->ic_state & XLOG_STATE_IOERROR)) {
                ASSERT(!logerror);
                /*
                 * Force the incore logs to disk before shutting the
                 * log down completely.
                 */
-               xlog_state_sync_all(log, XFS_LOG_FORCE|XFS_LOG_SYNC, &dummy);
+               _xfs_log_force(mp, XFS_LOG_SYNC, NULL);
+
                spin_lock(&log->l_icloglock);
                retval = xlog_state_ioerror(log);
                spin_unlock(&log->l_icloglock);