xfs: Introduce delayed logging core code
[safe/jmp/linux-2.6] / fs / xfs / xfs_log.c
index 19d0c5f..027ebfe 100644 (file)
@@ -54,9 +54,6 @@ STATIC xlog_t *  xlog_alloc_log(xfs_mount_t   *mp,
 STATIC int      xlog_space_left(xlog_t *log, int cycle, int bytes);
 STATIC int      xlog_sync(xlog_t *log, xlog_in_core_t *iclog);
 STATIC void     xlog_dealloc_log(xlog_t *log);
-STATIC int      xlog_write(struct log *log, struct xfs_log_vec *log_vector,
-                           struct xlog_ticket *tic, xfs_lsn_t *start_lsn,
-                           xlog_in_core_t **commit_iclog, uint flags);
 
 /* local state machine functions */
 STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int);
@@ -86,12 +83,6 @@ STATIC int xlog_regrant_write_log_space(xlog_t               *log,
 STATIC void xlog_ungrant_log_space(xlog_t       *log,
                                   xlog_ticket_t *ticket);
 
-
-/* local ticket functions */
-STATIC xlog_ticket_t *xlog_ticket_alloc(xlog_t *log, int unit_bytes, int count,
-                                       char clientid, uint flags,
-                                       int alloc_flags);
-
 #if defined(DEBUG)
 STATIC void    xlog_verify_dest_ptr(xlog_t *log, char *ptr);
 STATIC void    xlog_verify_grant_head(xlog_t *log, int equals);
@@ -460,6 +451,13 @@ xfs_log_mount(
        /* Normal transactions can now occur */
        mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY;
 
+       /*
+        * Now the log has been fully initialised and we know were our
+        * space grant counters are, we can initialise the permanent ticket
+        * needed for delayed logging to work.
+        */
+       xlog_cil_init_post_recovery(mp->m_log);
+
        return 0;
 
 out_destroy_ail:
@@ -666,6 +664,10 @@ xfs_log_item_init(
        item->li_ailp = mp->m_ail;
        item->li_type = type;
        item->li_ops = ops;
+       item->li_lv = NULL;
+
+       INIT_LIST_HEAD(&item->li_ail);
+       INIT_LIST_HEAD(&item->li_cil);
 }
 
 /*
@@ -1176,6 +1178,9 @@ xlog_alloc_log(xfs_mount_t        *mp,
        *iclogp = log->l_iclog;                 /* complete ring */
        log->l_iclog->ic_prev = prev_iclog;     /* re-write 1st prev ptr */
 
+       error = xlog_cil_init(log);
+       if (error)
+               goto out_free_iclog;
        return log;
 
 out_free_iclog:
@@ -1502,6 +1507,8 @@ xlog_dealloc_log(xlog_t *log)
        xlog_in_core_t  *iclog, *next_iclog;
        int             i;
 
+       xlog_cil_destroy(log);
+
        iclog = log->l_iclog;
        for (i=0; i<log->l_iclog_bufs; i++) {
                sv_destroy(&iclog->ic_force_wait);
@@ -1544,8 +1551,10 @@ xlog_state_finish_copy(xlog_t            *log,
  * print out info relating to regions written which consume
  * the reservation
  */
-STATIC void
-xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket)
+void
+xlog_print_tic_res(
+       struct xfs_mount        *mp,
+       struct xlog_ticket      *ticket)
 {
        uint i;
        uint ophdr_spc = ticket->t_res_num_ophdrs * (uint)sizeof(xlog_op_header_t);
@@ -1877,7 +1886,7 @@ xlog_write_copy_finish(
  *     we don't update ic_offset until the end when we know exactly how many
  *     bytes have been written out.
  */
-STATIC int
+int
 xlog_write(
        struct log              *log,
        struct xfs_log_vec      *log_vector,
@@ -1901,9 +1910,26 @@ xlog_write(
        *start_lsn = 0;
 
        len = xlog_write_calc_vec_length(ticket, log_vector);
-       if (ticket->t_curr_res < len)
+       if (log->l_cilp) {
+               /*
+                * Region headers and bytes are already accounted for.
+                * We only need to take into account start records and
+                * split regions in this function.
+                */
+               if (ticket->t_flags & XLOG_TIC_INITED)
+                       ticket->t_curr_res -= sizeof(xlog_op_header_t);
+
+               /*
+                * Commit record headers need to be accounted for. These
+                * come in as separate writes so are easy to detect.
+                */
+               if (flags & (XLOG_COMMIT_TRANS | XLOG_UNMOUNT_TRANS))
+                       ticket->t_curr_res -= sizeof(xlog_op_header_t);
+       } else
+               ticket->t_curr_res -= len;
+
+       if (ticket->t_curr_res < 0)
                xlog_print_tic_res(log->l_mp, ticket);
-       ticket->t_curr_res -= len;
 
        index = 0;
        lv = log_vector;
@@ -2999,6 +3025,8 @@ _xfs_log_force(
 
        XFS_STATS_INC(xs_log_force);
 
+       xlog_cil_push(log, 1);
+
        spin_lock(&log->l_icloglock);
 
        iclog = log->l_iclog;
@@ -3148,6 +3176,12 @@ _xfs_log_force_lsn(
 
        XFS_STATS_INC(xs_log_force);
 
+       if (log->l_cilp) {
+               lsn = xlog_cil_push_lsn(log, lsn);
+               if (lsn == NULLCOMMITLSN)
+                       return 0;
+       }
+
 try_again:
        spin_lock(&log->l_icloglock);
        iclog = log->l_iclog;
@@ -3322,7 +3356,7 @@ xfs_log_get_trans_ident(
 /*
  * Allocate and initialise a new log ticket.
  */
-STATIC xlog_ticket_t *
+xlog_ticket_t *
 xlog_ticket_alloc(
        struct log      *log,
        int             unit_bytes,