LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_dir2.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 346 362 95.6 %
Date: 2023-07-31 20:08:07 Functions: 20 21 95.2 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
       4             :  * All Rights Reserved.
       5             :  */
       6             : #include "xfs.h"
       7             : #include "xfs_fs.h"
       8             : #include "xfs_shared.h"
       9             : #include "xfs_format.h"
      10             : #include "xfs_log_format.h"
      11             : #include "xfs_trans_resv.h"
      12             : #include "xfs_mount.h"
      13             : #include "xfs_inode.h"
      14             : #include "xfs_trans.h"
      15             : #include "xfs_bmap.h"
      16             : #include "xfs_dir2.h"
      17             : #include "xfs_dir2_priv.h"
      18             : #include "xfs_errortag.h"
      19             : #include "xfs_error.h"
      20             : #include "xfs_trace.h"
      21             : #include "xfs_health.h"
      22             : 
      23             : const struct xfs_name xfs_name_dotdot = {
      24             :         .name   = (const unsigned char *)"..",
      25             :         .len    = 2,
      26             :         .type   = XFS_DIR3_FT_DIR,
      27             : };
      28             : 
      29             : const struct xfs_name xfs_name_dot = {
      30             :         .name   = (const unsigned char *)".",
      31             :         .len    = 1,
      32             :         .type   = XFS_DIR3_FT_DIR,
      33             : };
      34             : 
      35             : /*
      36             :  * Convert inode mode to directory entry filetype
      37             :  */
      38             : unsigned char
      39  1100489369 : xfs_mode_to_ftype(
      40             :         int             mode)
      41             : {
      42  1100489369 :         switch (mode & S_IFMT) {
      43             :         case S_IFREG:
      44             :                 return XFS_DIR3_FT_REG_FILE;
      45   129459318 :         case S_IFDIR:
      46   129459318 :                 return XFS_DIR3_FT_DIR;
      47   242353028 :         case S_IFCHR:
      48   242353028 :                 return XFS_DIR3_FT_CHRDEV;
      49          86 :         case S_IFBLK:
      50          86 :                 return XFS_DIR3_FT_BLKDEV;
      51        1643 :         case S_IFIFO:
      52        1643 :                 return XFS_DIR3_FT_FIFO;
      53          16 :         case S_IFSOCK:
      54          16 :                 return XFS_DIR3_FT_SOCK;
      55   482608416 :         case S_IFLNK:
      56   482608416 :                 return XFS_DIR3_FT_SYMLINK;
      57    21548438 :         default:
      58    21548438 :                 return XFS_DIR3_FT_UNKNOWN;
      59             :         }
      60             : }
      61             : 
      62             : /*
      63             :  * ASCII case-insensitive (ie. A-Z) support for directories that was
      64             :  * used in IRIX.
      65             :  */
      66             : xfs_dahash_t
      67     1681980 : xfs_ascii_ci_hashname(
      68             :         const struct xfs_name   *name)
      69             : {
      70     1681980 :         xfs_dahash_t            hash;
      71     1681980 :         int                     i;
      72             : 
      73    40372967 :         for (i = 0, hash = 0; i < name->len; i++)
      74    38690987 :                 hash = xfs_ascii_ci_xfrm(name->name[i]) ^ rol32(hash, 7);
      75             : 
      76     1681980 :         return hash;
      77             : }
      78             : 
      79             : enum xfs_dacmp
      80   345835803 : xfs_ascii_ci_compname(
      81             :         struct xfs_da_args      *args,
      82             :         const unsigned char     *name,
      83             :         int                     len)
      84             : {
      85   345835803 :         enum xfs_dacmp          result;
      86   345835803 :         int                     i;
      87             : 
      88   345835803 :         if (args->namelen != len)
      89             :                 return XFS_CMP_DIFFERENT;
      90             : 
      91             :         result = XFS_CMP_EXACT;
      92    18599413 :         for (i = 0; i < len; i++) {
      93    18458208 :                 if (args->name[i] == name[i])
      94     3858465 :                         continue;
      95    14599743 :                 if (xfs_ascii_ci_xfrm(args->name[i]) !=
      96    14599743 :                     xfs_ascii_ci_xfrm(name[i]))
      97             :                         return XFS_CMP_DIFFERENT;
      98             :                 result = XFS_CMP_CASE;
      99             :         }
     100             : 
     101             :         return result;
     102             : }
     103             : 
     104             : int
     105       24115 : xfs_da_mount(
     106             :         struct xfs_mount        *mp)
     107             : {
     108       24115 :         struct xfs_da_geometry  *dageo;
     109             : 
     110             : 
     111       24115 :         ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
     112       24115 :         ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE);
     113             : 
     114       24115 :         mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
     115             :                                     KM_MAYFAIL);
     116       24115 :         mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
     117             :                                      KM_MAYFAIL);
     118       24115 :         if (!mp->m_dir_geo || !mp->m_attr_geo) {
     119           0 :                 kmem_free(mp->m_dir_geo);
     120           0 :                 kmem_free(mp->m_attr_geo);
     121           0 :                 return -ENOMEM;
     122             :         }
     123             : 
     124             :         /* set up directory geometry */
     125       24115 :         dageo = mp->m_dir_geo;
     126       24115 :         dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
     127       24115 :         dageo->fsblog = mp->m_sb.sb_blocklog;
     128       24115 :         dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb);
     129       24115 :         dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
     130       24115 :         if (xfs_has_crc(mp)) {
     131       24073 :                 dageo->node_hdr_size = sizeof(struct xfs_da3_node_hdr);
     132       24073 :                 dageo->leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr);
     133       24073 :                 dageo->free_hdr_size = sizeof(struct xfs_dir3_free_hdr);
     134       24073 :                 dageo->data_entry_offset =
     135             :                                 sizeof(struct xfs_dir3_data_hdr);
     136             :         } else {
     137          42 :                 dageo->node_hdr_size = sizeof(struct xfs_da_node_hdr);
     138          42 :                 dageo->leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr);
     139          42 :                 dageo->free_hdr_size = sizeof(struct xfs_dir2_free_hdr);
     140          42 :                 dageo->data_entry_offset =
     141             :                                 sizeof(struct xfs_dir2_data_hdr);
     142             :         }
     143       24115 :         dageo->leaf_max_ents = (dageo->blksize - dageo->leaf_hdr_size) /
     144             :                         sizeof(struct xfs_dir2_leaf_entry);
     145       24115 :         dageo->free_max_bests = (dageo->blksize - dageo->free_hdr_size) /
     146             :                         sizeof(xfs_dir2_data_off_t);
     147             : 
     148       24115 :         dageo->data_first_offset = dageo->data_entry_offset +
     149       24115 :                         xfs_dir2_data_entsize(mp, 1) +
     150             :                         xfs_dir2_data_entsize(mp, 2);
     151             : 
     152             :         /*
     153             :          * Now we've set up the block conversion variables, we can calculate the
     154             :          * segment block constants using the geometry structure.
     155             :          */
     156       24115 :         dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
     157       24115 :         dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
     158       24115 :         dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
     159       24115 :         dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
     160             :                                 (uint)sizeof(xfs_da_node_entry_t);
     161       24115 :         dageo->max_extents = (XFS_DIR2_MAX_SPACES * XFS_DIR2_SPACE_SIZE) >>
     162       24115 :                                         mp->m_sb.sb_blocklog;
     163       24115 :         dageo->magicpct = (dageo->blksize * 37) / 100;
     164             : 
     165             :         /* set up attribute geometry - single fsb only */
     166       24115 :         dageo = mp->m_attr_geo;
     167       24115 :         dageo->blklog = mp->m_sb.sb_blocklog;
     168       24115 :         dageo->fsblog = mp->m_sb.sb_blocklog;
     169       24115 :         dageo->blksize = 1 << dageo->blklog;
     170       24115 :         dageo->fsbcount = 1;
     171       24115 :         dageo->node_hdr_size = mp->m_dir_geo->node_hdr_size;
     172       24115 :         dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
     173             :                                 (uint)sizeof(xfs_da_node_entry_t);
     174             : 
     175       24115 :         if (xfs_has_large_extent_counts(mp))
     176       24071 :                 dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_LARGE;
     177             :         else
     178          44 :                 dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_SMALL;
     179             : 
     180       24115 :         dageo->magicpct = (dageo->blksize * 37) / 100;
     181       24115 :         return 0;
     182             : }
     183             : 
     184             : void
     185       24122 : xfs_da_unmount(
     186             :         struct xfs_mount        *mp)
     187             : {
     188       24122 :         kmem_free(mp->m_dir_geo);
     189       24122 :         kmem_free(mp->m_attr_geo);
     190       24122 : }
     191             : 
     192             : /*
     193             :  * Return 1 if directory contains only "." and "..".
     194             :  */
     195             : int
     196     1061925 : xfs_dir_isempty(
     197             :         xfs_inode_t     *dp)
     198             : {
     199     1061925 :         xfs_dir2_sf_hdr_t       *sfp;
     200             : 
     201     1061925 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     202     1061925 :         if (dp->i_disk_size == 0)    /* might happen during shutdown. */
     203             :                 return 1;
     204     1061925 :         if (dp->i_disk_size > xfs_inode_data_fork_size(dp))
     205             :                 return 0;
     206     1060318 :         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
     207     1060318 :         return !sfp->count;
     208             : }
     209             : 
     210             : /*
     211             :  * Validate a given inode number.
     212             :  */
     213             : int
     214   845943313 : xfs_dir_ino_validate(
     215             :         xfs_mount_t     *mp,
     216             :         xfs_ino_t       ino)
     217             : {
     218   845943313 :         bool            ino_ok = xfs_verify_dir_ino(mp, ino);
     219             : 
     220  1691907341 :         if (XFS_IS_CORRUPT(mp, !ino_ok) ||
     221   845948855 :             XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DIR_INO_VALIDATE)) {
     222           2 :                 xfs_warn(mp, "Invalid inode number 0x%Lx",
     223             :                                 (unsigned long long) ino);
     224           2 :                 return -EFSCORRUPTED;
     225             :         }
     226             :         return 0;
     227             : }
     228             : 
     229             : /*
     230             :  * Initialize a directory with its "." and ".." entries.
     231             :  */
     232             : int
     233     6311429 : xfs_dir_init(
     234             :         xfs_trans_t     *tp,
     235             :         xfs_inode_t     *dp,
     236             :         xfs_inode_t     *pdp)
     237             : {
     238     6311429 :         struct xfs_da_args *args;
     239     6311429 :         int             error;
     240             : 
     241     6311429 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     242     6311429 :         error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
     243     6311406 :         if (error)
     244             :                 return error;
     245             : 
     246     6311421 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     247     6311411 :         if (!args)
     248             :                 return -ENOMEM;
     249             : 
     250     6311411 :         args->geo = dp->i_mount->m_dir_geo;
     251     6311411 :         args->dp = dp;
     252     6311411 :         args->trans = tp;
     253     6311411 :         args->owner = dp->i_ino;
     254     6311411 :         error = xfs_dir2_sf_create(args, pdp->i_ino);
     255     6311289 :         kmem_free(args);
     256     6311289 :         return error;
     257             : }
     258             : 
     259             : /*
     260             :  * Enter a name in a directory, or check for available space.
     261             :  * If inum is 0, only the available space test is performed.
     262             :  */
     263             : int
     264    85567532 : xfs_dir_createname(
     265             :         struct xfs_trans        *tp,
     266             :         struct xfs_inode        *dp,
     267             :         const struct xfs_name   *name,
     268             :         xfs_ino_t               inum,           /* new entry inode number */
     269             :         xfs_extlen_t            total)          /* bmap's total block count */
     270             : {
     271    85567532 :         struct xfs_da_args      *args;
     272    85567532 :         int                     rval;
     273    85567532 :         bool                    v;
     274             : 
     275    85567532 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     276             : 
     277    85567532 :         if (inum) {
     278    85567599 :                 rval = xfs_dir_ino_validate(tp->t_mountp, inum);
     279    85568840 :                 if (rval)
     280             :                         return rval;
     281    85568840 :                 XFS_STATS_INC(dp->i_mount, xs_dir_create);
     282             :         }
     283             : 
     284    85568773 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     285    85566095 :         if (!args)
     286             :                 return -ENOMEM;
     287             : 
     288    85566095 :         args->geo = dp->i_mount->m_dir_geo;
     289    85566095 :         args->name = name->name;
     290    85566095 :         args->namelen = name->len;
     291    85566095 :         args->filetype = name->type;
     292    85566095 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     293    85565015 :         args->inumber = inum;
     294    85565015 :         args->dp = dp;
     295    85565015 :         args->total = total;
     296    85565015 :         args->whichfork = XFS_DATA_FORK;
     297    85565015 :         args->trans = tp;
     298    85565015 :         args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
     299    85565015 :         args->owner = dp->i_ino;
     300    85565015 :         if (!inum)
     301           0 :                 args->op_flags |= XFS_DA_OP_JUSTCHECK;
     302             : 
     303    85565015 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     304    46337384 :                 rval = xfs_dir2_sf_addname(args);
     305    46339599 :                 goto out_free;
     306             :         }
     307             : 
     308    39227631 :         rval = xfs_dir2_isblock(args, &v);
     309    39230831 :         if (rval)
     310           0 :                 goto out_free;
     311    39230831 :         if (v) {
     312     2268982 :                 rval = xfs_dir2_block_addname(args);
     313     2269183 :                 goto out_free;
     314             :         }
     315             : 
     316    36961849 :         rval = xfs_dir2_isleaf(args, &v);
     317    36960537 :         if (rval)
     318           0 :                 goto out_free;
     319    36960537 :         if (v)
     320     4704825 :                 rval = xfs_dir2_leaf_addname(args);
     321             :         else
     322    32255712 :                 rval = xfs_dir2_node_addname(args);
     323             : 
     324    85570353 : out_free:
     325    85570353 :         kmem_free(args);
     326    85570353 :         return rval;
     327             : }
     328             : 
     329             : /*
     330             :  * If doing a CI lookup and case-insensitive match, dup actual name into
     331             :  * args.value. Return EEXIST for success (ie. name found) or an error.
     332             :  */
     333             : int
     334    30400800 : xfs_dir_cilookup_result(
     335             :         struct xfs_da_args *args,
     336             :         const unsigned char *name,
     337             :         int             len)
     338             : {
     339    30400800 :         if (args->cmpresult == XFS_CMP_DIFFERENT)
     340             :                 return -ENOENT;
     341    30400800 :         if (args->cmpresult != XFS_CMP_CASE ||
     342             :                                         !(args->op_flags & XFS_DA_OP_CILOOKUP))
     343             :                 return -EEXIST;
     344             : 
     345       88096 :         args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
     346       88096 :         if (!args->value)
     347             :                 return -ENOMEM;
     348             : 
     349      176192 :         memcpy(args->value, name, len);
     350       88096 :         args->valuelen = len;
     351       88096 :         return -EEXIST;
     352             : }
     353             : 
     354             : /*
     355             :  * Lookup a name in a directory, give back the inode number.
     356             :  * If ci_name is not NULL, returns the actual name in ci_name if it differs
     357             :  * to name, or ci_name->name is set to NULL for an exact match.
     358             :  */
     359             : 
     360             : int
     361   192884765 : xfs_dir_lookup(
     362             :         struct xfs_trans        *tp,
     363             :         struct xfs_inode        *dp,
     364             :         const struct xfs_name   *name,
     365             :         xfs_ino_t               *inum,    /* out: inode number */
     366             :         struct xfs_name         *ci_name) /* out: actual name if CI match */
     367             : {
     368   192884765 :         struct xfs_da_args      *args;
     369   192884765 :         int                     rval;
     370   192884765 :         bool                    v;
     371   192884765 :         int                     lock_mode;
     372             : 
     373   192884765 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     374   192884765 :         XFS_STATS_INC(dp->i_mount, xs_dir_lookup);
     375             : 
     376             :         /*
     377             :          * We need to use KM_NOFS here so that lockdep will not throw false
     378             :          * positive deadlock warnings on a non-transactional lookup path. It is
     379             :          * safe to recurse into inode recalim in that case, but lockdep can't
     380             :          * easily be taught about it. Hence KM_NOFS avoids having to add more
     381             :          * lockdep Doing this avoids having to add a bunch of lockdep class
     382             :          * annotations into the reclaim path for the ilock.
     383             :          */
     384   192884765 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     385   192874018 :         args->geo = dp->i_mount->m_dir_geo;
     386   192874018 :         args->name = name->name;
     387   192874018 :         args->namelen = name->len;
     388   192874018 :         args->filetype = name->type;
     389   192874018 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     390   192886249 :         args->dp = dp;
     391   192886249 :         args->whichfork = XFS_DATA_FORK;
     392   192886249 :         args->trans = tp;
     393   192886249 :         args->op_flags = XFS_DA_OP_OKNOENT;
     394   192886249 :         args->owner = dp->i_ino;
     395   192886249 :         if (ci_name)
     396      195894 :                 args->op_flags |= XFS_DA_OP_CILOOKUP;
     397             : 
     398   192886249 :         lock_mode = xfs_ilock_data_map_shared(dp);
     399   192882964 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     400   150580160 :                 rval = xfs_dir2_sf_lookup(args);
     401   150578869 :                 goto out_check_rval;
     402             :         }
     403             : 
     404    42302804 :         rval = xfs_dir2_isblock(args, &v);
     405    42300856 :         if (rval)
     406           0 :                 goto out_free;
     407    42300856 :         if (v) {
     408    21706858 :                 rval = xfs_dir2_block_lookup(args);
     409    21706432 :                 goto out_check_rval;
     410             :         }
     411             : 
     412    20593998 :         rval = xfs_dir2_isleaf(args, &v);
     413    20606131 :         if (rval)
     414           0 :                 goto out_free;
     415    20606131 :         if (v)
     416    10015176 :                 rval = xfs_dir2_leaf_lookup(args);
     417             :         else
     418    10590955 :                 rval = xfs_dir2_node_lookup(args);
     419             : 
     420   192896283 : out_check_rval:
     421   192896283 :         if (rval == -EEXIST)
     422             :                 rval = 0;
     423    73164556 :         if (!rval) {
     424   119730073 :                 *inum = args->inumber;
     425   119730073 :                 if (ci_name) {
     426      103142 :                         ci_name->name = args->value;
     427      103142 :                         ci_name->len = args->valuelen;
     428             :                 }
     429             :         }
     430   192793213 : out_free:
     431   192896283 :         xfs_iunlock(dp, lock_mode);
     432   192893066 :         kmem_free(args);
     433   192895348 :         return rval;
     434             : }
     435             : 
     436             : /*
     437             :  * Remove an entry from a directory.
     438             :  */
     439             : int
     440    60550358 : xfs_dir_removename(
     441             :         struct xfs_trans        *tp,
     442             :         struct xfs_inode        *dp,
     443             :         const struct xfs_name   *name,
     444             :         xfs_ino_t               ino,
     445             :         xfs_extlen_t            total)          /* bmap's total block count */
     446             : {
     447    60550358 :         struct xfs_da_args      *args;
     448    60550358 :         int                     rval;
     449    60550358 :         bool                    v;
     450             : 
     451    60550358 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     452    60550358 :         XFS_STATS_INC(dp->i_mount, xs_dir_remove);
     453             : 
     454    60550358 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     455    60551132 :         if (!args)
     456             :                 return -ENOMEM;
     457             : 
     458    60551132 :         args->geo = dp->i_mount->m_dir_geo;
     459    60551132 :         args->name = name->name;
     460    60551132 :         args->namelen = name->len;
     461    60551132 :         args->filetype = name->type;
     462    60551132 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     463    60551309 :         args->inumber = ino;
     464    60551309 :         args->dp = dp;
     465    60551309 :         args->total = total;
     466    60551309 :         args->whichfork = XFS_DATA_FORK;
     467    60551309 :         args->trans = tp;
     468    60551309 :         args->owner = dp->i_ino;
     469             : 
     470    60551309 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     471    23954289 :                 rval = xfs_dir2_sf_removename(args);
     472    23954556 :                 goto out_free;
     473             :         }
     474             : 
     475    36597020 :         rval = xfs_dir2_isblock(args, &v);
     476    36597173 :         if (rval)
     477           0 :                 goto out_free;
     478    36597173 :         if (v) {
     479     1690684 :                 rval = xfs_dir2_block_removename(args);
     480     1690682 :                 goto out_free;
     481             :         }
     482             : 
     483    34906489 :         rval = xfs_dir2_isleaf(args, &v);
     484    34906633 :         if (rval)
     485           0 :                 goto out_free;
     486    34906633 :         if (v)
     487     4611384 :                 rval = xfs_dir2_leaf_removename(args);
     488             :         else
     489    30295249 :                 rval = xfs_dir2_node_removename(args);
     490    60552316 : out_free:
     491    60552316 :         kmem_free(args);
     492    60552316 :         return rval;
     493             : }
     494             : 
     495             : /*
     496             :  * Replace the inode number of a directory entry.
     497             :  */
     498             : int
     499    31401761 : xfs_dir_replace(
     500             :         struct xfs_trans        *tp,
     501             :         struct xfs_inode        *dp,
     502             :         const struct xfs_name   *name,          /* name of entry to replace */
     503             :         xfs_ino_t               inum,           /* new inode number */
     504             :         xfs_extlen_t            total)          /* bmap's total block count */
     505             : {
     506    31401761 :         struct xfs_da_args      *args;
     507    31401761 :         int                     rval;
     508    31401761 :         bool                    v;
     509             : 
     510    31401761 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     511             : 
     512    31401761 :         rval = xfs_dir_ino_validate(tp->t_mountp, inum);
     513    31401760 :         if (rval)
     514             :                 return rval;
     515             : 
     516    31401765 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     517    31401759 :         if (!args)
     518             :                 return -ENOMEM;
     519             : 
     520    31401759 :         args->geo = dp->i_mount->m_dir_geo;
     521    31401759 :         args->name = name->name;
     522    31401759 :         args->namelen = name->len;
     523    31401759 :         args->filetype = name->type;
     524    31401759 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     525    31401742 :         args->inumber = inum;
     526    31401742 :         args->dp = dp;
     527    31401742 :         args->total = total;
     528    31401742 :         args->whichfork = XFS_DATA_FORK;
     529    31401742 :         args->trans = tp;
     530    31401742 :         args->owner = dp->i_ino;
     531             : 
     532    31401742 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     533    29801173 :                 rval = xfs_dir2_sf_replace(args);
     534    29801186 :                 goto out_free;
     535             :         }
     536             : 
     537     1600569 :         rval = xfs_dir2_isblock(args, &v);
     538     1600573 :         if (rval)
     539           0 :                 goto out_free;
     540     1600573 :         if (v) {
     541      881048 :                 rval = xfs_dir2_block_replace(args);
     542      881047 :                 goto out_free;
     543             :         }
     544             : 
     545      719525 :         rval = xfs_dir2_isleaf(args, &v);
     546      719524 :         if (rval)
     547           0 :                 goto out_free;
     548      719524 :         if (v)
     549      210662 :                 rval = xfs_dir2_leaf_replace(args);
     550             :         else
     551      508862 :                 rval = xfs_dir2_node_replace(args);
     552    31401759 : out_free:
     553    31401759 :         kmem_free(args);
     554    31401759 :         return rval;
     555             : }
     556             : 
     557             : /*
     558             :  * See if this entry can be added to the directory without allocating space.
     559             :  */
     560             : int
     561           0 : xfs_dir_canenter(
     562             :         xfs_trans_t     *tp,
     563             :         xfs_inode_t     *dp,
     564             :         struct xfs_name *name)          /* name of entry to add */
     565             : {
     566           0 :         return xfs_dir_createname(tp, dp, name, 0, 0);
     567             : }
     568             : 
     569             : /*
     570             :  * Utility routines.
     571             :  */
     572             : 
     573             : /*
     574             :  * Add a block to the directory.
     575             :  *
     576             :  * This routine is for data and free blocks, not leaf/node blocks which are
     577             :  * handled by xfs_da_grow_inode.
     578             :  */
     579             : int
     580      352968 : xfs_dir2_grow_inode(
     581             :         struct xfs_da_args      *args,
     582             :         int                     space,  /* v2 dir's space XFS_DIR2_xxx_SPACE */
     583             :         xfs_dir2_db_t           *dbp)   /* out: block number added */
     584             : {
     585      352968 :         struct xfs_inode        *dp = args->dp;
     586      352968 :         struct xfs_mount        *mp = dp->i_mount;
     587      352968 :         xfs_fileoff_t           bno;    /* directory offset of new block */
     588      352968 :         int                     count;  /* count of filesystem blocks */
     589      352968 :         int                     error;
     590             : 
     591      352968 :         trace_xfs_dir2_grow_inode(args, space);
     592             : 
     593             :         /*
     594             :          * Set lowest possible block in the space requested.
     595             :          */
     596      352968 :         bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
     597      352968 :         count = args->geo->fsbcount;
     598             : 
     599      352968 :         error = xfs_da_grow_inode_int(args, &bno, count);
     600      352965 :         if (error)
     601             :                 return error;
     602             : 
     603      352964 :         *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno);
     604             : 
     605             :         /*
     606             :          * Update file's size if this is the data space and it grew.
     607             :          */
     608      352964 :         if (space == XFS_DIR2_DATA_SPACE) {
     609      351269 :                 xfs_fsize_t     size;           /* directory file (data) size */
     610             : 
     611      351269 :                 size = XFS_FSB_TO_B(mp, bno + count);
     612      351269 :                 if (size > dp->i_disk_size) {
     613      350474 :                         dp->i_disk_size = size;
     614      350474 :                         xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
     615             :                 }
     616             :         }
     617             :         return 0;
     618             : }
     619             : 
     620             : /*
     621             :  * See if the directory is a single-block form directory.
     622             :  */
     623             : int
     624   233117176 : xfs_dir2_isblock(
     625             :         struct xfs_da_args      *args,
     626             :         bool                    *isblock)
     627             : {
     628   233117176 :         struct xfs_mount        *mp = args->dp->i_mount;
     629   233117176 :         xfs_fileoff_t           eof;
     630   233117176 :         int                     error;
     631             : 
     632   233117176 :         error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
     633   233153620 :         if (error)
     634             :                 return error;
     635             : 
     636   233153620 :         *isblock = false;
     637   233153620 :         if (XFS_FSB_TO_B(mp, eof) != args->geo->blksize)
     638             :                 return 0;
     639             : 
     640    47410009 :         *isblock = true;
     641    47410009 :         if (XFS_IS_CORRUPT(mp, args->dp->i_disk_size != args->geo->blksize)) {
     642           0 :                 xfs_da_mark_sick(args);
     643           0 :                 return -EFSCORRUPTED;
     644             :         }
     645             :         return 0;
     646             : }
     647             : 
     648             : /*
     649             :  * See if the directory is a single-leaf form directory.
     650             :  */
     651             : int
     652   165637381 : xfs_dir2_isleaf(
     653             :         struct xfs_da_args      *args,
     654             :         bool                    *isleaf)
     655             : {
     656   165637381 :         xfs_fileoff_t           eof;
     657   165637381 :         int                     error;
     658             : 
     659   165637381 :         error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
     660   165632136 :         if (error)
     661             :                 return error;
     662             : 
     663   165632136 :         *isleaf = false;
     664   165632136 :         if (eof != args->geo->leafblk + args->geo->fsbcount)
     665             :                 return 0;
     666             : 
     667    21582546 :         *isleaf = true;
     668    21582546 :         return 0;
     669             : }
     670             : 
     671             : /*
     672             :  * Remove the given block from the directory.
     673             :  * This routine is used for data and free blocks, leaf/node are done
     674             :  * by xfs_da_shrink_inode.
     675             :  */
     676             : int
     677      240143 : xfs_dir2_shrink_inode(
     678             :         struct xfs_da_args      *args,
     679             :         xfs_dir2_db_t           db,
     680             :         struct xfs_buf          *bp)
     681             : {
     682      240143 :         xfs_fileoff_t           bno;            /* directory file offset */
     683      240143 :         xfs_dablk_t             da;             /* directory file offset */
     684      240143 :         int                     done;           /* bunmap is finished */
     685      240143 :         struct xfs_inode        *dp;
     686      240143 :         int                     error;
     687      240143 :         struct xfs_mount        *mp;
     688      240143 :         struct xfs_trans        *tp;
     689             : 
     690      240143 :         trace_xfs_dir2_shrink_inode(args, db);
     691             : 
     692      240143 :         dp = args->dp;
     693      240143 :         mp = dp->i_mount;
     694      240143 :         tp = args->trans;
     695      240143 :         da = xfs_dir2_db_to_da(args->geo, db);
     696             : 
     697             :         /* Unmap the fsblock(s). */
     698      240143 :         error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, &done);
     699      240143 :         if (error) {
     700             :                 /*
     701             :                  * ENOSPC actually can happen if we're in a removename with no
     702             :                  * space reservation, and the resulting block removal would
     703             :                  * cause a bmap btree split or conversion from extents to btree.
     704             :                  * This can only happen for un-fragmented directory blocks,
     705             :                  * since you need to be punching out the middle of an extent.
     706             :                  * In this case we need to leave the block in the file, and not
     707             :                  * binval it.  So the block has to be in a consistent empty
     708             :                  * state and appropriately logged.  We don't free up the buffer,
     709             :                  * the caller can tell it hasn't happened since it got an error
     710             :                  * back.
     711             :                  */
     712             :                 return error;
     713             :         }
     714      240143 :         ASSERT(done);
     715             :         /*
     716             :          * Invalidate the buffer from the transaction.
     717             :          */
     718      240143 :         xfs_trans_binval(tp, bp);
     719             :         /*
     720             :          * If it's not a data block, we're done.
     721             :          */
     722      240143 :         if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET))
     723             :                 return 0;
     724             :         /*
     725             :          * If the block isn't the last one in the directory, we're done.
     726             :          */
     727      238906 :         if (dp->i_disk_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
     728             :                 return 0;
     729      219764 :         bno = da;
     730      219764 :         if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
     731             :                 /*
     732             :                  * This can't really happen unless there's kernel corruption.
     733             :                  */
     734             :                 return error;
     735             :         }
     736      219764 :         if (db == args->geo->datablk)
     737      217278 :                 ASSERT(bno == 0);
     738             :         else
     739        2486 :                 ASSERT(bno > 0);
     740             :         /*
     741             :          * Set the size to the new last block.
     742             :          */
     743      219764 :         dp->i_disk_size = XFS_FSB_TO_B(mp, bno);
     744      219764 :         xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
     745      219764 :         return 0;
     746             : }
     747             : 
     748             : /* Returns true if the directory entry name is valid. */
     749             : bool
     750 28195914665 : xfs_dir2_namecheck(
     751             :         const void      *name,
     752             :         size_t          length)
     753             : {
     754             :         /*
     755             :          * MAXNAMELEN includes the trailing null, but (name/length) leave it
     756             :          * out, so use >= for the length check.
     757             :          */
     758 28195914665 :         if (length >= MAXNAMELEN)
     759             :                 return false;
     760             : 
     761             :         /* There shouldn't be any slashes or nulls here */
     762 83140307551 :         return !memchr(name, '/', length) && !memchr(name, 0, length);
     763             : }
     764             : 
     765             : xfs_dahash_t
     766  2800934544 : xfs_dir2_hashname(
     767             :         struct xfs_mount        *mp,
     768             :         const struct xfs_name   *name)
     769             : {
     770  2800934544 :         if (unlikely(xfs_has_asciici(mp)))
     771     1680780 :                 return xfs_ascii_ci_hashname(name);
     772  2799253764 :         return xfs_da_hashname(name->name, name->len);
     773             : }
     774             : 
     775             : enum xfs_dacmp
     776  1685463145 : xfs_dir2_compname(
     777             :         struct xfs_da_args      *args,
     778             :         const unsigned char     *name,
     779             :         int                     len)
     780             : {
     781  1685463145 :         if (unlikely(xfs_has_asciici(args->dp->i_mount)))
     782   345835803 :                 return xfs_ascii_ci_compname(args, name, len);
     783  1339627342 :         return xfs_da_compname(args, name, len);
     784             : }

Generated by: LCOV version 1.14