Merge branch 'for-linus' of git://neil.brown.name/md
[pandora-kernel.git] / fs / xfs / xfs_log.c
index f4726f7..3750f04 100644 (file)
@@ -562,9 +562,8 @@ xfs_log_mount(
        }
 
        mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
-       if (!mp->m_log) {
-               cmn_err(CE_WARN, "XFS: Log allocation failed: No memory!");
-               error = ENOMEM;
+       if (IS_ERR(mp->m_log)) {
+               error = -PTR_ERR(mp->m_log);
                goto out;
        }
 
@@ -574,7 +573,7 @@ xfs_log_mount(
        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;
 
@@ -594,20 +593,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
@@ -632,19 +633,6 @@ xfs_log_mount_finish(xfs_mount_t *mp)
        return error;
 }
 
-/*
- * 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.
  *
@@ -795,7 +783,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);
@@ -1109,7 +1097,7 @@ xlog_bdstrat_cb(struct xfs_buf *bp)
 /*
  * 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.
@@ -1139,8 +1127,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;
@@ -1156,7 +1144,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;
 
@@ -1164,32 +1152,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)
@@ -1215,10 +1179,13 @@ xlog_alloc_log(xfs_mount_t      *mp,
        xfs_buf_t               *bp;
        int                     i;
        int                     iclogsize;
+       int                     error = ENOMEM;
 
        log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL);
-       if (!log)
-               return NULL;
+       if (!log) {
+               xlog_warn("XFS: Log allocation failed: No memory!");
+               goto out;
+       }
 
        log->l_mp          = mp;
        log->l_targ        = log_target;
@@ -1236,19 +1203,35 @@ 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;
@@ -1348,7 +1331,8 @@ out_free_iclog:
        xfs_buf_free(log->l_xbuf);
 out_free_log:
        kmem_free(log);
-       return NULL;
+out:
+       return ERR_PTR(-error);
 }      /* xlog_alloc_log */
 
 
@@ -2576,18 +2560,19 @@ redo:
                        xlog_ins_ticketq(&log->l_reserve_headq, tic);
                xlog_trace_loggrant(log, tic,
                                    "xlog_grant_log_space: sleep 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);
 
-               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_grant_log_space: wake 2");
-               xlog_grant_push_ail(log->l_mp, need_bytes);
-               spin_lock(&log->l_grant_lock);
                goto redo;
        } else if (tic->t_flags & XLOG_TIC_IN_Q)
                xlog_del_ticketq(&log->l_reserve_headq, tic);
@@ -2666,7 +2651,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);
@@ -2686,26 +2671,25 @@ xlog_regrant_write_log_space(xlog_t        *log,
 
                        xlog_trace_loggrant(log, tic,
                                    "xlog_regrant_write_log_space: sleep 1");
+                       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);
 
                        /* 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);
                }
        }
 
-       need_bytes = tic->t_unit_res;
-
 redo:
        if (XLOG_FORCED_SHUTDOWN(log))
                goto error_return;
@@ -2715,19 +2699,20 @@ 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_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);
                goto redo;
        } else if (tic->t_flags & XLOG_TIC_IN_Q)
                xlog_del_ticketq(&log->l_write_headq, tic);
@@ -3214,7 +3199,7 @@ xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
  */
 
 /*
- * Free a used ticket when it's refcount falls to zero.
+ * Free a used ticket when its refcount falls to zero.
  */
 void
 xfs_log_ticket_put(