Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[safe/jmp/linux-2.6] / fs / xfs / xfs_log.c
index 91b00a5..600b5b0 100644 (file)
@@ -40,6 +40,7 @@
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_rw.h"
+#include "xfs_trace.h"
 
 kmem_zone_t    *xfs_log_ticket_zone;
 
@@ -100,12 +101,11 @@ STATIC void xlog_ungrant_log_space(xlog_t  *log,
 
 
 /* local ticket functions */
-STATIC xlog_ticket_t   *xlog_ticket_get(xlog_t *log,
+STATIC xlog_ticket_t   *xlog_ticket_alloc(xlog_t *log,
                                         int    unit_bytes,
                                         int    count,
                                         char   clientid,
                                         uint   flags);
-STATIC void            xlog_ticket_put(xlog_t *log, xlog_ticket_t *ticket);
 
 #if defined(DEBUG)
 STATIC void    xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr);
@@ -123,57 +123,6 @@ STATIC void        xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog,
 
 STATIC int     xlog_iclogs_empty(xlog_t *log);
 
-#if defined(XFS_LOG_TRACE)
-void
-xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string)
-{
-       unsigned long cnts;
-
-       if (!log->l_grant_trace) {
-               log->l_grant_trace = ktrace_alloc(2048, KM_NOSLEEP);
-               if (!log->l_grant_trace)
-                       return;
-       }
-       /* ticket counts are 1 byte each */
-       cnts = ((unsigned long)tic->t_ocnt) | ((unsigned long)tic->t_cnt) << 8;
-
-       ktrace_enter(log->l_grant_trace,
-                    (void *)tic,
-                    (void *)log->l_reserve_headq,
-                    (void *)log->l_write_headq,
-                    (void *)((unsigned long)log->l_grant_reserve_cycle),
-                    (void *)((unsigned long)log->l_grant_reserve_bytes),
-                    (void *)((unsigned long)log->l_grant_write_cycle),
-                    (void *)((unsigned long)log->l_grant_write_bytes),
-                    (void *)((unsigned long)log->l_curr_cycle),
-                    (void *)((unsigned long)log->l_curr_block),
-                    (void *)((unsigned long)CYCLE_LSN(log->l_tail_lsn)),
-                    (void *)((unsigned long)BLOCK_LSN(log->l_tail_lsn)),
-                    (void *)string,
-                    (void *)((unsigned long)tic->t_trans_type),
-                    (void *)cnts,
-                    (void *)((unsigned long)tic->t_curr_res),
-                    (void *)((unsigned long)tic->t_unit_res));
-}
-
-void
-xlog_trace_iclog(xlog_in_core_t *iclog, uint state)
-{
-       if (!iclog->ic_trace)
-               iclog->ic_trace = ktrace_alloc(256, KM_SLEEP);
-       ktrace_enter(iclog->ic_trace,
-                    (void *)((unsigned long)state),
-                    (void *)((unsigned long)current_pid()),
-                    (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
-                    (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
-                    (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
-                    (void *)NULL, (void *)NULL);
-}
-#else
-#define        xlog_trace_loggrant(log,tic,string)
-#define        xlog_trace_iclog(iclog,state)
-#endif /* XFS_LOG_TRACE */
-
 
 static void
 xlog_ins_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic)
@@ -326,25 +275,24 @@ xfs_log_done(xfs_mount_t  *mp,
 
        if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) == 0 ||
            (flags & XFS_LOG_REL_PERM_RESERV)) {
+               trace_xfs_log_done_nonperm(log, ticket);
+
                /*
                 * Release ticket if not permanent reservation or a specific
                 * request has been made to release a permanent reservation.
                 */
-               xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)");
                xlog_ungrant_log_space(log, ticket);
-               xlog_ticket_put(log, ticket);
+               xfs_log_ticket_put(ticket);
        } else {
-               xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)");
-               xlog_regrant_reserve_log_space(log, ticket);
-       }
+               trace_xfs_log_done_perm(log, ticket);
 
-       /* If this ticket was a permanent reservation and we aren't
-        * trying to release it, reset the inited flags; so next time
-        * we write, a start record will be written out.
-        */
-       if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) &&
-           (flags & XFS_LOG_REL_PERM_RESERV) == 0)
+               xlog_regrant_reserve_log_space(log, ticket);
+               /* If this ticket was a permanent reservation and we aren't
+                * trying to release it, reset the inited flags; so next time
+                * we write, a start record will be written out.
+                */
                ticket->t_flags |= XLOG_TIC_INITED;
+       }
 
        return lsn;
 }      /* xfs_log_done */
