]> git.karo-electronics.de Git - linux-beck.git/blobdiff - fs/xfs/xfs_inode_item.c
Merge branches 'x86-fixes-for-linus', 'perf-fixes-for-linus' and 'sched-fixes-for...
[linux-beck.git] / fs / xfs / xfs_inode_item.c
index fe00777e2796317146ce1e20142cc7f4e3679635..7c8d30c453c340de5afbab276505487ddbbf3373 100644 (file)
@@ -222,15 +222,6 @@ xfs_inode_item_format(
        vecp++;
        nvecs        = 1;
 
-       /*
-        * Make sure the linux inode is dirty. We do this before
-        * clearing i_update_core as the VFS will call back into
-        * XFS here and set i_update_core, so we need to dirty the
-        * inode first so that the ordering of i_update_core and
-        * unlogged modifications still works as described below.
-        */
-       xfs_mark_inode_dirty_sync(ip);
-
        /*
         * Clear i_update_core if the timestamps (or any other
         * non-transactional modification) need flushing/logging
@@ -666,18 +657,37 @@ xfs_inode_item_unlock(
 }
 
 /*
- * This is called to find out where the oldest active copy of the
- * inode log item in the on disk log resides now that the last log
- * write of it completed at the given lsn.  Since we always re-log
- * all dirty data in an inode, the latest copy in the on disk log
- * is the only one that matters.  Therefore, simply return the
- * given lsn.
+ * This is called to find out where the oldest active copy of the inode log
+ * item in the on disk log resides now that the last log write of it completed
+ * at the given lsn.  Since we always re-log all dirty data in an inode, the
+ * latest copy in the on disk log is the only one that matters.  Therefore,
+ * simply return the given lsn.
+ *
+ * If the inode has been marked stale because the cluster is being freed, we
+ * don't want to (re-)insert this inode into the AIL. There is a race condition
+ * where the cluster buffer may be unpinned before the inode is inserted into
+ * the AIL during transaction committed processing. If the buffer is unpinned
+ * before the inode item has been committed and inserted, then it is possible
+ * for the buffer to be written and IO completions before the inode is inserted
+ * into the AIL. In that case, we'd be inserting a clean, stale inode into the
+ * AIL which will never get removed. It will, however, get reclaimed which
+ * triggers an assert in xfs_inode_free() complaining about freein an inode
+ * still in the AIL.
+ *
+ * To avoid this, return a lower LSN than the one passed in so that the
+ * transaction committed code will not move the inode forward in the AIL but
+ * will still unpin it properly.
  */
 STATIC xfs_lsn_t
 xfs_inode_item_committed(
        struct xfs_log_item     *lip,
        xfs_lsn_t               lsn)
 {
+       struct xfs_inode_log_item *iip = INODE_ITEM(lip);
+       struct xfs_inode        *ip = iip->ili_inode;
+
+       if (xfs_iflags_test(ip, XFS_ISTALE))
+               return lsn - 1;
        return lsn;
 }