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-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 348 362 96.1 %
Date: 2023-07-31 20:08:12 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             : #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  1433315666 : xfs_mode_to_ftype(
      40             :         int             mode)
      41             : {
      42  1433315666 :         switch (mode & S_IFMT) {
      43             :         case S_IFREG:
      44             :                 return XFS_DIR3_FT_REG_FILE;
      45   168586861 :         case S_IFDIR:
      46   168586861 :                 return XFS_DIR3_FT_DIR;
      47   221783977 :         case S_IFCHR:
      48   221783977 :                 return XFS_DIR3_FT_CHRDEV;
      49         378 :         case S_IFBLK:
      50         378 :                 return XFS_DIR3_FT_BLKDEV;
      51       10345 :         case S_IFIFO:
      52       10345 :                 return XFS_DIR3_FT_FIFO;
      53          88 :         case S_IFSOCK:
      54          88 :                 return XFS_DIR3_FT_SOCK;
      55   642274773 :         case S_IFLNK:
      56   642274773 :                 return XFS_DIR3_FT_SYMLINK;
      57    34563561 :         default:
      58    34563561 :                 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     7285897 : xfs_ascii_ci_hashname(
      68             :         const struct xfs_name   *name)
      69             : {
      70     7285897 :         xfs_dahash_t            hash;
      71     7285897 :         int                     i;
      72             : 
      73   176589438 :         for (i = 0, hash = 0; i < name->len; i++)
      74   169303541 :                 hash = xfs_ascii_ci_xfrm(name->name[i]) ^ rol32(hash, 7);
      75             : 
      76     7285897 :         return hash;
      77             : }
      78             : 
      79             : enum xfs_dacmp
      80  1906245261 : xfs_ascii_ci_compname(
      81             :         struct xfs_da_args      *args,
      82             :         const unsigned char     *name,
      83             :         int                     len)
      84             : {
      85  1906245261 :         enum xfs_dacmp          result;
      86  1906245261 :         int                     i;
      87             : 
      88  1906245261 :         if (args->namelen != len)
      89             :                 return XFS_CMP_DIFFERENT;
      90             : 
      91             :         result = XFS_CMP_EXACT;
      92   102992870 :         for (i = 0; i < len; i++) {
      93   102213591 :                 if (args->name[i] == name[i])
      94    21724336 :                         continue;
      95    80489255 :                 if (xfs_ascii_ci_xfrm(args->name[i]) !=
      96    80489255 :                     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       60764 : xfs_da_mount(
     106             :         struct xfs_mount        *mp)
     107             : {
     108       60764 :         struct xfs_da_geometry  *dageo;
     109             : 
     110             : 
     111       60764 :         ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
     112       60764 :         ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE);
     113             : 
     114       60764 :         mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
     115             :                                     KM_MAYFAIL);
     116       60764 :         mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
     117             :                                      KM_MAYFAIL);
     118       60764 :         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       60764 :         dageo = mp->m_dir_geo;
     126       60764 :         dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
     127       60764 :         dageo->fsblog = mp->m_sb.sb_blocklog;
     128       60764 :         dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb);
     129       60764 :         dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
     130       60764 :         if (xfs_has_crc(mp)) {
     131       60569 :                 dageo->node_hdr_size = sizeof(struct xfs_da3_node_hdr);
     132       60569 :                 dageo->leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr);
     133       60569 :                 dageo->free_hdr_size = sizeof(struct xfs_dir3_free_hdr);
     134       60569 :                 dageo->data_entry_offset =
     135             :                                 sizeof(struct xfs_dir3_data_hdr);
     136             :         } else {
     137         195 :                 dageo->node_hdr_size = sizeof(struct xfs_da_node_hdr);
     138         195 :                 dageo->leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr);
     139         195 :                 dageo->free_hdr_size = sizeof(struct xfs_dir2_free_hdr);
     140         195 :                 dageo->data_entry_offset =
     141             :                                 sizeof(struct xfs_dir2_data_hdr);
     142             :         }
     143       60764 :         dageo->leaf_max_ents = (dageo->blksize - dageo->leaf_hdr_size) /
     144             :                         sizeof(struct xfs_dir2_leaf_entry);
     145       60764 :         dageo->free_max_bests = (dageo->blksize - dageo->free_hdr_size) /
     146             :                         sizeof(xfs_dir2_data_off_t);
     147             : 
     148       60764 :         dageo->data_first_offset = dageo->data_entry_offset +
     149       60764 :                         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       60764 :         dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
     157       60764 :         dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
     158       60764 :         dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
     159       60764 :         dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
     160             :                                 (uint)sizeof(xfs_da_node_entry_t);
     161           0 :         dageo->max_extents = (XFS_DIR2_MAX_SPACES * XFS_DIR2_SPACE_SIZE) >>
     162       60764 :                                         mp->m_sb.sb_blocklog;
     163       60764 :         dageo->magicpct = (dageo->blksize * 37) / 100;
     164             : 
     165             :         /* set up attribute geometry - single fsb only */
     166       60764 :         dageo = mp->m_attr_geo;
     167       60764 :         dageo->blklog = mp->m_sb.sb_blocklog;
     168       60764 :         dageo->fsblog = mp->m_sb.sb_blocklog;
     169       60764 :         dageo->blksize = 1 << dageo->blklog;
     170       60764 :         dageo->fsbcount = 1;
     171       60764 :         dageo->node_hdr_size = mp->m_dir_geo->node_hdr_size;
     172       60764 :         dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
     173             :                                 (uint)sizeof(xfs_da_node_entry_t);
     174             : 
     175       60764 :         if (xfs_has_large_extent_counts(mp))
     176       60558 :                 dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_LARGE;
     177             :         else
     178         206 :                 dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_SMALL;
     179             : 
     180       60764 :         dageo->magicpct = (dageo->blksize * 37) / 100;
     181       60764 :         return 0;
     182             : }
     183             : 
     184             : void
     185       60774 : xfs_da_unmount(
     186             :         struct xfs_mount        *mp)
     187             : {
     188       60774 :         kmem_free(mp->m_dir_geo);
     189       60774 :         kmem_free(mp->m_attr_geo);
     190       60774 : }
     191             : 
     192             : /*
     193             :  * Return 1 if directory contains only "." and "..".
     194             :  */
     195             : int
     196     2329555 : xfs_dir_isempty(
     197             :         xfs_inode_t     *dp)
     198             : {
     199     2329555 :         xfs_dir2_sf_hdr_t       *sfp;
     200             : 
     201     2329555 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     202     2329555 :         if (dp->i_disk_size == 0)    /* might happen during shutdown. */
     203             :                 return 1;
     204     2329555 :         if (dp->i_disk_size > xfs_inode_data_fork_size(dp))
     205             :                 return 0;
     206     2326925 :         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
     207     2326925 :         return !sfp->count;
     208             : }
     209             : 
     210             : /*
     211             :  * Validate a given inode number.
     212             :  */
     213             : int
     214  1112321346 : xfs_dir_ino_validate(
     215             :         xfs_mount_t     *mp,
     216             :         xfs_ino_t       ino)
     217             : {
     218  1112321346 :         bool            ino_ok = xfs_verify_dir_ino(mp, ino);
     219             : 
     220  2224397631 :         if (XFS_IS_CORRUPT(mp, !ino_ok) ||
     221  1112215540 :             XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DIR_INO_VALIDATE)) {
     222          11 :                 xfs_warn(mp, "Invalid inode number 0x%Lx",
     223             :                                 (unsigned long long) ino);
     224          11 :                 return -EFSCORRUPTED;
     225             :         }
     226             :         return 0;
     227             : }
     228             : 
     229             : /*
     230             :  * Initialize a directory with its "." and ".." entries.
     231             :  */
     232             : int
     233    12194944 : xfs_dir_init(
     234             :         xfs_trans_t     *tp,
     235             :         xfs_inode_t     *dp,
     236             :         xfs_inode_t     *pdp)
     237             : {
     238    12194944 :         struct xfs_da_args *args;
     239    12194944 :         int             error;
     240             : 
     241    12194944 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     242    12194944 :         error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
     243    12195471 :         if (error)
     244             :                 return error;
     245             : 
     246    12195673 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     247    12195045 :         if (!args)
     248             :                 return -ENOMEM;
     249             : 
     250    12195045 :         args->geo = dp->i_mount->m_dir_geo;
     251    12195045 :         args->dp = dp;
     252    12195045 :         args->trans = tp;
     253    12195045 :         args->owner = dp->i_ino;
     254    12195045 :         error = xfs_dir2_sf_create(args, pdp->i_ino);
     255    12196865 :         kmem_free(args);
     256    12196865 :         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   142656826 : 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   142656826 :         struct xfs_da_args      *args;
     272   142656826 :         int                     rval;
     273   142656826 :         bool                    v;
     274             : 
     275   142656826 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     276             : 
     277   142656826 :         if (inum) {
     278   142641141 :                 rval = xfs_dir_ino_validate(tp->t_mountp, inum);
     279   142562661 :                 if (rval)
     280             :                         return rval;
     281   142562661 :                 XFS_STATS_INC(dp->i_mount, xs_dir_create);
     282             :         }
     283             : 
     284   142614179 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     285   142598259 :         if (!args)
     286             :                 return -ENOMEM;
     287             : 
     288   142598259 :         args->geo = dp->i_mount->m_dir_geo;
     289   142598259 :         args->name = name->name;
     290   142598259 :         args->namelen = name->len;
     291   142598259 :         args->filetype = name->type;
     292   142598259 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     293   142545226 :         args->inumber = inum;
     294   142545226 :         args->dp = dp;
     295   142545226 :         args->total = total;
     296   142545226 :         args->whichfork = XFS_DATA_FORK;
     297   142545226 :         args->trans = tp;
     298   142545226 :         args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
     299   142545226 :         args->owner = dp->i_ino;
     300   142545226 :         if (!inum)
     301        3686 :                 args->op_flags |= XFS_DA_OP_JUSTCHECK;
     302             : 
     303   142545226 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     304    79513834 :                 rval = xfs_dir2_sf_addname(args);
     305    79535720 :                 goto out_free;
     306             :         }
     307             : 
     308    63031392 :         rval = xfs_dir2_isblock(args, &v);
     309    63152714 :         if (rval)
     310           0 :                 goto out_free;
     311    63152714 :         if (v) {
     312     6800776 :                 rval = xfs_dir2_block_addname(args);
     313     6806007 :                 goto out_free;
     314             :         }
     315             : 
     316    56351938 :         rval = xfs_dir2_isleaf(args, &v);
     317    56395025 :         if (rval)
     318           0 :                 goto out_free;
     319    56395025 :         if (v)
     320    12051808 :                 rval = xfs_dir2_leaf_addname(args);
     321             :         else
     322    44343217 :                 rval = xfs_dir2_node_addname(args);
     323             : 
     324   142690009 : out_free:
     325   142690009 :         kmem_free(args);
     326   142690009 :         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    28784286 : xfs_dir_cilookup_result(
     335             :         struct xfs_da_args *args,
     336             :         const unsigned char *name,
     337             :         int             len)
     338             : {
     339    28784286 :         if (args->cmpresult == XFS_CMP_DIFFERENT)
     340             :                 return -ENOENT;
     341    28784286 :         if (args->cmpresult != XFS_CMP_CASE ||
     342             :                                         !(args->op_flags & XFS_DA_OP_CILOOKUP))
     343             :                 return -EEXIST;
     344             : 
     345      484528 :         args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
     346      484528 :         if (!args->value)
     347             :                 return -ENOMEM;
     348             : 
     349      969056 :         memcpy(args->value, name, len);
     350      484528 :         args->valuelen = len;
     351      484528 :         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   206334635 : 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   206334635 :         struct xfs_da_args      *args;
     369   206334635 :         int                     rval;
     370   206334635 :         bool                    v;
     371   206334635 :         int                     lock_mode;
     372             : 
     373   206334635 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     374   206334635 :         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   206333090 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     385   206444607 :         args->geo = dp->i_mount->m_dir_geo;
     386   206444607 :         args->name = name->name;
     387   206444607 :         args->namelen = name->len;
     388   206444607 :         args->filetype = name->type;
     389   206444607 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     390   206131443 :         args->dp = dp;
     391   206131443 :         args->whichfork = XFS_DATA_FORK;
     392   206131443 :         args->trans = tp;
     393   206131443 :         args->op_flags = XFS_DA_OP_OKNOENT;
     394   206131443 :         args->owner = dp->i_ino;
     395   206131443 :         if (ci_name)
     396     1077163 :                 args->op_flags |= XFS_DA_OP_CILOOKUP;
     397             : 
     398   206131443 :         lock_mode = xfs_ilock_data_map_shared(dp);
     399   206210658 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     400   130366167 :                 rval = xfs_dir2_sf_lookup(args);
     401   130377029 :                 goto out_check_rval;
     402             :         }
     403             : 
     404    75844491 :         rval = xfs_dir2_isblock(args, &v);
     405    76068744 :         if (rval)
     406           0 :                 goto out_free;
     407    76068744 :         if (v) {
     408    17074603 :                 rval = xfs_dir2_block_lookup(args);
     409    17092002 :                 goto out_check_rval;
     410             :         }
     411             : 
     412    58994141 :         rval = xfs_dir2_isleaf(args, &v);
     413    59195537 :         if (rval)
     414           0 :                 goto out_free;
     415    59195537 :         if (v)
     416    24628702 :                 rval = xfs_dir2_leaf_lookup(args);
     417             :         else
     418    34566835 :                 rval = xfs_dir2_node_lookup(args);
     419             : 
     420   206586795 : out_check_rval:
     421   206586795 :         if (rval == -EEXIST)
     422             :                 rval = 0;
     423   149781686 :         if (!rval) {
     424    56816537 :                 *inum = args->inumber;
     425    56816537 :                 if (ci_name) {
     426      699942 :                         ci_name->name = args->value;
     427      699942 :                         ci_name->len = args->valuelen;
     428             :                 }
     429             :         }
     430   205886853 : out_free:
     431   206586795 :         xfs_iunlock(dp, lock_mode);
     432   206196338 :         kmem_free(args);
     433   206391084 :         return rval;
     434             : }
     435             : 
     436             : /*
     437             :  * Remove an entry from a directory.
     438             :  */
     439             : int
     440    95120845 : 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    95120845 :         struct xfs_da_args      *args;
     448    95120845 :         int                     rval;
     449    95120845 :         bool                    v;
     450             : 
     451    95120845 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     452    95120845 :         XFS_STATS_INC(dp->i_mount, xs_dir_remove);
     453             : 
     454    95090900 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     455    95102681 :         if (!args)
     456             :                 return -ENOMEM;
     457             : 
     458    95102681 :         args->geo = dp->i_mount->m_dir_geo;
     459    95102681 :         args->name = name->name;
     460    95102681 :         args->namelen = name->len;
     461    95102681 :         args->filetype = name->type;
     462    95102681 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     463    95086332 :         args->inumber = ino;
     464    95086332 :         args->dp = dp;
     465    95086332 :         args->total = total;
     466    95086332 :         args->whichfork = XFS_DATA_FORK;
     467    95086332 :         args->trans = tp;
     468    95086332 :         args->owner = dp->i_ino;
     469             : 
     470    95086332 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     471    40021697 :                 rval = xfs_dir2_sf_removename(args);
     472    40023387 :                 goto out_free;
     473             :         }
     474             : 
     475    55064635 :         rval = xfs_dir2_isblock(args, &v);
     476    55093279 :         if (rval)
     477           0 :                 goto out_free;
     478    55093279 :         if (v) {
     479     4095009 :                 rval = xfs_dir2_block_removename(args);
     480     4096181 :                 goto out_free;
     481             :         }
     482             : 
     483    50998270 :         rval = xfs_dir2_isleaf(args, &v);
     484    51024302 :         if (rval)
     485           0 :                 goto out_free;
     486    51024302 :         if (v)
     487    11081592 :                 rval = xfs_dir2_leaf_removename(args);
     488             :         else
     489    39942710 :                 rval = xfs_dir2_node_removename(args);
     490    95148830 : out_free:
     491    95148830 :         kmem_free(args);
     492    95148830 :         return rval;
     493             : }
     494             : 
     495             : /*
     496             :  * Replace the inode number of a directory entry.
     497             :  */
     498             : int
     499    49409065 : 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    49409065 :         struct xfs_da_args      *args;
     507    49409065 :         int                     rval;
     508    49409065 :         bool                    v;
     509             : 
     510    49409065 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     511             : 
     512    49409065 :         rval = xfs_dir_ino_validate(tp->t_mountp, inum);
     513    49408947 :         if (rval)
     514             :                 return rval;
     515             : 
     516    49408898 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     517    49408923 :         if (!args)
     518             :                 return -ENOMEM;
     519             : 
     520    49408923 :         args->geo = dp->i_mount->m_dir_geo;
     521    49408923 :         args->name = name->name;
     522    49408923 :         args->namelen = name->len;
     523    49408923 :         args->filetype = name->type;
     524    49408923 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     525    49408778 :         args->inumber = inum;
     526    49408778 :         args->dp = dp;
     527    49408778 :         args->total = total;
     528    49408778 :         args->whichfork = XFS_DATA_FORK;
     529    49408778 :         args->trans = tp;
     530    49408778 :         args->owner = dp->i_ino;
     531             : 
     532    49408778 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     533    46661879 :                 rval = xfs_dir2_sf_replace(args);
     534    46662216 :                 goto out_free;
     535             :         }
     536             : 
     537     2746899 :         rval = xfs_dir2_isblock(args, &v);
     538     2746905 :         if (rval)
     539           0 :                 goto out_free;
     540     2746905 :         if (v) {
     541     1402625 :                 rval = xfs_dir2_block_replace(args);
     542     1402636 :                 goto out_free;
     543             :         }
     544             : 
     545     1344280 :         rval = xfs_dir2_isleaf(args, &v);
     546     1344302 :         if (rval)
     547           0 :                 goto out_free;
     548     1344302 :         if (v)
     549      611966 :                 rval = xfs_dir2_leaf_replace(args);
     550             :         else
     551      732336 :                 rval = xfs_dir2_node_replace(args);
     552    49409140 : out_free:
     553    49409140 :         kmem_free(args);
     554    49409140 :         return rval;
     555             : }
     556             : 
     557             : /*
     558             :  * See if this entry can be added to the directory without allocating space.
     559             :  */
     560             : int
     561        3687 : 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        3687 :         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      724865 : 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      724865 :         struct xfs_inode        *dp = args->dp;
     586      724865 :         struct xfs_mount        *mp = dp->i_mount;
     587      724865 :         xfs_fileoff_t           bno;    /* directory offset of new block */
     588      724865 :         int                     count;  /* count of filesystem blocks */
     589      724865 :         int                     error;
     590             : 
     591      724865 :         trace_xfs_dir2_grow_inode(args, space);
     592             : 
     593             :         /*
     594             :          * Set lowest possible block in the space requested.
     595             :          */
     596      724865 :         bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
     597      724865 :         count = args->geo->fsbcount;
     598             : 
     599      724865 :         error = xfs_da_grow_inode_int(args, &bno, count);
     600      724860 :         if (error)
     601             :                 return error;
     602             : 
     603      724844 :         *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      724819 :         if (space == XFS_DIR2_DATA_SPACE) {
     609      714867 :                 xfs_fsize_t     size;           /* directory file (data) size */
     610             : 
     611      714867 :                 size = XFS_FSB_TO_B(mp, bno + count);
     612      714867 :                 if (size > dp->i_disk_size) {
     613      714094 :                         dp->i_disk_size = size;
     614      714094 :                         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   473683213 : xfs_dir2_isblock(
     625             :         struct xfs_da_args      *args,
     626             :         bool                    *isblock)
     627             : {
     628   473683213 :         struct xfs_mount        *mp = args->dp->i_mount;
     629   473683213 :         xfs_fileoff_t           eof;
     630   473683213 :         int                     error;
     631             : 
     632   473683213 :         error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
     633   474034844 :         if (error)
     634             :                 return error;
     635             : 
     636   474034844 :         *isblock = false;
     637   474034844 :         if (XFS_FSB_TO_B(mp, eof) != args->geo->blksize)
     638             :                 return 0;
     639             : 
     640   134630403 :         *isblock = true;
     641   134630403 :         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   287851589 : xfs_dir2_isleaf(
     653             :         struct xfs_da_args      *args,
     654             :         bool                    *isleaf)
     655             : {
     656   287851589 :         xfs_fileoff_t           eof;
     657   287851589 :         int                     error;
     658             : 
     659   287851589 :         error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
     660   288476939 :         if (error)
     661             :                 return error;
     662             : 
     663   288476939 :         *isleaf = false;
     664   288476939 :         if (eof != args->geo->leafblk + args->geo->fsbcount)
     665             :                 return 0;
     666             : 
     667    55938755 :         *isleaf = true;
     668    55938755 :         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      494697 : xfs_dir2_shrink_inode(
     678             :         struct xfs_da_args      *args,
     679             :         xfs_dir2_db_t           db,
     680             :         struct xfs_buf          *bp)
     681             : {
     682      494697 :         xfs_fileoff_t           bno;            /* directory file offset */
     683      494697 :         xfs_dablk_t             da;             /* directory file offset */
     684      494697 :         int                     done;           /* bunmap is finished */
     685      494697 :         struct xfs_inode        *dp;
     686      494697 :         int                     error;
     687      494697 :         struct xfs_mount        *mp;
     688      494697 :         struct xfs_trans        *tp;
     689             : 
     690      494697 :         trace_xfs_dir2_shrink_inode(args, db);
     691             : 
     692      494697 :         dp = args->dp;
     693      494697 :         mp = dp->i_mount;
     694      494697 :         tp = args->trans;
     695      494697 :         da = xfs_dir2_db_to_da(args->geo, db);
     696             : 
     697             :         /* Unmap the fsblock(s). */
     698      494697 :         error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, &done);
     699      494696 :         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      494696 :         ASSERT(done);
     715             :         /*
     716             :          * Invalidate the buffer from the transaction.
     717             :          */
     718      494696 :         xfs_trans_binval(tp, bp);
     719             :         /*
     720             :          * If it's not a data block, we're done.
     721             :          */
     722      494698 :         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      487232 :         if (dp->i_disk_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
     728             :                 return 0;
     729      381568 :         bno = da;
     730      381568 :         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      381566 :         if (db == args->geo->datablk)
     737      369550 :                 ASSERT(bno == 0);
     738             :         else
     739       12016 :                 ASSERT(bno > 0);
     740             :         /*
     741             :          * Set the size to the new last block.
     742             :          */
     743      381566 :         dp->i_disk_size = XFS_FSB_TO_B(mp, bno);
     744      381566 :         xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
     745      381566 :         return 0;
     746             : }
     747             : 
     748             : /* Returns true if the directory entry name is valid. */
     749             : bool
     750 33357362820 : 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 33357362820 :         if (length >= MAXNAMELEN)
     759             :                 return false;
     760             : 
     761             :         /* There shouldn't be any slashes or nulls here */
     762 >10094*10^7 :         return !memchr(name, '/', length) && !memchr(name, 0, length);
     763             : }
     764             : 
     765             : xfs_dahash_t
     766  4364839904 : xfs_dir2_hashname(
     767             :         struct xfs_mount        *mp,
     768             :         const struct xfs_name   *name)
     769             : {
     770  4364839904 :         if (unlikely(xfs_has_asciici(mp)))
     771     7280897 :                 return xfs_ascii_ci_hashname(name);
     772  4357559007 :         return xfs_da_hashname(name->name, name->len);
     773             : }
     774             : 
     775             : enum xfs_dacmp
     776  3690400016 : xfs_dir2_compname(
     777             :         struct xfs_da_args      *args,
     778             :         const unsigned char     *name,
     779             :         int                     len)
     780             : {
     781  3690400016 :         if (unlikely(xfs_has_asciici(args->dp->i_mount)))
     782  1906245261 :                 return xfs_ascii_ci_compname(args, name, len);
     783  1784154755 :         return xfs_da_compname(args, name, len);
     784             : }

Generated by: LCOV version 1.14