Merge tag 'xfs-6.9-merge-8' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[linux-block.git] / fs / xfs / libxfs / xfs_dir2.c
index a76673281514501560e286d8bb5ac19cbc7e5707..4821519efad4b7e6cf8ba5eb50079773ec158f91 100644 (file)
@@ -18,6 +18,7 @@
 #include "xfs_errortag.h"
 #include "xfs_error.h"
 #include "xfs_trace.h"
+#include "xfs_health.h"
 
 const struct xfs_name xfs_name_dotdot = {
        .name   = (const unsigned char *)"..",
@@ -25,6 +26,12 @@ const struct xfs_name xfs_name_dotdot = {
        .type   = XFS_DIR3_FT_DIR,
 };
 
+const struct xfs_name xfs_name_dot = {
+       .name   = (const unsigned char *)".",
+       .len    = 1,
+       .type   = XFS_DIR3_FT_DIR,
+};
+
 /*
  * Convert inode mode to directory entry filetype
  */
@@ -104,13 +111,13 @@ xfs_da_mount(
        ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
        ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE);
 
-       mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
-                                   KM_MAYFAIL);
-       mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
-                                    KM_MAYFAIL);
+       mp->m_dir_geo = kzalloc(sizeof(struct xfs_da_geometry),
+                               GFP_KERNEL | __GFP_RETRY_MAYFAIL);
+       mp->m_attr_geo = kzalloc(sizeof(struct xfs_da_geometry),
+                               GFP_KERNEL | __GFP_RETRY_MAYFAIL);
        if (!mp->m_dir_geo || !mp->m_attr_geo) {
-               kmem_free(mp->m_dir_geo);
-               kmem_free(mp->m_attr_geo);
+               kfree(mp->m_dir_geo);
+               kfree(mp->m_attr_geo);
                return -ENOMEM;
        }
 
@@ -178,8 +185,8 @@ void
 xfs_da_unmount(
        struct xfs_mount        *mp)
 {
-       kmem_free(mp->m_dir_geo);
-       kmem_free(mp->m_attr_geo);
+       kfree(mp->m_dir_geo);
+       kfree(mp->m_attr_geo);
 }
 
 /*
@@ -236,7 +243,7 @@ xfs_dir_init(
        if (error)
                return error;
 
-       args = kmem_zalloc(sizeof(*args), KM_NOFS);
+       args = kzalloc(sizeof(*args), GFP_KERNEL | __GFP_NOFAIL);
        if (!args)
                return -ENOMEM;
 
@@ -244,7 +251,7 @@ xfs_dir_init(
        args->dp = dp;
        args->trans = tp;
        error = xfs_dir2_sf_create(args, pdp->i_ino);
-       kmem_free(args);
+       kfree(args);
        return error;
 }
 
@@ -273,7 +280,7 @@ xfs_dir_createname(
                XFS_STATS_INC(dp->i_mount, xs_dir_create);
        }
 
-       args = kmem_zalloc(sizeof(*args), KM_NOFS);
+       args = kzalloc(sizeof(*args), GFP_KERNEL | __GFP_NOFAIL);
        if (!args)
                return -ENOMEM;
 
@@ -313,7 +320,7 @@ xfs_dir_createname(
                rval = xfs_dir2_node_addname(args);
 
 out_free:
-       kmem_free(args);
+       kfree(args);
        return rval;
 }
 
@@ -333,7 +340,8 @@ xfs_dir_cilookup_result(
                                        !(args->op_flags & XFS_DA_OP_CILOOKUP))
                return -EEXIST;
 
-       args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
+       args->value = kmalloc(len,
+                       GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_RETRY_MAYFAIL);
        if (!args->value)
                return -ENOMEM;
 
@@ -364,15 +372,8 @@ xfs_dir_lookup(
        ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
        XFS_STATS_INC(dp->i_mount, xs_dir_lookup);
 
-       /*
-        * We need to use KM_NOFS here so that lockdep will not throw false
-        * positive deadlock warnings on a non-transactional lookup path. It is
-        * safe to recurse into inode recalim in that case, but lockdep can't
-        * easily be taught about it. Hence KM_NOFS avoids having to add more
-        * lockdep Doing this avoids having to add a bunch of lockdep class
-        * annotations into the reclaim path for the ilock.
-        */
-       args = kmem_zalloc(sizeof(*args), KM_NOFS);
+       args = kzalloc(sizeof(*args),
+                       GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL);
        args->geo = dp->i_mount->m_dir_geo;
        args->name = name->name;
        args->namelen = name->len;
@@ -419,7 +420,7 @@ out_check_rval:
        }
 out_free:
        xfs_iunlock(dp, lock_mode);
-       kmem_free(args);
+       kfree(args);
        return rval;
 }
 
@@ -441,7 +442,7 @@ xfs_dir_removename(
        ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
        XFS_STATS_INC(dp->i_mount, xs_dir_remove);
 
-       args = kmem_zalloc(sizeof(*args), KM_NOFS);
+       args = kzalloc(sizeof(*args), GFP_KERNEL | __GFP_NOFAIL);
        if (!args)
                return -ENOMEM;
 
@@ -477,7 +478,7 @@ xfs_dir_removename(
        else
                rval = xfs_dir2_node_removename(args);
 out_free:
-       kmem_free(args);
+       kfree(args);
        return rval;
 }
 
@@ -502,7 +503,7 @@ xfs_dir_replace(
        if (rval)
                return rval;
 
-       args = kmem_zalloc(sizeof(*args), KM_NOFS);
+       args = kzalloc(sizeof(*args), GFP_KERNEL | __GFP_NOFAIL);
        if (!args)
                return -ENOMEM;
 
@@ -538,7 +539,7 @@ xfs_dir_replace(
        else
                rval = xfs_dir2_node_replace(args);
 out_free:
-       kmem_free(args);
+       kfree(args);
        return rval;
 }
 
@@ -626,8 +627,10 @@ xfs_dir2_isblock(
                return 0;
 
        *isblock = true;
-       if (XFS_IS_CORRUPT(mp, args->dp->i_disk_size != args->geo->blksize))
+       if (XFS_IS_CORRUPT(mp, args->dp->i_disk_size != args->geo->blksize)) {
+               xfs_da_mark_sick(args);
                return -EFSCORRUPTED;
+       }
        return 0;
 }