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-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 343 356 96.3 %
Date: 2023-07-31 20:08:17 Functions: 21 21 100.0 %

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

Generated by: LCOV version 1.14