@@ -357,11 +305,11 @@ xfs_log_done(xfs_mount_t  *mp,
  * 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 semaphore.  All callers
- * to force a given lsn to disk will wait on a semaphore attached to the
+ * 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
- * semaphore.
+ * sv.
  */
 int
 _xfs_log_force(
@@ -481,24 +429,26 @@ xfs_log_reserve(xfs_mount_t        *mp,
 
        XFS_STATS_INC(xs_try_logspace);
 
+
        if (*ticket != NULL) {
                ASSERT(flags & XFS_LOG_PERM_RESERV);
                internal_ticket = (xlog_ticket_t *)*ticket;
-               xlog_trace_loggrant(log, internal_ticket, "xfs_log_reserve: existing ticket (permanent trans)");
+
+               trace_xfs_log_reserve(log, internal_ticket);
+
                xlog_grant_push_ail(mp, internal_ticket->t_unit_res);
                retval = xlog_regrant_write_log_space(log, internal_ticket);
        } else {
                /* may sleep if need to allocate more tickets */
-               internal_ticket = xlog_ticket_get(log, unit_bytes, cnt,
+               internal_ticket = xlog_ticket_alloc(log, unit_bytes, cnt,
                                                  client, flags);
                if (!internal_ticket)
                        return XFS_ERROR(ENOMEM);
                internal_ticket->t_trans_type = t_type;
                *ticket = internal_ticket;
-               xlog_trace_loggrant(log, internal_ticket, 
-                       (internal_ticket->t_flags & XLOG_TIC_PERM_RESERV) ?
-                       "xfs_log_reserve: create new ticket (permanent trans)" :
-                       "xfs_log_reserve: create new ticket");
+
+               trace_xfs_log_reserve(log, internal_ticket);
+
                xlog_grant_push_ail(mp,
                                    (internal_ticket->t_unit_res *
                                     internal_ticket->t_cnt));
@@ -538,16 +488,20 @@ xfs_log_mount(
        }
 
        mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
+       if (IS_ERR(mp->m_log)) {
+               error = -PTR_ERR(mp->m_log);
+               goto out;
+       }
 
        /*
         * Initialize the AIL now we have a log.
         */
-       spin_lock_init(&mp->m_ail_lock);
        error = xfs_trans_ail_init(mp);
        if (error) {
                cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error);
-               goto error;
+               goto out_free_log;
        }
+       mp->m_log->l_ailp = mp->m_ail;
 
        /*
         * skip log recovery on a norecovery mount.  pretend it all
@@ -565,19 +519,22 @@ xfs_log_mount(
                        mp->m_flags |= XFS_MOUNT_RDONLY;
                if (error) {
                        cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
-                       goto error;
+                       goto out_destroy_ail;
                }
        }
 
        /* Normal transactions can now occur */
        mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY;
 
-       /* End mounting message in xfs_log_mount_finish */
        return 0;
-error:
-       xfs_log_unmount_dealloc(mp);
+
+out_destroy_ail:
+       xfs_trans_ail_destroy(mp);
+out_free_log:
+       xlog_dealloc_log(mp->m_log);
+out:
        return error;
-}      /* xfs_log_mount */
+}
 
 /*
  * Finish the recovery of the file system.  This is separate from
@@ -588,12 +545,12 @@ error:
  * mp          - ubiquitous xfs mount point structure
  */
 int
-xfs_log_mount_finish(xfs_mount_t *mp, int mfsi_flags)
+xfs_log_mount_finish(xfs_mount_t *mp)
 {
        int     error;
 
        if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
-               error = xlog_recover_finish(mp->m_log, mfsi_flags);
+               error = xlog_recover_finish(mp->m_log);
        else {
                error = 0;
                ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
@@ -603,19 +560,6 @@ xfs_log_mount_finish(xfs_mount_t *mp, int mfsi_flags)
 }
 
 /*
- * Unmount processing for the log.
- */
-int
-xfs_log_unmount(xfs_mount_t *mp)
-{
-       int             error;
-
-       error = xfs_log_unmount_write(mp);
-       xfs_log_unmount_dealloc(mp);
-       return error;
-}
-
-/*
  * Final log writes as part of unmount.
  *
  * Mark the filesystem clean as unmount happens.  Note that during relocation
@@ -699,15 +643,15 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                spin_lock(&log->l_icloglock);
                iclog = log->l_iclog;
                atomic_inc(&iclog->ic_refcnt);
-               spin_unlock(&log->l_icloglock);
                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)) {
-                               sv_wait(&iclog->ic_forcesema, PMEM,
+                               sv_wait(&iclog->ic_force_wait, PMEM,
                                        &log->l_icloglock, s);
                        } else {
                                spin_unlock(&log->l_icloglock);
@@ -716,9 +660,9 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                        spin_unlock(&log->l_icloglock);
                }
                if (tic) {
-                       xlog_trace_loggrant(log, tic, "unmount rec");
+                       trace_xfs_log_umount_write(log, tic);
                        xlog_ungrant_log_space(log, tic);
-                       xlog_ticket_put(log, tic);
+                       xfs_log_ticket_put(tic);
                }
        } else {
                /*
@@ -737,9 +681,9 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                spin_lock(&log->l_icloglock);
                iclog = log->l_iclog;
                atomic_inc(&iclog->ic_refcnt);
-               spin_unlock(&log->l_icloglock);
 
                xlog_state_want_sync(log, iclog);
+               spin_unlock(&log->l_icloglock);
                error =  xlog_state_release_iclog(log, iclog);
 
                spin_lock(&log->l_icloglock);
@@ -748,7 +692,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                        || iclog->ic_state == XLOG_STATE_DIRTY
                        || iclog->ic_state == XLOG_STATE_IOERROR) ) {
 
-                               sv_wait(&iclog->ic_forcesema, PMEM,
+                               sv_wait(&iclog->ic_force_wait, PMEM,
                                        &log->l_icloglock, s);
                } else {
                        spin_unlock(&log->l_icloglock);
@@ -765,7 +709,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
  * and deallocate the log as the aild references the log.
  */
 void
-xfs_log_unmount_dealloc(xfs_mount_t *mp)
+xfs_log_unmount(xfs_mount_t *mp)
 {
        xfs_trans_ail_destroy(mp);
        xlog_dealloc_log(mp->m_log);
@@ -838,7 +782,7 @@ xfs_log_move_tail(xfs_mount_t       *mp,
                                break;
                        tail_lsn = 0;
                        free_bytes -= tic->t_unit_res;
-                       sv_signal(&tic->t_sema);
+                       sv_signal(&tic->t_wait);
                        tic = tic->t_next;
                } while (tic != log->l_write_headq);
        }
@@ -859,7 +803,7 @@ xfs_log_move_tail(xfs_mount_t       *mp,
                                break;
                        tail_lsn = 0;
                        free_bytes -= need_bytes;
-                       sv_signal(&tic->t_sema);
+                       sv_signal(&tic->t_wait);
                        tic = tic->t_next;
                } while (tic != log->l_reserve_headq);
        }
@@ -875,7 +819,7 @@ xfs_log_move_tail(xfs_mount_t       *mp,
 int
 xfs_log_need_covered(xfs_mount_t *mp)
 {
-       int             needed = 0, gen;
+       int             needed = 0;
        xlog_t          *log = mp->m_log;
 
        if (!xfs_fs_writable(mp))
@@ -884,7 +828,7 @@ xfs_log_need_covered(xfs_mount_t *mp)
        spin_lock(&log->l_icloglock);
        if (((log->l_covered_state == XLOG_STATE_COVER_NEED) ||
                (log->l_covered_state == XLOG_STATE_COVER_NEED2))
-                       && !xfs_trans_first_ail(mp, &gen)
+                       && !xfs_trans_ail_tail(log->l_ailp)
                        && xlog_iclogs_empty(log)) {
                if (log->l_covered_state == XLOG_STATE_COVER_NEED)
                        log->l_covered_state = XLOG_STATE_COVER_DONE;
@@ -921,7 +865,7 @@ xlog_assign_tail_lsn(xfs_mount_t *mp)
        xfs_lsn_t tail_lsn;
        xlog_t    *log = mp->m_log;
 
-       tail_lsn = xfs_trans_tail_ail(mp);
+       tail_lsn = xfs_trans_ail_tail(mp->m_ail);
        spin_lock(&log->l_grant_lock);
        if (tail_lsn != 0) {
                log->l_tail_lsn = tail_lsn;
@@ -999,25 +943,19 @@ xlog_iodone(xfs_buf_t *bp)
        ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long) 2);
        XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
        aborted = 0;
-
-       /*
-        * Some versions of cpp barf on the recursive definition of
-        * ic_log -> hic_fields.ic_log and expand ic_log twice when
-        * it is passed through two macros.  Workaround broken cpp.
-        */
        l = iclog->ic_log;
 
        /*
-        * If the ordered flag has been removed by a lower
-        * layer, it means the underlyin device no longer supports
+        * If the _XFS_BARRIER_FAILED flag was set by a lower
+        * layer, it means the underlying device no longer supports
         * barrier I/O. Warn loudly and turn off barriers.
         */
-       if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ORDERED(bp)) {
+       if (bp->b_flags & _XFS_BARRIER_FAILED) {
+               bp->b_flags &= ~_XFS_BARRIER_FAILED;
                l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER;
                xfs_fs_cmn_err(CE_WARN, l->l_mp,
                                "xlog_iodone: Barriers are no longer supported"
                                " by device. Disabling barriers\n");
-               xfs_buftrace("XLOG_IODONE BARRIERS OFF", bp);
        }
 
        /*
@@ -1072,19 +1010,16 @@ xlog_bdstrat_cb(struct xfs_buf *bp)
                return 0;
        }
 
-       xfs_buftrace("XLOG__BDSTRAT IOERROR", bp);
        XFS_BUF_ERROR(bp, EIO);
        XFS_BUF_STALE(bp);
        xfs_biodone(bp);
        return XFS_ERROR(EIO);
-
-
 }
 
 /*
  * Return size of each in-core log record buffer.
  *
- * All machines get 8 x 32KB buffers by default, unless tuned otherwise.
+ * All machines get 8 x 32kB buffers by default, unless tuned otherwise.
  *
  * If the filesystem blocksize is too large, we may need to choose a
  * larger size since the directory code currently logs entire blocks.
@@ -1114,8 +1049,8 @@ xlog_get_iclog_buffer_size(xfs_mount_t    *mp,
                }
 
                if (xfs_sb_version_haslogv2(&mp->m_sb)) {
-                       /* # headers = size / 32K
-                        * one header holds cycles from 32K of data
+                       /* # headers = size / 32k
+                        * one header holds cycles from 32k of data
                         */
 
                        xhdrs = mp->m_logbsize / XLOG_HEADER_CYCLE_SIZE;
@@ -1131,7 +1066,7 @@ xlog_get_iclog_buffer_size(xfs_mount_t    *mp,
                goto done;
        }
 
-       /* All machines use 32KB buffers by default. */
+       /* All machines use 32kB buffers by default. */
        log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;
        log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
 
@@ -1139,32 +1074,8 @@ xlog_get_iclog_buffer_size(xfs_mount_t   *mp,
        log->l_iclog_hsize = BBSIZE;
        log->l_iclog_heads = 1;
 
-       /*
-        * For 16KB, we use 3 32KB buffers.  For 32KB block sizes, we use
-        * 4 32KB buffers.  For 64KB block sizes, we use 8 32KB buffers.
-        */
-       if (mp->m_sb.sb_blocksize >= 16*1024) {
-               log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;
-               log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
-               if (mp->m_logbufs <= 0) {
-                       switch (mp->m_sb.sb_blocksize) {
-                           case 16*1024:                       /* 16 KB */
-                               log->l_iclog_bufs = 3;
-                               break;
-                           case 32*1024:                       /* 32 KB */
-                               log->l_iclog_bufs = 4;
-                               break;
-                           case 64*1024:                       /* 64 KB */
-                               log->l_iclog_bufs = 8;
-                               break;
-                           default:
-                               xlog_panic("XFS: Invalid blocksize");
-                               break;
-                       }
-               }
-       }
-
-done:  /* are we being asked to make the sizes selected above visible? */
+done:
+       /* are we being asked to make the sizes selected above visible? */
        if (mp->m_logbufs == 0)
                mp->m_logbufs = log->l_iclog_bufs;
        if (mp->m_logbsize == 0)
@@ -1190,8 +1101,13 @@ xlog_alloc_log(xfs_mount_t       *mp,
        xfs_buf_t               *bp;
        int                     i;
        int                     iclogsize;
+       int                     error = ENOMEM;
 
-       log = (xlog_t *)kmem_zalloc(sizeof(xlog_t), KM_SLEEP);
+       log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL);
+       if (!log) {
+               xlog_warn("XFS: Log allocation failed: No memory!");
+               goto out;
+       }
 
        log->l_mp          = mp;
        log->l_targ        = log_target;
@@ -1209,20 +1125,38 @@ xlog_alloc_log(xfs_mount_t      *mp,
        log->l_grant_reserve_cycle = 1;
        log->l_grant_write_cycle = 1;
 
+       error = EFSCORRUPTED;
        if (xfs_sb_version_hassector(&mp->m_sb)) {
                log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT;
-               ASSERT(log->l_sectbb_log <= mp->m_sectbb_log);
+               if (log->l_sectbb_log < 0 ||
+                   log->l_sectbb_log > mp->m_sectbb_log) {
+                       xlog_warn("XFS: Log sector size (0x%x) out of range.",
+                                               log->l_sectbb_log);
+                       goto out_free_log;
+               }
+
                /* for larger sector sizes, must have v2 or external log */
-               ASSERT(log->l_sectbb_log == 0 ||
-                       log->l_logBBstart == 0 ||
-                       xfs_sb_version_haslogv2(&mp->m_sb));
-               ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT);
+               if (log->l_sectbb_log != 0 &&
+                   (log->l_logBBstart != 0 &&
+                    !xfs_sb_version_haslogv2(&mp->m_sb))) {
+                       xlog_warn("XFS: log sector size (0x%x) invalid "
+                                 "for configuration.", log->l_sectbb_log);
+                       goto out_free_log;
+               }
+               if (mp->m_sb.sb_logsectlog < BBSHIFT) {
+                       xlog_warn("XFS: Log sector log (0x%x) too small.",
+                                               mp->m_sb.sb_logsectlog);
+                       goto out_free_log;
+               }
        }
        log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1;
 
        xlog_get_iclog_buffer_size(mp, log);
 
+       error = ENOMEM;
        bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
+       if (!bp)
+               goto out_free_log;
        XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
        XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
        XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
@@ -1248,20 +1182,24 @@ xlog_alloc_log(xfs_mount_t      *mp,
        iclogsize = log->l_iclog_size;
        ASSERT(log->l_iclog_size >= 4096);
        for (i=0; i < log->l_iclog_bufs; i++) {
-               *iclogp = (xlog_in_core_t *)
-                         kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
+               *iclogp = kmem_zalloc(sizeof(xlog_in_core_t), KM_MAYFAIL);
+               if (!*iclogp)
+                       goto out_free_iclog;
+
                iclog = *iclogp;
                iclog->ic_prev = prev_iclog;
                prev_iclog = iclog;
 
                bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
+               if (!bp)
+                       goto out_free_iclog;
                if (!XFS_BUF_CPSEMA(bp))
                        ASSERT(0);
                XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
                XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
                XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
                iclog->ic_bp = bp;
-               iclog->hic_data = bp->b_addr;
+               iclog->ic_data = bp->b_addr;
 #ifdef DEBUG
                log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header);
 #endif
@@ -1281,12 +1219,12 @@ xlog_alloc_log(xfs_mount_t      *mp,
                atomic_set(&iclog->ic_refcnt, 0);
                spin_lock_init(&iclog->ic_callback_lock);
                iclog->ic_callback_tail = &(iclog->ic_callback);
-               iclog->ic_datap = (char *)iclog->hic_data + log->l_iclog_hsize;
+               iclog->ic_datap = (char *)iclog->ic_data + log->l_iclog_hsize;
 
                ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp));
                ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0);
-               sv_init(&iclog->ic_forcesema, SV_DEFAULT, "iclog-force");
-               sv_init(&iclog->ic_writesema, SV_DEFAULT, "iclog-write");
+               sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force");
+               sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write");
 
                iclogp = &iclog->ic_next;
        }
@@ -1294,6 +1232,24 @@ xlog_alloc_log(xfs_mount_t       *mp,
        log->l_iclog->ic_prev = prev_iclog;     /* re-write 1st prev ptr */
 
        return log;
+
+out_free_iclog:
+       for (iclog = log->l_iclog; iclog; iclog = prev_iclog) {
+               prev_iclog = iclog->ic_next;
+               if (iclog->ic_bp) {
+                       sv_destroy(&iclog->ic_force_wait);
+                       sv_destroy(&iclog->ic_write_wait);
+                       xfs_buf_free(iclog->ic_bp);
+               }
+               kmem_free(iclog);
+       }
+       spinlock_destroy(&log->l_icloglock);
+       spinlock_destroy(&log->l_grant_lock);
+       xfs_buf_free(log->l_xbuf);
+out_free_log:
+       kmem_free(log);
+out:
+       return ERR_PTR(-error);
 }      /* xlog_alloc_log */
 
 
@@ -1384,7 +1340,7 @@ xlog_grant_push_ail(xfs_mount_t   *mp,
      */
     if (threshold_lsn &&
        !XLOG_FORCED_SHUTDOWN(log))
-           xfs_trans_push_ail(mp, threshold_lsn);
+           xfs_trans_ail_push(log->l_ailp, threshold_lsn);
 }      /* xlog_grant_push_ail */
 
 
@@ -1485,6 +1441,7 @@ xlog_sync(xlog_t          *log,
        XFS_BUF_ZEROFLAGS(bp);
        XFS_BUF_BUSY(bp);
        XFS_BUF_ASYNC(bp);
+       bp->b_flags |= XBF_LOG_BUFFER;
        /*
         * Do an ordered write for the log block.
         * Its unnecessary to flush the first split block in the log wrap case.
@@ -1522,6 +1479,7 @@ xlog_sync(xlog_t          *log,
                XFS_BUF_ZEROFLAGS(bp);
                XFS_BUF_BUSY(bp);
                XFS_BUF_ASYNC(bp);
+               bp->b_flags |= XBF_LOG_BUFFER;
                if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
                        XFS_BUF_ORDERED(bp);
                dptr = XFS_BUF_PTR(bp);
@@ -1565,14 +1523,9 @@ xlog_dealloc_log(xlog_t *log)
 
        iclog = log->l_iclog;
        for (i=0; i<log->l_iclog_bufs; i++) {
-               sv_destroy(&iclog->ic_forcesema);
-               sv_destroy(&iclog->ic_writesema);
+               sv_destroy(&iclog->ic_force_wait);
+               sv_destroy(&iclog->ic_write_wait);
                xfs_buf_free(iclog->ic_bp);
-#ifdef XFS_LOG_TRACE
-               if (iclog->ic_trace != NULL) {
-                       ktrace_free(iclog->ic_trace);
-               }
-#endif
                next_iclog = iclog->ic_next;
                kmem_free(iclog);
                iclog = next_iclog;
@@ -1581,14 +1534,6 @@ xlog_dealloc_log(xlog_t *log)
        spinlock_destroy(&log->l_grant_lock);
 
        xfs_buf_free(log->l_xbuf);
-#ifdef XFS_LOG_TRACE
-       if (log->l_trace != NULL) {
-               ktrace_free(log->l_trace);
-       }
-       if (log->l_grant_trace != NULL) {
-               ktrace_free(log->l_grant_trace);
-       }
-#endif
        log->l_mp->m_log = NULL;
        kmem_free(log);
 }      /* xlog_dealloc_log */
@@ -1940,7 +1885,9 @@ xlog_write(xfs_mount_t *  mp,
                if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) {
                    xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
                    record_cnt = data_cnt = 0;
+                   spin_lock(&log->l_icloglock);
                    xlog_state_want_sync(log, iclog);
+                   spin_unlock(&log->l_icloglock);
                    if (commit_iclog) {
                        ASSERT(flags & XLOG_COMMIT_TRANS);
                        *commit_iclog = iclog;
@@ -1976,7 +1923,7 @@ xlog_write(xfs_mount_t *  mp,
 /* Clean iclogs starting from the head.  This ordering must be
  * maintained, so an iclog doesn't become ACTIVE beyond one that
  * is SYNCING.  This is also required to maintain the notion that we use
- * a counting semaphore to hold off would be writers to the log when every
+ * a ordered wait queue to hold off would be writers to the log when every
  * iclog is trying to sync to disk.
  *
  * State Change: DIRTY -> ACTIVE
@@ -2240,7 +2187,7 @@ xlog_state_do_callback(
                        xlog_state_clean_log(log);
 
                        /* wake up threads waiting in xfs_log_force() */
-                       sv_broadcast(&iclog->ic_forcesema);
+                       sv_broadcast(&iclog->ic_force_wait);
 
                        iclog = iclog->ic_next;
                } while (first_iclog != iclog);
@@ -2302,8 +2249,7 @@ xlog_state_do_callback(
  * the second completion goes through.
  *
  * Callbacks could take time, so they are done outside the scope of the
- * global state machine log lock.  Assume that the calls to cvsema won't
- * take a long time.  At least we know it won't sleep.
+ * global state machine log lock.
  */
 STATIC void
 xlog_state_done_syncing(
@@ -2339,7 +2285,7 @@ xlog_state_done_syncing(
         * iclog buffer, we wake them all, one will get to do the
         * I/O, the others get to wait for the result.
         */
-       sv_broadcast(&iclog->ic_writesema);
+       sv_broadcast(&iclog->ic_write_wait);
        spin_unlock(&log->l_icloglock);
        xlog_state_do_callback(log, aborted, iclog);    /* also cleans log */
 }      /* xlog_state_done_syncing */
@@ -2347,11 +2293,9 @@ xlog_state_done_syncing(
 
 /*
  * If the head of the in-core log ring is not (ACTIVE or DIRTY), then we must
- * sleep.  The flush semaphore is set to the number of in-core buffers and
- * decremented around disk syncing.  Therefore, if all buffers are syncing,
- * this semaphore will cause new writes to sleep until a sync completes.
- * Otherwise, this code just does p() followed by v().  This approximates
- * a sleep/wakeup except we can't race.
+ * sleep.  We wait on the flush queue on the head iclog as that should be
+ * the first iclog to complete flushing. Hence if all iclogs are syncing,
+ * we will wait here and all new writes will sleep until a sync completes.
  *
  * The in-core logs are used in a circular fashion. They are not used
  * out-of-order even when an iclog past the head is free.
@@ -2387,7 +2331,6 @@ restart:
 
        iclog = log->l_iclog;
        if (iclog->ic_state != XLOG_STATE_ACTIVE) {
-               xlog_trace_iclog(iclog, XLOG_TRACE_SLEEP_FLUSH);
                XFS_STATS_INC(xs_log_noiclogs);
 
                /* Wait for log writes to have flushed */
@@ -2493,13 +2436,15 @@ xlog_grant_log_space(xlog_t        *log,
 
        /* Is there space or do we need to sleep? */
        spin_lock(&log->l_grant_lock);
-       xlog_trace_loggrant(log, tic, "xlog_grant_log_space: enter");
+
+       trace_xfs_log_grant_enter(log, tic);
 
        /* something is already sleeping; insert new transaction at end */
        if (log->l_reserve_headq) {
                xlog_ins_ticketq(&log->l_reserve_headq, tic);
-               xlog_trace_loggrant(log, tic,
-                                   "xlog_grant_log_space: sleep 1");
+
+               trace_xfs_log_grant_sleep1(log, tic);
+
                /*
                 * Gotta check this before going to sleep, while we're
                 * holding the grant lock.
@@ -2508,13 +2453,12 @@ xlog_grant_log_space(xlog_t        *log,
                        goto error_return;
 
                XFS_STATS_INC(xs_sleep_logspace);
-               sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
+               sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
                /*
                 * If we got an error, and the filesystem is shutting down,
                 * we'll catch it down below. So just continue...
                 */
-               xlog_trace_loggrant(log, tic,
-                                   "xlog_grant_log_space: wake 1");
+               trace_xfs_log_grant_wake1(log, tic);
                spin_lock(&log->l_grant_lock);
        }
        if (tic->t_flags & XFS_LOG_PERM_RESERV)
@@ -2531,20 +2475,22 @@ redo:
        if (free_bytes < need_bytes) {
                if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
                        xlog_ins_ticketq(&log->l_reserve_headq, tic);
-               xlog_trace_loggrant(log, tic,
-                                   "xlog_grant_log_space: sleep 2");
-               XFS_STATS_INC(xs_sleep_logspace);
-               sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
 
-               if (XLOG_FORCED_SHUTDOWN(log)) {
-                       spin_lock(&log->l_grant_lock);
-                       goto error_return;
-               }
+               trace_xfs_log_grant_sleep2(log, tic);
 
-               xlog_trace_loggrant(log, tic,
-                                   "xlog_grant_log_space: wake 2");
+               spin_unlock(&log->l_grant_lock);
                xlog_grant_push_ail(log->l_mp, need_bytes);
                spin_lock(&log->l_grant_lock);
+
+               XFS_STATS_INC(xs_sleep_logspace);
+               sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
+
+               spin_lock(&log->l_grant_lock);
+               if (XLOG_FORCED_SHUTDOWN(log))
+                       goto error_return;
+
+               trace_xfs_log_grant_wake2(log, tic);
+
                goto redo;
        } else if (tic->t_flags & XLOG_TIC_IN_Q)
                xlog_del_ticketq(&log->l_reserve_headq, tic);
@@ -2564,7 +2510,7 @@ redo:
                ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn)));
        }
 #endif
-       xlog_trace_loggrant(log, tic, "xlog_grant_log_space: exit");
+       trace_xfs_log_grant_exit(log, tic);
        xlog_verify_grant_head(log, 1);
        spin_unlock(&log->l_grant_lock);
        return 0;
@@ -2572,7 +2518,9 @@ redo:
  error_return:
        if (tic->t_flags & XLOG_TIC_IN_Q)
                xlog_del_ticketq(&log->l_reserve_headq, tic);
-       xlog_trace_loggrant(log, tic, "xlog_grant_log_space: err_ret");
+
+       trace_xfs_log_grant_error(log, tic);
+
        /*
         * If we are failing, make sure the ticket doesn't have any
         * current reservations. We don't want to add this back when
@@ -2612,7 +2560,8 @@ xlog_regrant_write_log_space(xlog_t          *log,
 #endif
 
        spin_lock(&log->l_grant_lock);
-       xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: enter");
+
+       trace_xfs_log_regrant_write_enter(log, tic);
 
        if (XLOG_FORCED_SHUTDOWN(log))
                goto error_return;
@@ -2623,7 +2572,7 @@ xlog_regrant_write_log_space(xlog_t          *log,
         * for more free space, otherwise try to get some space for
         * this transaction.
         */
-
+       need_bytes = tic->t_unit_res;
        if ((ntic = log->l_write_headq)) {
                free_bytes = xlog_space_left(log, log->l_grant_write_cycle,
                                             log->l_grant_write_bytes);
@@ -2633,7 +2582,7 @@ xlog_regrant_write_log_space(xlog_t          *log,
                        if (free_bytes < ntic->t_unit_res)
                                break;
                        free_bytes -= ntic->t_unit_res;
-                       sv_signal(&ntic->t_sema);
+                       sv_signal(&ntic->t_wait);
                        ntic = ntic->t_next;
                } while (ntic != log->l_write_headq);
 
@@ -2641,28 +2590,26 @@ xlog_regrant_write_log_space(xlog_t        *log,
                        if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
                                xlog_ins_ticketq(&log->l_write_headq, tic);
 
-                       xlog_trace_loggrant(log, tic,
-                                   "xlog_regrant_write_log_space: sleep 1");
+                       trace_xfs_log_regrant_write_sleep1(log, tic);
+
+                       spin_unlock(&log->l_grant_lock);
+                       xlog_grant_push_ail(log->l_mp, need_bytes);
+                       spin_lock(&log->l_grant_lock);
+
                        XFS_STATS_INC(xs_sleep_logspace);
-                       sv_wait(&tic->t_sema, PINOD|PLTWAIT,
+                       sv_wait(&tic->t_wait, PINOD|PLTWAIT,
                                &log->l_grant_lock, s);
 
                        /* If we're shutting down, this tic is already
                         * off the queue */
-                       if (XLOG_FORCED_SHUTDOWN(log)) {
-                               spin_lock(&log->l_grant_lock);
+                       spin_lock(&log->l_grant_lock);
+                       if (XLOG_FORCED_SHUTDOWN(log))
                                goto error_return;
-                       }
 
-                       xlog_trace_loggrant(log, tic,
-                                   "xlog_regrant_write_log_space: wake 1");
-                       xlog_grant_push_ail(log->l_mp, tic->t_unit_res);
-                       spin_lock(&log->l_grant_lock);
+                       trace_xfs_log_regrant_write_wake1(log, tic);
                }
        }
 
-       need_bytes = tic->t_unit_res;
-
 redo:
        if (XLOG_FORCED_SHUTDOWN(log))
                goto error_return;
@@ -2672,19 +2619,21 @@ redo:
        if (free_bytes < need_bytes) {
                if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
                        xlog_ins_ticketq(&log->l_write_headq, tic);
+               spin_unlock(&log->l_grant_lock);
+               xlog_grant_push_ail(log->l_mp, need_bytes);
+               spin_lock(&log->l_grant_lock);
+
                XFS_STATS_INC(xs_sleep_logspace);
-               sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
+               trace_xfs_log_regrant_write_sleep2(log, tic);
+
+               sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
 
                /* If we're shutting down, this tic is already off the queue */
-               if (XLOG_FORCED_SHUTDOWN(log)) {
-                       spin_lock(&log->l_grant_lock);
+               spin_lock(&log->l_grant_lock);
+               if (XLOG_FORCED_SHUTDOWN(log))
                        goto error_return;
-               }
 
-               xlog_trace_loggrant(log, tic,
-                                   "xlog_regrant_write_log_space: wake 2");
-               xlog_grant_push_ail(log->l_mp, need_bytes);
-               spin_lock(&log->l_grant_lock);
+               trace_xfs_log_regrant_write_wake2(log, tic);
                goto redo;
        } else if (tic->t_flags & XLOG_TIC_IN_Q)
                xlog_del_ticketq(&log->l_write_headq, tic);
@@ -2699,7 +2648,8 @@ redo:
        }
 #endif
 
-       xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: exit");
+       trace_xfs_log_regrant_write_exit(log, tic);
+
        xlog_verify_grant_head(log, 1);
        spin_unlock(&log->l_grant_lock);
        return 0;
@@ -2708,7 +2658,9 @@ redo:
  error_return:
        if (tic->t_flags & XLOG_TIC_IN_Q)
                xlog_del_ticketq(&log->l_reserve_headq, tic);
-       xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: err_ret");
+
+       trace_xfs_log_regrant_write_error(log, tic);
+
        /*
         * If we are failing, make sure the ticket doesn't have any
         * current reservations. We don't want to add this back when
@@ -2732,8 +2684,8 @@ STATIC void
 xlog_regrant_reserve_log_space(xlog_t       *log,
                               xlog_ticket_t *ticket)
 {
-       xlog_trace_loggrant(log, ticket,
-                           "xlog_regrant_reserve_log_space: enter");
+       trace_xfs_log_regrant_reserve_enter(log, ticket);
+
        if (ticket->t_cnt > 0)
                ticket->t_cnt--;
 
@@ -2741,8 +2693,9 @@ xlog_regrant_reserve_log_space(xlog_t          *log,
        xlog_grant_sub_space(log, ticket->t_curr_res);
        ticket->t_curr_res = ticket->t_unit_res;
        xlog_tic_reset_res(ticket);
-       xlog_trace_loggrant(log, ticket,
-                           "xlog_regrant_reserve_log_space: sub current res");
+
+       trace_xfs_log_regrant_reserve_sub(log, ticket);
+
        xlog_verify_grant_head(log, 1);
 
        /* just return if we still have some of the pre-reserved space */
@@ -2752,8 +2705,9 @@ xlog_regrant_reserve_log_space(xlog_t          *log,
        }
 
        xlog_grant_add_space_reserve(log, ticket->t_unit_res);
-       xlog_trace_loggrant(log, ticket,
-                           "xlog_regrant_reserve_log_space: exit");
+
+       trace_xfs_log_regrant_reserve_exit(log, ticket);
+
        xlog_verify_grant_head(log, 0);
        spin_unlock(&log->l_grant_lock);
        ticket->t_curr_res = ticket->t_unit_res;
@@ -2783,11 +2737,11 @@ xlog_ungrant_log_space(xlog_t        *log,
                ticket->t_cnt--;
 
        spin_lock(&log->l_grant_lock);
-       xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: enter");
+       trace_xfs_log_ungrant_enter(log, ticket);
 
        xlog_grant_sub_space(log, ticket->t_curr_res);
 
-       xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: sub current");
+       trace_xfs_log_ungrant_sub(log, ticket);
 
        /* If this is a permanent reservation ticket, we may be able to free
         * up more space based on the remaining count.
@@ -2797,7 +2751,8 @@ xlog_ungrant_log_space(xlog_t          *log,
                xlog_grant_sub_space(log, ticket->t_unit_res*ticket->t_cnt);
        }
 
-       xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: exit");
+       trace_xfs_log_ungrant_exit(log, ticket);
+
        xlog_verify_grant_head(log, 1);
        spin_unlock(&log->l_grant_lock);
        xfs_log_move_tail(log->l_mp, 1);
@@ -2916,7 +2871,7 @@ xlog_state_switch_iclogs(xlog_t           *log,
  *     2. the current iclog is drity, and the previous iclog is in the
  *             active or dirty state.
  *
- * We may sleep (call psema) if:
+ * We may sleep if:
  *
  *     1. the current iclog is not in the active nor dirty state.
  *     2. the current iclog dirty, and the previous iclog is not in the
@@ -3013,7 +2968,7 @@ maybe_sleep:
                        return XFS_ERROR(EIO);
                }
                XFS_STATS_INC(xs_log_force_sleep);
-               sv_wait(&iclog->ic_forcesema, PINOD, &log->l_icloglock, s);
+               sv_wait(&iclog->ic_force_wait, PINOD, &log->l_icloglock, s);
                /*
                 * No need to grab the log lock here since we're
                 * only deciding whether or not to return EIO
@@ -3096,7 +3051,7 @@ try_again:
                                                 XLOG_STATE_SYNCING))) {
                        ASSERT(!(iclog->ic_state & XLOG_STATE_IOERROR));
                        XFS_STATS_INC(xs_log_force_sleep);
-                       sv_wait(&iclog->ic_prev->ic_writesema, PSWP,
+                       sv_wait(&iclog->ic_prev->ic_write_wait, PSWP,
                                &log->l_icloglock, s);
                        *log_flushed = 1;
                        already_slept = 1;
@@ -3116,7 +3071,7 @@ try_again:
            !(iclog->ic_state & (XLOG_STATE_ACTIVE | XLOG_STATE_DIRTY))) {
 
                /*
-                * Don't wait on the forcesema if we know that we've
+                * Don't wait on completion if we know that we've
                 * gotten a log write error.
                 */
                if (iclog->ic_state & XLOG_STATE_IOERROR) {
@@ -3124,7 +3079,7 @@ try_again:
                        return XFS_ERROR(EIO);
                }
                XFS_STATS_INC(xs_log_force_sleep);
-               sv_wait(&iclog->ic_forcesema, PSWP, &log->l_icloglock, s);
+               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
@@ -3152,7 +3107,7 @@ try_again:
 STATIC void
 xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
 {
-       spin_lock(&log->l_icloglock);
+       assert_spin_locked(&log->l_icloglock);
 
        if (iclog->ic_state == XLOG_STATE_ACTIVE) {
                xlog_state_switch_iclogs(log, iclog, 0);
@@ -3160,10 +3115,7 @@ xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
                ASSERT(iclog->ic_state &
                        (XLOG_STATE_WANT_SYNC|XLOG_STATE_IOERROR));
        }
-
-       spin_unlock(&log->l_icloglock);
-}      /* xlog_state_want_sync */
-
+}
 
 
 /*****************************************************************************
@@ -3174,22 +3126,33 @@ xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
  */
 
 /*
- * Free a used ticket.
+ * Free a used ticket when its refcount falls to zero.
  */
-STATIC void
-xlog_ticket_put(xlog_t         *log,
-               xlog_ticket_t   *ticket)
+void
+xfs_log_ticket_put(
+       xlog_ticket_t   *ticket)
 {
-       sv_destroy(&ticket->t_sema);
-       kmem_zone_free(xfs_log_ticket_zone, ticket);
-}      /* xlog_ticket_put */
+       ASSERT(atomic_read(&ticket->t_ref) > 0);
+       if (atomic_dec_and_test(&ticket->t_ref)) {
+               sv_destroy(&ticket->t_wait);
+               kmem_zone_free(xfs_log_ticket_zone, ticket);
+       }
+}
 
+xlog_ticket_t *
+xfs_log_ticket_get(
+       xlog_ticket_t   *ticket)
+{
+       ASSERT(atomic_read(&ticket->t_ref) > 0);
+       atomic_inc(&ticket->t_ref);
+       return ticket;
+}
 
 /*
  * Allocate and initialise a new log ticket.
  */
 STATIC xlog_ticket_t *
-xlog_ticket_get(xlog_t         *log,
+xlog_ticket_alloc(xlog_t               *log,
                int             unit_bytes,
                int             cnt,
                char            client,
@@ -3260,6 +3223,7 @@ xlog_ticket_get(xlog_t            *log,
                unit_bytes += 2*BBSIZE;
         }
 
+       atomic_set(&tic->t_ref, 1);
        tic->t_unit_res         = unit_bytes;
        tic->t_curr_res         = unit_bytes;
        tic->t_cnt              = cnt;
@@ -3270,12 +3234,12 @@ xlog_ticket_get(xlog_t          *log,
        tic->t_trans_type       = 0;
        if (xflags & XFS_LOG_PERM_RESERV)
                tic->t_flags |= XLOG_TIC_PERM_RESERV;
-       sv_init(&(tic->t_sema), SV_DEFAULT, "logtick");
+       sv_init(&(tic->t_wait), SV_DEFAULT, "logtick");
 
        xlog_tic_reset_res(tic);
 
        return tic;
-}      /* xlog_ticket_get */
+}
 
 
 /******************************************************************************
@@ -3404,7 +3368,7 @@ xlog_verify_iclog(xlog_t   *log,
        ptr = iclog->ic_datap;
        base_ptr = ptr;
        ophead = (xlog_op_header_t *)ptr;
-       xhdr = (xlog_in_core_2_t *)&iclog->ic_header;
+       xhdr = iclog->ic_data;
        for (i = 0; i < len; i++) {
                ophead = (xlog_op_header_t *)ptr;
 
@@ -3510,7 +3474,8 @@ xfs_log_force_umount(
        if (!log ||
            log->l_flags & XLOG_ACTIVE_RECOVERY) {
                mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
-               XFS_BUF_DONE(mp->m_sb_bp);
+               if (mp->m_sb_bp)
+                       XFS_BUF_DONE(mp->m_sb_bp);
                return 0;
        }
 
@@ -3531,7 +3496,9 @@ xfs_log_force_umount(
        spin_lock(&log->l_icloglock);
        spin_lock(&log->l_grant_lock);
        mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
-       XFS_BUF_DONE(mp->m_sb_bp);
+       if (mp->m_sb_bp)
+               XFS_BUF_DONE(mp->m_sb_bp);
+
        /*
         * This flag is sort of redundant because of the mount flag, but
         * it's good to maintain the separation between the log and the rest
@@ -3557,14 +3524,14 @@ xfs_log_force_umount(
         */
        if ((tic = log->l_reserve_headq)) {
                do {
-                       sv_signal(&tic->t_sema);
+                       sv_signal(&tic->t_wait);
                        tic = tic->t_next;
                } while (tic != log->l_reserve_headq);
        }
 
        if ((tic = log->l_write_headq)) {
                do {
-                       sv_signal(&tic->t_sema);
+                       sv_signal(&tic->t_wait);
                        tic = tic->t_next;
                } while (tic != log->l_write_headq);
        }