]> git.hungrycats.org Git - linux/commitdiff
[XFS] fix one more set of transaction callback ordering issues,
authorGlen Overby <overby@sgi.com>
Wed, 19 Feb 2003 19:26:14 +0000 (20:26 +0100)
committerChristoph Hellwig <hch@lab343.munich.sgi.com>
Wed, 19 Feb 2003 19:26:14 +0000 (20:26 +0100)
this was always there, but exposed by the last change in
this area and made much more likely.

SGI Modid: 2.5.x-xfs:slinx:139655a

fs/xfs/xfs_log.c
fs/xfs/xfs_log.h
fs/xfs/xfs_trans.c

index a30359bcbbba1422efce71ea7fb1b3fd191e15ca..b044f4f8003c0713545f69cb27a1e6ef44440121 100644 (file)
@@ -378,17 +378,26 @@ xfs_log_notify(xfs_mount_t          *mp,          /* mount of partition */
                iclog->ic_callback_tail = &(cb->cb_next);
        }
        LOG_UNLOCK(log, spl);
-       if (!abortflg) {
-               if (xlog_state_release_iclog(log, iclog)) {
-                       xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
-                       return EIO;
-               }
-       } else {
+       if (abortflg) {
                cb->cb_func(cb->cb_arg, abortflg);
        }
        return 0;
 }      /* xfs_log_notify */
 
+int
+xfs_log_release_iclog(xfs_mount_t *mp,
+                     void        *iclog_hndl)
+{
+       xlog_t *log = mp->m_log;
+       xlog_in_core_t    *iclog = (xlog_in_core_t *)iclog_hndl;
+
+       if (xlog_state_release_iclog(log, iclog)) {
+               xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
+               return(EIO);
+       }
+
+       return 0;
+}
 
 /*
  * Initialize log manager data.         This routine is intended to be called when
index 68a3ea4fe730e7312a6f0b36fe5f1292f5dd5692..02955f0c0b46f7d710f3a04e3c120d147ff80db1 100644 (file)
@@ -164,6 +164,8 @@ void          xfs_log_move_tail(struct xfs_mount    *mp,
 int      xfs_log_notify(struct xfs_mount       *mp,
                         void                   *iclog,
                         xfs_log_callback_t     *callback_entry);
+int      xfs_log_release_iclog(struct xfs_mount *mp,
+                        void                    *iclog_hndl);
 int      xfs_log_reserve(struct xfs_mount *mp,
                          int              length,
                          int              count,
index 355e283f8ab6bf7b87adc62962acb461104d2ade..599ec46ec7a6ac2311d499663a58469f43239a56 100644 (file)
@@ -808,19 +808,6 @@ shut_us_down:
                return XFS_ERROR(EIO);
        }
 
-       /*
-        * Once all the items of the transaction have been copied
-        * to the in core log we can release them.  Do that here.
-        * This will free descriptors pointing to items which were
-        * not logged since there is nothing more to do with them.
-        * For items which were logged, we will keep pointers to them
-        * so they can be unpinned after the transaction commits to disk.
-        * This will also stamp each modified meta-data item with
-        * the commit lsn of this transaction for dependency tracking
-        * purposes.
-        */
-       xfs_trans_unlock_items(tp, commit_lsn);
-
        /*
         * Once the transaction has committed, unused
         * reservations need to be released and changes to
@@ -856,12 +843,36 @@ shut_us_down:
        tp->t_logcb.cb_arg = tp;
 
        /* We need to pass the iclog buffer which was used for the
-        * transaction commit record into this function, attach
-        * the callback to it, and then release it. This will guarantee
-        * that we do callbacks on the transaction in the correct order.
+        * transaction commit record into this function, and attach
+        * the callback to it. The callback must be attached before
+        * the items are unlocked to avoid racing with other threads
+        * waiting for an item to unlock.
         */
        error = xfs_log_notify(mp, commit_iclog, &(tp->t_logcb));
 #endif
+
+       /*
+        * Once all the items of the transaction have been copied
+        * to the in core log and the callback is attached, the
+        * items can be unlocked.
+        *
+        * This will free descriptors pointing to items which were
+        * not logged since there is nothing more to do with them.
+        * For items which were logged, we will keep pointers to them
+        * so they can be unpinned after the transaction commits to disk.
+        * This will also stamp each modified meta-data item with
+        * the commit lsn of this transaction for dependency tracking
+        * purposes.
+        */
+       xfs_trans_unlock_items(tp, commit_lsn);
+
+       /*
+        * Now that the xfs_trans_committed callback has been attached,
+        * and the items are released we can finally allow the iclog to
+        * go to disk.
+        */
+       error = xfs_log_release_iclog(mp, commit_iclog);
+
        /*
         * If the transaction needs to be synchronous, then force the
         * log out now and wait for it.