eCryptfs: Fix lockdep warning in miscdev operations
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / xfs / xfs_sync.c
index 205ebcb34d9e499f732423bd00c1204bb89f6ef8..1e9ee064dbb28c7cb491d4c41dce53007eebc7e9 100644 (file)
@@ -18,7 +18,6 @@
 #include "xfs.h"
 #include "xfs_fs.h"
 #include "xfs_types.h"
-#include "xfs_bit.h"
 #include "xfs_log.h"
 #include "xfs_inum.h"
 #include "xfs_trans.h"
@@ -241,45 +240,6 @@ xfs_sync_inode_data(
        return error;
 }
 
-STATIC int
-xfs_sync_inode_attr(
-       struct xfs_inode        *ip,
-       struct xfs_perag        *pag,
-       int                     flags)
-{
-       int                     error = 0;
-
-       xfs_ilock(ip, XFS_ILOCK_SHARED);
-       if (xfs_inode_clean(ip))
-               goto out_unlock;
-       if (!xfs_iflock_nowait(ip)) {
-               if (!(flags & SYNC_WAIT))
-                       goto out_unlock;
-               xfs_iflock(ip);
-       }
-
-       if (xfs_inode_clean(ip)) {
-               xfs_ifunlock(ip);
-               goto out_unlock;
-       }
-
-       error = xfs_iflush(ip, flags);
-
-       /*
-        * We don't want to try again on non-blocking flushes that can't run
-        * again immediately. If an inode really must be written, then that's
-        * what the SYNC_WAIT flag is for.
-        */
-       if (error == EAGAIN) {
-               ASSERT(!(flags & SYNC_WAIT));
-               error = 0;
-       }
-
- out_unlock:
-       xfs_iunlock(ip, XFS_ILOCK_SHARED);
-       return error;
-}
-
 /*
  * Write out pagecache data for the whole filesystem.
  */
@@ -300,19 +260,6 @@ xfs_sync_data(
        return 0;
 }
 
-/*
- * Write out inode metadata (attributes) for the whole filesystem.
- */
-STATIC int
-xfs_sync_attr(
-       struct xfs_mount        *mp,
-       int                     flags)
-{
-       ASSERT((flags & ~SYNC_WAIT) == 0);
-
-       return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags);
-}
-
 STATIC int
 xfs_sync_fsdata(
        struct xfs_mount        *mp)
@@ -350,7 +297,7 @@ xfs_sync_fsdata(
  * First stage of freeze - no writers will make progress now we are here,
  * so we flush delwri and delalloc buffers here, then wait for all I/O to
  * complete.  Data is frozen at that point. Metadata is not frozen,
- * transactions can still occur here so don't bother flushing the buftarg
+ * transactions can still occur here so don't bother emptying the AIL
  * because it'll just get dirty again.
  */
 int
@@ -365,47 +312,13 @@ xfs_quiesce_data(
        /* write superblock and hoover up shutdown errors */
        error = xfs_sync_fsdata(mp);
 
-       /* make sure all delwri buffers are written out */
-       xfs_flush_buftarg(mp->m_ddev_targp, 1);
-
        /* mark the log as covered if needed */
        if (xfs_log_need_covered(mp))
                error2 = xfs_fs_log_dummy(mp);
 
-       /* flush data-only devices */
-       if (mp->m_rtdev_targp)
-               xfs_flush_buftarg(mp->m_rtdev_targp, 1);
-
        return error ? error : error2;
 }
 
-STATIC void
-xfs_quiesce_fs(
-       struct xfs_mount        *mp)
-{
-       int     count = 0, pincount;
-
-       xfs_reclaim_inodes(mp, 0);
-       xfs_flush_buftarg(mp->m_ddev_targp, 0);
-
-       /*
-        * This loop must run at least twice.  The first instance of the loop
-        * will flush most meta data but that will generate more meta data
-        * (typically directory updates).  Which then must be flushed and
-        * logged before we can write the unmount record. We also so sync
-        * reclaim of inodes to catch any that the above delwri flush skipped.
-        */
-       do {
-               xfs_reclaim_inodes(mp, SYNC_WAIT);
-               xfs_sync_attr(mp, SYNC_WAIT);
-               pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
-               if (!pincount) {
-                       delay(50);
-                       count++;
-               }
-       } while (count < 2);
-}
-
 /*
  * Second stage of a quiesce. The data is already synced, now we have to take
  * care of the metadata. New transactions are already blocked, so we need to
@@ -421,8 +334,12 @@ xfs_quiesce_attr(
        while (atomic_read(&mp->m_active_trans) > 0)
                delay(100);
 
-       /* flush inodes and push all remaining buffers out to disk */
-       xfs_quiesce_fs(mp);
+       /* reclaim inodes to do any IO before the freeze completes */
+       xfs_reclaim_inodes(mp, 0);
+       xfs_reclaim_inodes(mp, SYNC_WAIT);
+
+       /* flush all pending changes from the AIL */
+       xfs_ail_push_all_sync(mp->m_ail);
 
        /*
         * Just warn here till VFS can correctly support
@@ -436,7 +353,12 @@ xfs_quiesce_attr(
                xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "
                                "Frozen image may not be consistent.");
        xfs_log_unmount_write(mp);
-       xfs_unmountfs_writesb(mp);
+
+       /*
+        * At this point we might have modified the superblock again and thus
+        * added an item to the AIL, thus flush it again.
+        */
+       xfs_ail_push_all_sync(mp->m_ail);
 }
 
 static void
