Merge tag 'xfs-5.15-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[linux-2.6-microblaze.git] / fs / xfs / xfs_inode.c
index f00145e..a4f6f03 100644 (file)
@@ -674,7 +674,7 @@ xfs_lookup(
 
        trace_xfs_lookup(dp, name);
 
-       if (XFS_FORCED_SHUTDOWN(dp->i_mount))
+       if (xfs_is_shutdown(dp->i_mount))
                return -EIO;
 
        error = xfs_dir_lookup(NULL, dp, name, &inum, ci_name);
@@ -716,7 +716,7 @@ xfs_inode_inherit_flags(
                        di_flags |= XFS_DIFLAG_PROJINHERIT;
        } else if (S_ISREG(mode)) {
                if ((pip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
-                   xfs_sb_version_hasrealtime(&ip->i_mount->m_sb))
+                   xfs_has_realtime(ip->i_mount))
                        di_flags |= XFS_DIFLAG_REALTIME;
                if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
                        di_flags |= XFS_DIFLAG_EXTSIZE;
@@ -837,8 +837,7 @@ xfs_init_new_inode(
        inode->i_rdev = rdev;
        ip->i_projid = prid;
 
-       if (dir && !(dir->i_mode & S_ISGID) &&
-           (mp->m_flags & XFS_MOUNT_GRPID)) {
+       if (dir && !(dir->i_mode & S_ISGID) && xfs_has_grpid(mp)) {
                inode_fsuid_set(inode, mnt_userns);
                inode->i_gid = dir->i_gid;
                inode->i_mode = mode;
@@ -868,7 +867,7 @@ xfs_init_new_inode(
        ip->i_extsize = 0;
        ip->i_diflags = 0;
 
-       if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+       if (xfs_has_v3inodes(mp)) {
                inode_set_iversion(inode, 1);
                ip->i_cowextsize = 0;
                ip->i_crtime = tv;
@@ -908,7 +907,7 @@ xfs_init_new_inode(
         * this saves us from needing to run a separate transaction to set the
         * fork offset in the immediate future.
         */
-       if (init_xattrs && xfs_sb_version_hasattr(&mp->m_sb)) {
+       if (init_xattrs && xfs_has_attr(mp)) {
                ip->i_forkoff = xfs_default_attroffset(ip) >> 3;
                ip->i_afp = xfs_ifork_alloc(XFS_DINODE_FMT_EXTENTS, 0);
        }
@@ -987,7 +986,7 @@ xfs_create(
 
        trace_xfs_create(dp, name);
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
        prid = xfs_get_initial_prid(dp);
@@ -1079,7 +1078,7 @@ xfs_create(
         * create transaction goes to disk before returning to
         * the user.
         */
-       if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
+       if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
                xfs_trans_set_sync(tp);
 
        /*
@@ -1141,7 +1140,7 @@ xfs_create_tmpfile(
        uint                    resblks;
        xfs_ino_t               ino;
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
        prid = xfs_get_initial_prid(dp);
@@ -1171,7 +1170,7 @@ xfs_create_tmpfile(
        if (error)
                goto out_trans_cancel;
 
-       if (mp->m_flags & XFS_MOUNT_WSYNC)
+       if (xfs_has_wsync(mp))
                xfs_trans_set_sync(tp);
 
        /*
@@ -1231,7 +1230,7 @@ xfs_link(
 
        ASSERT(!S_ISDIR(VFS_I(sip)->i_mode));
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
        error = xfs_qm_dqattach(sip);
@@ -1305,7 +1304,7 @@ xfs_link(
         * link transaction goes to disk before returning to
         * the user.
         */
-       if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
+       if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
                xfs_trans_set_sync(tp);
 
        return xfs_trans_commit(tp);
@@ -1446,10 +1445,10 @@ xfs_release(
                return 0;
 
        /* If this is a read-only mount, don't do this (would generate I/O) */
-       if (mp->m_flags & XFS_MOUNT_RDONLY)
+       if (xfs_is_readonly(mp))
                return 0;
 
-       if (!XFS_FORCED_SHUTDOWN(mp)) {
+       if (!xfs_is_shutdown(mp)) {
                int truncated;
 
                /*
@@ -1532,7 +1531,7 @@ xfs_inactive_truncate(
 
        error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
        if (error) {
-               ASSERT(XFS_FORCED_SHUTDOWN(mp));
+               ASSERT(xfs_is_shutdown(mp));
                return error;
        }
        xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1603,7 +1602,7 @@ xfs_inactive_ifree(
                        "Failed to remove inode(s) from unlinked list. "
                        "Please free space, unmount and run xfs_repair.");
                } else {
-                       ASSERT(XFS_FORCED_SHUTDOWN(mp));
+                       ASSERT(xfs_is_shutdown(mp));
                }
                return error;
        }
@@ -1639,7 +1638,7 @@ xfs_inactive_ifree(
                 * might do that, we need to make sure.  Otherwise the
                 * inode might be lost for a long time or forever.
                 */
-               if (!XFS_FORCED_SHUTDOWN(mp)) {
+               if (!xfs_is_shutdown(mp)) {
                        xfs_notice(mp, "%s: xfs_ifree returned error %d",
                                __func__, error);
                        xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
@@ -1665,6 +1664,59 @@ xfs_inactive_ifree(
        return 0;
 }
 
+/*
+ * Returns true if we need to update the on-disk metadata before we can free
+ * the memory used by this inode.  Updates include freeing post-eof
+ * preallocations; freeing COW staging extents; and marking the inode free in
+ * the inobt if it is on the unlinked list.
+ */
+bool
+xfs_inode_needs_inactive(
+       struct xfs_inode        *ip)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_ifork        *cow_ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
+
+       /*
+        * If the inode is already free, then there can be nothing
+        * to clean up here.
+        */
+       if (VFS_I(ip)->i_mode == 0)
+               return false;
+
+       /* If this is a read-only mount, don't do this (would generate I/O) */
+       if (xfs_is_readonly(mp))
+               return false;
+
+       /* If the log isn't running, push inodes straight to reclaim. */
+       if (xfs_is_shutdown(mp) || xfs_has_norecovery(mp))
+               return false;
+
+       /* Metadata inodes require explicit resource cleanup. */
+       if (xfs_is_metadata_inode(ip))
+               return false;
+
+       /* Want to clean out the cow blocks if there are any. */
+       if (cow_ifp && cow_ifp->if_bytes > 0)
+               return true;
+
+       /* Unlinked files must be freed. */
+       if (VFS_I(ip)->i_nlink == 0)
+               return true;
+
+       /*
+        * This file isn't being freed, so check if there are post-eof blocks
+        * to free.  @force is true because we are evicting an inode from the
+        * cache.  Post-eof blocks must be freed, lest we end up with broken
+        * free space accounting.
+        *
+        * Note: don't bother with iolock here since lockdep complains about
+        * acquiring it in reclaim context. We have the only reference to the
+        * inode at this point anyways.
+        */
+       return xfs_can_free_eofblocks(ip, true);
+}
+
 /*
  * xfs_inactive
  *
@@ -1694,7 +1746,7 @@ xfs_inactive(
        ASSERT(!xfs_iflags_test(ip, XFS_IRECOVERY));
 
        /* If this is a read-only mount, don't do this (would generate I/O) */
-       if (mp->m_flags & XFS_MOUNT_RDONLY)
+       if (xfs_is_readonly(mp))
                goto out;
 
        /* Metadata inodes require explicit resource cleanup. */
@@ -1969,7 +2021,7 @@ xfs_iunlink_destroy(
        rhashtable_free_and_destroy(&pag->pagi_unlinked_hash,
                        xfs_iunlink_free_item, &freed_anything);
 
-       ASSERT(freed_anything == false || XFS_FORCED_SHUTDOWN(pag->pag_mount));
+       ASSERT(freed_anything == false || xfs_is_shutdown(pag->pag_mount));
 }
 
 /*
@@ -2714,7 +2766,7 @@ xfs_remove(
 
        trace_xfs_remove(dp, name);
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
        error = xfs_qm_dqattach(dp);
@@ -2813,7 +2865,7 @@ xfs_remove(
         * remove transaction goes to disk before returning to
         * the user.
         */
-       if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
+       if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
                xfs_trans_set_sync(tp);
 
        error = xfs_trans_commit(tp);
@@ -2890,7 +2942,7 @@ xfs_finish_rename(
         * If this is a synchronous mount, make sure that the rename transaction
         * goes to disk before returning to the user.
         */
-       if (tp->t_mountp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
+       if (xfs_has_wsync(tp->t_mountp) || xfs_has_dirsync(tp->t_mountp))
                xfs_trans_set_sync(tp);
 
        return xfs_trans_commit(tp);
@@ -3473,7 +3525,7 @@ xfs_iflush(
         * happen but we need to still do it to ensure backwards compatibility
         * with old kernels that predate logging all inode changes.
         */
-       if (!xfs_sb_version_has_v3inode(&mp->m_sb))
+       if (!xfs_has_v3inodes(mp))
                ip->i_flushiter++;
 
        /*
@@ -3495,7 +3547,7 @@ xfs_iflush(
        xfs_inode_to_disk(ip, dip, iip->ili_item.li_lsn);
 
        /* Wrap, we never let the log put out DI_MAX_FLUSH */
-       if (!xfs_sb_version_has_v3inode(&mp->m_sb)) {
+       if (!xfs_has_v3inodes(mp)) {
                if (ip->i_flushiter == DI_MAX_FLUSH)
                        ip->i_flushiter = 0;
        }
@@ -3614,7 +3666,7 @@ xfs_iflush_cluster(
                 * AIL, leaving a dirty/unpinned inode attached to the buffer
                 * that otherwise looks like it should be flushed.
                 */
-               if (XFS_FORCED_SHUTDOWN(mp)) {
+               if (xfs_is_shutdown(mp)) {
                        xfs_iunpin_wait(ip);
                        xfs_iflush_abort(ip);
                        xfs_iunlock(ip, XFS_ILOCK_SHARED);