Merge remote-tracking branches 'asoc/topic/ab8500', 'asoc/topic/ac97' and 'asoc/topic...
[firefly-linux-kernel-4.4.55.git] / fs / xfs / xfs_icache.c
index c48df5f25b9f460e2fd312c9557b69d1db4209a9..981b2cf519853f72c91dff609c90b78eb1626c4e 100644 (file)
@@ -33,6 +33,9 @@
 #include "xfs_trace.h"
 #include "xfs_icache.h"
 #include "xfs_bmap_util.h"
+#include "xfs_quota.h"
+#include "xfs_dquot_item.h"
+#include "xfs_dquot.h"
 
 #include <linux/kthread.h>
 #include <linux/freezer.h>
@@ -158,7 +161,7 @@ xfs_iget_cache_hit(
        if (ip->i_ino != ino) {
                trace_xfs_iget_skip(ip);
                XFS_STATS_INC(xs_ig_frecycle);
-               error = EAGAIN;
+               error = -EAGAIN;
                goto out_error;
        }
 
@@ -176,7 +179,7 @@ xfs_iget_cache_hit(
        if (ip->i_flags & (XFS_INEW|XFS_IRECLAIM)) {
                trace_xfs_iget_skip(ip);
                XFS_STATS_INC(xs_ig_frecycle);
-               error = EAGAIN;
+               error = -EAGAIN;
                goto out_error;
        }
 
@@ -184,7 +187,7 @@ xfs_iget_cache_hit(
         * If lookup is racing with unlink return an error immediately.
         */
        if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) {
-               error = ENOENT;
+               error = -ENOENT;
                goto out_error;
        }
 
@@ -206,7 +209,7 @@ xfs_iget_cache_hit(
                spin_unlock(&ip->i_flags_lock);
                rcu_read_unlock();
 
-               error = -inode_init_always(mp->m_super, inode);
+               error = inode_init_always(mp->m_super, inode);
                if (error) {
                        /*
                         * Re-initializing the inode failed, and we are in deep
@@ -243,7 +246,7 @@ xfs_iget_cache_hit(
                /* If the VFS inode is being torn down, pause and try again. */
                if (!igrab(inode)) {
                        trace_xfs_iget_skip(ip);
-                       error = EAGAIN;
+                       error = -EAGAIN;
                        goto out_error;
                }
 
@@ -285,7 +288,7 @@ xfs_iget_cache_miss(
 
        ip = xfs_inode_alloc(mp, ino);
        if (!ip)
-               return ENOMEM;
+               return -ENOMEM;
 
        error = xfs_iread(mp, tp, ip, flags);
        if (error)
@@ -294,7 +297,7 @@ xfs_iget_cache_miss(
        trace_xfs_iget_miss(ip);
 
        if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
-               error = ENOENT;
+               error = -ENOENT;
                goto out_destroy;
        }
 
@@ -305,7 +308,7 @@ xfs_iget_cache_miss(
         * recurse into the file system.
         */
        if (radix_tree_preload(GFP_NOFS)) {
-               error = EAGAIN;
+               error = -EAGAIN;
                goto out_destroy;
        }
 
@@ -341,7 +344,7 @@ xfs_iget_cache_miss(
        if (unlikely(error)) {
                WARN_ON(error != -EEXIST);
                XFS_STATS_INC(xs_ig_dup);
-               error = EAGAIN;
+               error = -EAGAIN;
                goto out_preload_end;
        }
        spin_unlock(&pag->pag_ici_lock);
@@ -408,7 +411,7 @@ xfs_iget(
 
        /* reject inode numbers outside existing AGs */
        if (!ino || XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount)
-               return EINVAL;
+               return -EINVAL;
 
        /* get the perag structure and ensure that it's inode capable */
        pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
@@ -445,7 +448,7 @@ again:
        return 0;
 
 out_error_or_again:
-       if (error == EAGAIN) {
+       if (error == -EAGAIN) {
                delay(1);
                goto again;
        }
@@ -489,18 +492,18 @@ xfs_inode_ag_walk_grab(
 
        /* nothing to sync during shutdown */
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-               return EFSCORRUPTED;
+               return -EFSCORRUPTED;
 
        /* If we can't grab the inode, it must on it's way to reclaim. */
        if (!igrab(inode))
-               return ENOENT;
+               return -ENOENT;
 
        /* inode is valid */
        return 0;
 
 out_unlock_noent:
        spin_unlock(&ip->i_flags_lock);
-       return ENOENT;
+       return -ENOENT;
 }
 
 STATIC int
@@ -583,16 +586,16 @@ restart:
                                continue;
                        error = execute(batch[i], flags, args);
                        IRELE(batch[i]);
-                       if (error == EAGAIN) {
+                       if (error == -EAGAIN) {
                                skipped++;
                                continue;
                        }
-                       if (error && last_error != EFSCORRUPTED)
+                       if (error && last_error != -EFSCORRUPTED)
                                last_error = error;
                }
 
                /* bail out if the filesystem is corrupted.  */
-               if (error == EFSCORRUPTED)
+               if (error == -EFSCORRUPTED)
                        break;
 
                cond_resched();
@@ -652,11 +655,11 @@ xfs_inode_ag_iterator(
                xfs_perag_put(pag);
                if (error) {
                        last_error = error;
-                       if (error == EFSCORRUPTED)
+                       if (error == -EFSCORRUPTED)
                                break;
                }
        }
-       return XFS_ERROR(last_error);
+       return last_error;
 }
 
 int
@@ -680,11 +683,11 @@ xfs_inode_ag_iterator_tag(
                xfs_perag_put(pag);
                if (error) {
                        last_error = error;
-                       if (error == EFSCORRUPTED)
+                       if (error == -EFSCORRUPTED)
                                break;
                }
        }
-       return XFS_ERROR(last_error);
+       return last_error;
 }
 
 /*
@@ -944,7 +947,7 @@ restart:
         * see the stale flag set on the inode.
         */
        error = xfs_iflush(ip, &bp);
-       if (error == EAGAIN) {
+       if (error == -EAGAIN) {
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
                /* backoff longer than in xfs_ifree_cluster */
                delay(2);
@@ -997,7 +1000,7 @@ 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
+        * 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 the reclaim work never goes back to
         * the idle state. Instead, return 0 to let the next scheduled
@@ -1100,7 +1103,7 @@ restart:
                                if (!batch[i])
                                        continue;
                                error = xfs_reclaim_inode(batch[i], pag, flags);
-                               if (error && last_error != EFSCORRUPTED)
+                               if (error && last_error != -EFSCORRUPTED)
                                        last_error = error;
                        }
 
@@ -1129,7 +1132,7 @@ restart:
                trylock = 0;
                goto restart;
        }
-       return XFS_ERROR(last_error);
+       return last_error;
 }
 
 int
@@ -1203,6 +1206,30 @@ xfs_inode_match_id(
        return 1;
 }
 
+/*
+ * A union-based inode filtering algorithm. Process the inode if any of the
+ * criteria match. This is for global/internal scans only.
+ */
+STATIC int
+xfs_inode_match_id_union(
+       struct xfs_inode        *ip,
+       struct xfs_eofblocks    *eofb)
+{
+       if ((eofb->eof_flags & XFS_EOF_FLAGS_UID) &&
+           uid_eq(VFS_I(ip)->i_uid, eofb->eof_uid))
+               return 1;
+
+       if ((eofb->eof_flags & XFS_EOF_FLAGS_GID) &&
+           gid_eq(VFS_I(ip)->i_gid, eofb->eof_gid))
+               return 1;
+
+       if ((eofb->eof_flags & XFS_EOF_FLAGS_PRID) &&
+           xfs_get_projid(ip) == eofb->eof_prid)
+               return 1;
+
+       return 0;
+}
+
 STATIC int
 xfs_inode_free_eofblocks(
        struct xfs_inode        *ip,
@@ -1211,6 +1238,10 @@ xfs_inode_free_eofblocks(
 {
        int ret;
        struct xfs_eofblocks *eofb = args;
+       bool need_iolock = true;
+       int match;
+
+       ASSERT(!eofb || (eofb && eofb->eof_scan_owner != 0));
 
        if (!xfs_can_free_eofblocks(ip, false)) {
                /* inode could be preallocated or append-only */
@@ -1228,19 +1259,31 @@ xfs_inode_free_eofblocks(
                return 0;
 
        if (eofb) {
-               if (!xfs_inode_match_id(ip, eofb))
+               if (eofb->eof_flags & XFS_EOF_FLAGS_UNION)
+                       match = xfs_inode_match_id_union(ip, eofb);
+               else
+                       match = xfs_inode_match_id(ip, eofb);
+               if (!match)
                        return 0;
 
                /* skip the inode if the file size is too small */
                if (eofb->eof_flags & XFS_EOF_FLAGS_MINFILESIZE &&
                    XFS_ISIZE(ip) < eofb->eof_min_file_size)
                        return 0;
+
+               /*
+                * A scan owner implies we already hold the iolock. Skip it in
+                * xfs_free_eofblocks() to avoid deadlock. This also eliminates
+                * the possibility of EAGAIN being returned.
+                */
+               if (eofb->eof_scan_owner == ip->i_ino)
+                       need_iolock = false;
        }
 
-       ret = xfs_free_eofblocks(ip->i_mount, ip, true);
+       ret = xfs_free_eofblocks(ip->i_mount, ip, need_iolock);
 
        /* don't revisit the inode if we're not waiting */
-       if (ret == EAGAIN && !(flags & SYNC_WAIT))
+       if (ret == -EAGAIN && !(flags & SYNC_WAIT))
                ret = 0;
 
        return ret;
@@ -1260,6 +1303,55 @@ xfs_icache_free_eofblocks(
                                         eofb, XFS_ICI_EOFBLOCKS_TAG);
 }
 
+/*
+ * Run eofblocks scans on the quotas applicable to the inode. For inodes with
+ * multiple quotas, we don't know exactly which quota caused an allocation
+ * failure. We make a best effort by including each quota under low free space
+ * conditions (less than 1% free space) in the scan.
+ */
+int
+xfs_inode_free_quota_eofblocks(
+       struct xfs_inode *ip)
+{
+       int scan = 0;
+       struct xfs_eofblocks eofb = {0};
+       struct xfs_dquot *dq;
+
+       ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
+
+       /*
+        * Set the scan owner to avoid a potential livelock. Otherwise, the scan
+        * can repeatedly trylock on the inode we're currently processing. We
+        * run a sync scan to increase effectiveness and use the union filter to
+        * cover all applicable quotas in a single scan.
+        */
+       eofb.eof_scan_owner = ip->i_ino;
+       eofb.eof_flags = XFS_EOF_FLAGS_UNION|XFS_EOF_FLAGS_SYNC;
+
+       if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) {
+               dq = xfs_inode_dquot(ip, XFS_DQ_USER);
+               if (dq && xfs_dquot_lowsp(dq)) {
+                       eofb.eof_uid = VFS_I(ip)->i_uid;
+                       eofb.eof_flags |= XFS_EOF_FLAGS_UID;
+                       scan = 1;
+               }
+       }
+
+       if (XFS_IS_GQUOTA_ENFORCED(ip->i_mount)) {
+               dq = xfs_inode_dquot(ip, XFS_DQ_GROUP);
+               if (dq && xfs_dquot_lowsp(dq)) {
+                       eofb.eof_gid = VFS_I(ip)->i_gid;
+                       eofb.eof_flags |= XFS_EOF_FLAGS_GID;
+                       scan = 1;
+               }
+       }
+
+       if (scan)
+               xfs_icache_free_eofblocks(ip->i_mount, &eofb);
+
+       return scan;
+}
+
 void
 xfs_inode_set_eofblocks_tag(
        xfs_inode_t     *ip)