@@ -460,7 +382,17 @@ xfs_sync_worker(
                                        struct xfs_mount, m_sync_work);
        int             error;
 
-       if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
+       /*
+        * We shouldn't write/force the log if we are in the mount/unmount
+        * process or on a read only filesystem. The workqueue still needs to be
+        * active in both cases, however, because it is used for inode reclaim
+        * during these times.  Use the MS_ACTIVE flag to avoid doing anything
+        * during mount.  Doing work during unmount is avoided by calling
+        * cancel_delayed_work_sync on this work queue before tearing down
+        * the ail and the log in xfs_log_unmount.
+        */
+       if (!(mp->m_super->s_flags & MS_ACTIVE) &&
+           !(mp->m_flags & XFS_MOUNT_RDONLY)) {
                /* dgc: errors ignored here */
                if (mp->m_super->s_frozen == SB_UNFROZEN &&
                    xfs_log_need_covered(mp))
@@ -468,7 +400,8 @@ xfs_sync_worker(
                else
                        xfs_log_force(mp, 0);
 
-               /* start pushing all the metadata that is currently dirty */
+               /* start pushing all the metadata that is currently
+                * dirty */
                xfs_ail_push_all(mp->m_ail);
        }
 
@@ -488,14 +421,6 @@ xfs_syncd_queue_reclaim(
        struct xfs_mount        *mp)
 {
 
-       /*
-        * We can have inodes enter reclaim after we've shut down the syncd
-        * workqueue during unmount, so don't allow reclaim work to be queued
-        * during unmount.
-        */
-       if (!(mp->m_super->s_flags & MS_ACTIVE))
-               return;
-
        rcu_read_lock();
        if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
                queue_delayed_work(xfs_syncd_wq, &mp->m_reclaim_work,
@@ -564,7 +489,6 @@ xfs_syncd_init(
        INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
 
        xfs_syncd_queue_sync(mp);
-       xfs_syncd_queue_reclaim(mp);
 
        return 0;
 }
@@ -702,11 +626,8 @@ xfs_reclaim_inode_grab(
 }
 
 /*
- * Inodes in different states need to be treated differently, and the return
- * value of xfs_iflush is not sufficient to get this right. The following table
- * lists the inode states and the reclaim actions necessary for non-blocking
- * reclaim:
- *
+ * Inodes in different states need to be treated differently. The following
+ * table lists the inode states and the reclaim actions necessary:
  *
  *     inode state          iflush ret         required action
  *      ---------------      ----------         ---------------
@@ -716,39 +637,31 @@ xfs_reclaim_inode_grab(
  *     stale, unpinned         0               reclaim
  *     clean, pinned(*)        0               requeue
  *     stale, pinned           EAGAIN          requeue
- *     dirty, delwri ok        0               requeue
- *     dirty, delwri blocked   EAGAIN          requeue
- *     dirty, sync flush       0               reclaim
+ *     dirty, async            -               requeue
+ *     dirty, sync             0               reclaim
  *
  * (*) dgc: I don't think the clean, pinned state is possible but it gets
  * handled anyway given the order of checks implemented.
  *
- * As can be seen from the table, the return value of xfs_iflush() is not
- * sufficient to correctly decide the reclaim action here. The checks in
- * xfs_iflush() might look like duplicates, but they are not.
- *
  * Also, because we get the flush lock first, we know that any inode that has
  * been flushed delwri has had the flush completed by the time we check that
- * the inode is clean. The clean inode check needs to be done before flushing
- * the inode delwri otherwise we would loop forever requeuing clean inodes as
- * we cannot tell apart a successful delwri flush and a clean inode from the
- * return value of xfs_iflush().
+ * the inode is clean.
  *
- * Note that because the inode is flushed delayed write by background
- * writeback, the flush lock may already be held here and waiting on it can
- * result in very long latencies. Hence for sync reclaims, where we wait on the
- * flush lock, the caller should push out delayed write inodes first before
- * trying to reclaim them to minimise the amount of time spent waiting. For
- * background relaim, we just requeue the inode for the next pass.
+ * Note that because the inode is flushed delayed write by AIL pushing, the
+ * flush lock may already be held here and waiting on it can result in very
+ * long latencies.  Hence for sync reclaims, where we wait on the flush lock,
+ * the caller should push the AIL first before trying to reclaim inodes to
+ * minimise the amount of time spent waiting.  For background relaim, we only
+ * bother to reclaim clean inodes anyway.
  *
  * Hence the order of actions after gaining the locks should be:
  *     bad             => reclaim
  *     shutdown        => unpin and reclaim
- *     pinned, delwri  => requeue
+ *     pinned, async   => requeue
  *     pinned, sync    => unpin
  *     stale           => reclaim
  *     clean           => reclaim
- *     dirty, delwri   => flush and requeue
+ *     dirty, async    => requeue
  *     dirty, sync     => flush, wait and reclaim
  */
 STATIC int
@@ -757,7 +670,8 @@ xfs_reclaim_inode(
        struct xfs_perag        *pag,
        int                     sync_mode)
 {
-       int     error;
+       struct xfs_buf          *bp = NULL;
+       int                     error;
 
 restart:
        error = 0;
@@ -765,17 +679,6 @@ restart:
        if (!xfs_iflock_nowait(ip)) {
                if (!(sync_mode & SYNC_WAIT))
                        goto out;
-
-               /*
-                * If we only have a single dirty inode in a cluster there is
-                * a fair chance that the AIL push may have pushed it into
-                * the buffer, but xfsbufd won't touch it until 30 seconds
-                * from now, and thus we will lock up here.
-                *
-                * Promote the inode buffer to the front of the delwri list
-                * and wake up xfsbufd now.
-                */
-               xfs_promote_inode(ip);
                xfs_iflock(ip);
        }
 
@@ -783,13 +686,12 @@ restart:
                goto reclaim;
        if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
                xfs_iunpin_wait(ip);
+               xfs_iflush_abort(ip, false);
                goto reclaim;
        }
        if (xfs_ipincount(ip)) {
-               if (!(sync_mode & SYNC_WAIT)) {
-                       xfs_ifunlock(ip);
-                       goto out;
-               }
+               if (!(sync_mode & SYNC_WAIT))
+                       goto out_ifunlock;
                xfs_iunpin_wait(ip);
        }
        if (xfs_iflags_test(ip, XFS_ISTALE))
@@ -797,61 +699,43 @@ restart:
        if (xfs_inode_clean(ip))
                goto reclaim;
 
+       /*
+        * Never flush out dirty data during non-blocking reclaim, as it would
+        * just contend with AIL pushing trying to do the same job.
+        */
+       if (!(sync_mode & SYNC_WAIT))
+               goto out_ifunlock;
+
        /*
         * Now we have an inode that needs flushing.
         *
-        * We do a nonblocking flush here even if we are doing a SYNC_WAIT
-        * reclaim as we can deadlock with inode cluster removal.
+        * Note that xfs_iflush will never block on the inode buffer lock, as
         * xfs_ifree_cluster() can lock the inode buffer before it locks the
-        * ip->i_lock, and we are doing the exact opposite here. As a result,
-        * doing a blocking xfs_itobp() to get the cluster buffer will result
+        * ip->i_lock, and we are doing the exact opposite here.  As a result,
+        * doing a blocking xfs_itobp() to get the cluster buffer would result
         * in an ABBA deadlock with xfs_ifree_cluster().
         *
         * As xfs_ifree_cluser() must gather all inodes that are active in the
         * cache to mark them stale, if we hit this case we don't actually want
         * to do IO here - we want the inode marked stale so we can simply
-        * reclaim it. Hence if we get an EAGAIN error on a SYNC_WAIT flush,
-        * just unlock the inode, back off and try again. Hopefully the next
-        * pass through will see the stale flag set on the inode.
+        * reclaim it.  Hence if we get an EAGAIN error here,  just unlock the
+        * inode, back off and try again.  Hopefully the next pass through will
+        * see the stale flag set on the inode.
         */
-       error = xfs_iflush(ip, SYNC_TRYLOCK | sync_mode);
-       if (sync_mode & SYNC_WAIT) {
-               if (error == EAGAIN) {
-                       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                       /* backoff longer than in xfs_ifree_cluster */
-                       delay(2);
-                       goto restart;
-               }
-               xfs_iflock(ip);
-               goto reclaim;
+       error = xfs_iflush(ip, &bp);
+       if (error == EAGAIN) {
+               xfs_iunlock(ip, XFS_ILOCK_EXCL);
+               /* backoff longer than in xfs_ifree_cluster */
+               delay(2);
+               goto restart;
        }
 
-       /*
-        * When we have to flush an inode but don't have SYNC_WAIT set, we
-        * flush the inode out using a delwri buffer and wait for the next
-        * call into reclaim to find it in a clean state instead of waiting for
-        * it now. We also don't return errors here - if the error is transient
-        * then the next reclaim pass will flush the inode, and if the error
-        * is permanent then the next sync reclaim will reclaim the inode and
-        * pass on the error.
-        */
-       if (error && error != EAGAIN && !XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-               xfs_warn(ip->i_mount,
-                       "inode 0x%llx background reclaim flush failed with %d",
-                       (long long)ip->i_ino, error);
+       if (!error) {
+               error = xfs_bwrite(bp);
+               xfs_buf_relse(bp);
        }
-out:
-       xfs_iflags_clear(ip, XFS_IRECLAIM);
-       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-       /*
-        * We could return EAGAIN here to make reclaim rescan the inode tree in
-        * a short while. However, this just burns CPU time scanning the tree
-        * waiting for IO to complete and xfssyncd never goes back to the idle
-        * state. Instead, return 0 to let the next scheduled background reclaim
-        * attempt to reclaim the inode again.
-        */
-       return 0;
 
+       xfs_iflock(ip);
 reclaim:
        xfs_ifunlock(ip);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -884,8 +768,21 @@ reclaim:
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
        xfs_inode_free(ip);
-
        return error;
+
+out_ifunlock:
+       xfs_ifunlock(ip);
+out:
+       xfs_iflags_clear(ip, XFS_IRECLAIM);
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       /*
+        * We could return EAGAIN here to make reclaim rescan the inode tree in
+        * a short while. However, this just burns CPU time scanning the tree
+        * waiting for IO to complete and xfssyncd never goes back to the idle
+        * state. Instead, return 0 to let the next scheduled background reclaim
+        * attempt to reclaim the inode again.
+        */
+       return 0;
 }
 
 /*