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-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 343 356 96.3 %
Date: 2023-07-31 20:08:22 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  1459700637 : xfs_mode_to_ftype(
      33             :         int             mode)
      34             : {
      35  1459700637 :         switch (mode & S_IFMT) {
      36             :         case S_IFREG:
      37             :                 return XFS_DIR3_FT_REG_FILE;
      38   357581413 :         case S_IFDIR:
      39   357581413 :                 return XFS_DIR3_FT_DIR;
      40   252243726 :         case S_IFCHR:
      41   252243726 :                 return XFS_DIR3_FT_CHRDEV;
      42         311 :         case S_IFBLK:
      43         311 :                 return XFS_DIR3_FT_BLKDEV;
      44        9116 :         case S_IFIFO:
      45        9116 :                 return XFS_DIR3_FT_FIFO;
      46          88 :         case S_IFSOCK:
      47          88 :                 return XFS_DIR3_FT_SOCK;
      48   360468374 :         case S_IFLNK:
      49   360468374 :                 return XFS_DIR3_FT_SYMLINK;
      50    33125723 :         default:
      51    33125723 :                 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     6780552 : xfs_ascii_ci_hashname(
      61             :         const struct xfs_name   *name)
      62             : {
      63     6780552 :         xfs_dahash_t            hash;
      64     6780552 :         int                     i;
      65             : 
      66   160781635 :         for (i = 0, hash = 0; i < name->len; i++)
      67   154001083 :                 hash = xfs_ascii_ci_xfrm(name->name[i]) ^ rol32(hash, 7);
      68             : 
      69     6780552 :         return hash;
      70             : }
      71             : 
      72             : enum xfs_dacmp
      73  1906247819 : xfs_ascii_ci_compname(
      74             :         struct xfs_da_args      *args,
      75             :         const unsigned char     *name,
      76             :         int                     len)
      77             : {
      78  1906247819 :         enum xfs_dacmp          result;
      79  1906247819 :         int                     i;
      80             : 
      81  1906247819 :         if (args->namelen != len)
      82             :                 return XFS_CMP_DIFFERENT;
      83             : 
      84             :         result = XFS_CMP_EXACT;
      85   101987843 :         for (i = 0; i < len; i++) {
      86   101214194 :                 if (args->name[i] == name[i])
      87    20725511 :                         continue;
      88    80488683 :                 if (xfs_ascii_ci_xfrm(args->name[i]) !=
      89    80488683 :                     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       59289 : xfs_da_mount(
      99             :         struct xfs_mount        *mp)
     100             : {
     101       59289 :         struct xfs_da_geometry  *dageo;
     102             : 
     103             : 
     104       59289 :         ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
     105       59289 :         ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE);
     106             : 
     107       59289 :         mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
     108             :                                     KM_MAYFAIL);
     109       59289 :         mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
     110             :                                      KM_MAYFAIL);
     111       59289 :         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       59289 :         dageo = mp->m_dir_geo;
     119       59289 :         dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
     120       59289 :         dageo->fsblog = mp->m_sb.sb_blocklog;
     121       59289 :         dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb);
     122       59289 :         dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
     123       59289 :         if (xfs_has_crc(mp)) {
     124       59094 :                 dageo->node_hdr_size = sizeof(struct xfs_da3_node_hdr);
     125       59094 :                 dageo->leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr);
     126       59094 :                 dageo->free_hdr_size = sizeof(struct xfs_dir3_free_hdr);
     127       59094 :                 dageo->data_entry_offset =
     128             :                                 sizeof(struct xfs_dir3_data_hdr);
     129             :         } else {
     130         195 :                 dageo->node_hdr_size = sizeof(struct xfs_da_node_hdr);
     131         195 :                 dageo->leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr);
     132         195 :                 dageo->free_hdr_size = sizeof(struct xfs_dir2_free_hdr);
     133         195 :                 dageo->data_entry_offset =
     134             :                                 sizeof(struct xfs_dir2_data_hdr);
     135             :         }
     136       59289 :         dageo->leaf_max_ents = (dageo->blksize - dageo->leaf_hdr_size) /
     137             :                         sizeof(struct xfs_dir2_leaf_entry);
     138       59289 :         dageo->free_max_bests = (dageo->blksize - dageo->free_hdr_size) /
     139             :                         sizeof(xfs_dir2_data_off_t);
     140             : 
     141       59289 :         dageo->data_first_offset = dageo->data_entry_offset +
     142       59289 :                         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       59289 :         dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
     150       59289 :         dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
     151       59289 :         dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
     152       59289 :         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       59289 :                                         mp->m_sb.sb_blocklog;
     156       59289 :         dageo->magicpct = (dageo->blksize * 37) / 100;
     157             : 
     158             :         /* set up attribute geometry - single fsb only */
     159       59289 :         dageo = mp->m_attr_geo;
     160       59289 :         dageo->blklog = mp->m_sb.sb_blocklog;
     161       59289 :         dageo->fsblog = mp->m_sb.sb_blocklog;
     162       59289 :         dageo->blksize = 1 << dageo->blklog;
     163       59289 :         dageo->fsbcount = 1;
     164       59289 :         dageo->node_hdr_size = mp->m_dir_geo->node_hdr_size;
     165       59289 :         dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
     166             :                                 (uint)sizeof(xfs_da_node_entry_t);
     167             : 
     168       59289 :         if (xfs_has_large_extent_counts(mp))
     169       59040 :                 dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_LARGE;
     170             :         else
     171         249 :                 dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_SMALL;
     172             : 
     173       59289 :         dageo->magicpct = (dageo->blksize * 37) / 100;
     174       59289 :         return 0;
     175             : }
     176             : 
     177             : void
     178       59296 : xfs_da_unmount(
     179             :         struct xfs_mount        *mp)
     180             : {
     181       59296 :         kmem_free(mp->m_dir_geo);
     182       59296 :         kmem_free(mp->m_attr_geo);
     183       59296 : }
     184             : 
     185             : /*
     186             :  * Return 1 if directory contains only "." and "..".
     187             :  */
     188             : int
     189     1583491 : xfs_dir_isempty(
     190             :         xfs_inode_t     *dp)
     191             : {
     192     1583491 :         xfs_dir2_sf_hdr_t       *sfp;
     193             : 
     194     1583491 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     195     1583491 :         if (dp->i_disk_size == 0)    /* might happen during shutdown. */
     196             :                 return 1;
     197     1583491 :         if (dp->i_disk_size > xfs_inode_data_fork_size(dp))
     198             :                 return 0;
     199     1582967 :         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
     200     1582967 :         return !sfp->count;
     201             : }
     202             : 
     203             : /*
     204             :  * Validate a given inode number.
     205             :  */
     206             : int
     207   807153838 : xfs_dir_ino_validate(
     208             :         xfs_mount_t     *mp,
     209             :         xfs_ino_t       ino)
     210             : {
     211   807153838 :         bool            ino_ok = xfs_verify_dir_ino(mp, ino);
     212             : 
     213  1614221054 :         if (XFS_IS_CORRUPT(mp, !ino_ok) ||
     214   807151410 :             XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DIR_INO_VALIDATE)) {
     215          11 :                 xfs_warn(mp, "Invalid inode number 0x%Lx",
     216             :                                 (unsigned long long) ino);
     217          11 :                 return -EFSCORRUPTED;
     218             :         }
     219             :         return 0;
     220             : }
     221             : 
     222             : /*
     223             :  * Initialize a directory with its "." and ".." entries.
     224             :  */
     225             : int
     226     6561261 : xfs_dir_init(
     227             :         xfs_trans_t     *tp,
     228             :         xfs_inode_t     *dp,
     229             :         xfs_inode_t     *pdp)
     230             : {
     231     6561261 :         struct xfs_da_args *args;
     232     6561261 :         int             error;
     233             : 
     234     6561261 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     235     6561261 :         error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
     236     6560842 :         if (error)
     237             :                 return error;
     238             : 
     239     6560945 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     240     6560410 :         if (!args)
     241             :                 return -ENOMEM;
     242             : 
     243     6560410 :         args->geo = dp->i_mount->m_dir_geo;
     244     6560410 :         args->dp = dp;
     245     6560410 :         args->trans = tp;
     246     6560410 :         error = xfs_dir2_sf_create(args, pdp->i_ino);
     247     6561803 :         kmem_free(args);
     248     6561803 :         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   115706814 : 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   115706814 :         struct xfs_da_args      *args;
     264   115706814 :         int                     rval;
     265   115706814 :         bool                    v;
     266             : 
     267   115706814 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     268             : 
     269   115706814 :         if (inum) {
     270   115384438 :                 rval = xfs_dir_ino_validate(tp->t_mountp, inum);
     271   115270144 :                 if (rval)
     272             :                         return rval;
     273   115270144 :                 XFS_STATS_INC(dp->i_mount, xs_dir_create);
     274             :         }
     275             : 
     276   115629698 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     277   115619468 :         if (!args)
     278             :                 return -ENOMEM;
     279             : 
     280   115619468 :         args->geo = dp->i_mount->m_dir_geo;
     281   115619468 :         args->name = name->name;
     282   115619468 :         args->namelen = name->len;
     283   115619468 :         args->filetype = name->type;
     284   115619468 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     285   115605324 :         args->inumber = inum;
     286   115605324 :         args->dp = dp;
     287   115605324 :         args->total = total;
     288   115605324 :         args->whichfork = XFS_DATA_FORK;
     289   115605324 :         args->trans = tp;
     290   115605324 :         args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
     291   115605324 :         if (!inum)
     292      311524 :                 args->op_flags |= XFS_DA_OP_JUSTCHECK;
     293             : 
     294   115605324 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     295    57710519 :                 rval = xfs_dir2_sf_addname(args);
     296    57725917 :                 goto out_free;
     297             :         }
     298             : 
     299    57894805 :         rval = xfs_dir2_isblock(args, &v);
     300    57949522 :         if (rval)
     301           0 :                 goto out_free;
     302    57949522 :         if (v) {
     303     4816106 :                 rval = xfs_dir2_block_addname(args);
     304     4820399 :                 goto out_free;
     305             :         }
     306             : 
     307    53133416 :         rval = xfs_dir2_isleaf(args, &v);
     308    53184627 :         if (rval)
     309           0 :                 goto out_free;
     310    53184627 :         if (v)
     311    14091194 :                 rval = xfs_dir2_leaf_addname(args);
     312             :         else
     313    39093433 :                 rval = xfs_dir2_node_addname(args);
     314             : 
     315   115725884 : out_free:
     316   115725884 :         kmem_free(args);
     317   115725884 :         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    13593472 : xfs_dir_cilookup_result(
     326             :         struct xfs_da_args *args,
     327             :         const unsigned char *name,
     328             :         int             len)
     329             : {
     330    13593472 :         if (args->cmpresult == XFS_CMP_DIFFERENT)
     331             :                 return -ENOENT;
     332    13593472 :         if (args->cmpresult != XFS_CMP_CASE ||
     333             :                                         !(args->op_flags & XFS_DA_OP_CILOOKUP))
     334             :                 return -EEXIST;
     335             : 
     336      484528 :         args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
     337      484528 :         if (!args->value)
     338             :                 return -ENOMEM;
     339             : 
     340      969056 :         memcpy(args->value, name, len);
     341      484528 :         args->valuelen = len;
     342      484528 :         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   170483816 : 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   170483816 :         struct xfs_da_args      *args;
     360   170483816 :         int                     rval;
     361   170483816 :         bool                    v;
     362   170483816 :         int                     lock_mode;
     363             : 
     364   170483816 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     365   170483816 :         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   170423196 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     376   170551948 :         args->geo = dp->i_mount->m_dir_geo;
     377   170551948 :         args->name = name->name;
     378   170551948 :         args->namelen = name->len;
     379   170551948 :         args->filetype = name->type;
     380   170551948 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     381   170310212 :         args->dp = dp;
     382   170310212 :         args->whichfork = XFS_DATA_FORK;
     383   170310212 :         args->trans = tp;
     384   170310212 :         args->op_flags = XFS_DA_OP_OKNOENT;
     385   170310212 :         if (ci_name)
     386     1077139 :                 args->op_flags |= XFS_DA_OP_CILOOKUP;
     387             : 
     388   170310212 :         lock_mode = xfs_ilock_data_map_shared(dp);
     389   170372623 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     390   101252725 :                 rval = xfs_dir2_sf_lookup(args);
     391   101291123 :                 goto out_check_rval;
     392             :         }
     393             : 
     394    69119898 :         rval = xfs_dir2_isblock(args, &v);
     395    69324436 :         if (rval)
     396           0 :                 goto out_free;
     397    69324436 :         if (v) {
     398     7888318 :                 rval = xfs_dir2_block_lookup(args);
     399     7904972 :                 goto out_check_rval;
     400             :         }
     401             : 
     402    61436118 :         rval = xfs_dir2_isleaf(args, &v);
     403    61644578 :         if (rval)
     404           0 :                 goto out_free;
     405    61644578 :         if (v)
     406    28299373 :                 rval = xfs_dir2_leaf_lookup(args);
     407             :         else
     408    33345205 :                 rval = xfs_dir2_node_lookup(args);
     409             : 
     410   170761565 : out_check_rval:
     411   170761565 :         if (rval == -EEXIST)
     412             :                 rval = 0;
     413   122930190 :         if (!rval) {
     414    47842887 :                 *inum = args->inumber;
     415    47842887 :                 if (ci_name) {
     416      684834 :                         ci_name->name = args->value;
     417      684834 :                         ci_name->len = args->valuelen;
     418             :                 }
     419             :         }
     420   170076731 : out_free:
     421   170761565 :         xfs_iunlock(dp, lock_mode);
     422   170399244 :         kmem_free(args);
     423   170619063 :         return rval;
     424             : }
     425             : 
     426             : /*
     427             :  * Remove an entry from a directory.
     428             :  */
     429             : int
     430    85330825 : 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    85330825 :         struct xfs_da_args      *args;
     438    85330825 :         int                     rval;
     439    85330825 :         bool                    v;
     440             : 
     441    85330825 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     442    85330825 :         XFS_STATS_INC(dp->i_mount, xs_dir_remove);
     443             : 
     444    85298603 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     445    85297223 :         if (!args)
     446             :                 return -ENOMEM;
     447             : 
     448    85297223 :         args->geo = dp->i_mount->m_dir_geo;
     449    85297223 :         args->name = name->name;
     450    85297223 :         args->namelen = name->len;
     451    85297223 :         args->filetype = name->type;
     452    85297223 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     453    85306119 :         args->inumber = ino;
     454    85306119 :         args->dp = dp;
     455    85306119 :         args->total = total;
     456    85306119 :         args->whichfork = XFS_DATA_FORK;
     457    85306119 :         args->trans = tp;
     458             : 
     459    85306119 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     460    34608364 :                 rval = xfs_dir2_sf_removename(args);
     461    34609597 :                 goto out_free;
     462             :         }
     463             : 
     464    50697755 :         rval = xfs_dir2_isblock(args, &v);
     465    50695063 :         if (rval)
     466           0 :                 goto out_free;
     467    50695063 :         if (v) {
     468     2337249 :                 rval = xfs_dir2_block_removename(args);
     469     2337888 :                 goto out_free;
     470             :         }
     471             : 
     472    48357814 :         rval = xfs_dir2_isleaf(args, &v);
     473    48397548 :         if (rval)
     474           0 :                 goto out_free;
     475    48397548 :         if (v)
     476    13137732 :                 rval = xfs_dir2_leaf_removename(args);
     477             :         else
     478    35259816 :                 rval = xfs_dir2_node_removename(args);
     479    85352889 : out_free:
     480    85352889 :         kmem_free(args);
     481    85352889 :         return rval;
     482             : }
     483             : 
     484             : /*
     485             :  * Replace the inode number of a directory entry.
     486             :  */
     487             : int
     488    47631976 : 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    47631976 :         struct xfs_da_args      *args;
     496    47631976 :         int                     rval;
     497    47631976 :         bool                    v;
     498             : 
     499    47631976 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     500             : 
     501    47631976 :         rval = xfs_dir_ino_validate(tp->t_mountp, inum);
     502    47631940 :         if (rval)
     503             :                 return rval;
     504             : 
     505    47631875 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     506    47631931 :         if (!args)
     507             :                 return -ENOMEM;
     508             : 
     509    47631931 :         args->geo = dp->i_mount->m_dir_geo;
     510    47631931 :         args->name = name->name;
     511    47631931 :         args->namelen = name->len;
     512    47631931 :         args->filetype = name->type;
     513    47631931 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     514    47631860 :         args->inumber = inum;
     515    47631860 :         args->dp = dp;
     516    47631860 :         args->total = total;
     517    47631860 :         args->whichfork = XFS_DATA_FORK;
     518    47631860 :         args->trans = tp;
     519             : 
     520    47631860 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     521    45921823 :                 rval = xfs_dir2_sf_replace(args);
     522    45922034 :                 goto out_free;
     523             :         }
     524             : 
     525     1710037 :         rval = xfs_dir2_isblock(args, &v);
     526     1710039 :         if (rval)
     527           0 :                 goto out_free;
     528     1710039 :         if (v) {
     529      403231 :                 rval = xfs_dir2_block_replace(args);
     530      403240 :                 goto out_free;
     531             :         }
     532             : 
     533     1306808 :         rval = xfs_dir2_isleaf(args, &v);
     534     1306819 :         if (rval)
     535           0 :                 goto out_free;
     536     1306819 :         if (v)
     537      617897 :                 rval = xfs_dir2_leaf_replace(args);
     538             :         else
     539      688922 :                 rval = xfs_dir2_node_replace(args);
     540    47632086 : out_free:
     541    47632086 :         kmem_free(args);
     542    47632086 :         return rval;
     543             : }
     544             : 
     545             : /*
     546             :  * See if this entry can be added to the directory without allocating space.
     547             :  */
     548             : int
     549      311534 : 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      311534 :         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      344676 : 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      344676 :         struct xfs_inode        *dp = args->dp;
     574      344676 :         struct xfs_mount        *mp = dp->i_mount;
     575      344676 :         xfs_fileoff_t           bno;    /* directory offset of new block */
     576      344676 :         int                     count;  /* count of filesystem blocks */
     577      344676 :         int                     error;
     578             : 
     579      344676 :         trace_xfs_dir2_grow_inode(args, space);
     580             : 
     581             :         /*
     582             :          * Set lowest possible block in the space requested.
     583             :          */
     584      344666 :         bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
     585      344666 :         count = args->geo->fsbcount;
     586             : 
     587      344666 :         error = xfs_da_grow_inode_int(args, &bno, count);
     588      344666 :         if (error)
     589             :                 return error;
     590             : 
     591      344656 :         *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      344634 :         if (space == XFS_DIR2_DATA_SPACE) {
     597      335351 :                 xfs_fsize_t     size;           /* directory file (data) size */
     598             : 
     599      335351 :                 size = XFS_FSB_TO_B(mp, bno + count);
     600      335351 :                 if (size > dp->i_disk_size) {
     601      334837 :                         dp->i_disk_size = size;
     602      334837 :                         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   325666242 : xfs_dir2_isblock(
     613             :         struct xfs_da_args      *args,
     614             :         bool                    *isblock)
     615             : {
     616   325666242 :         struct xfs_mount        *mp = args->dp->i_mount;
     617   325666242 :         xfs_fileoff_t           eof;
     618   325666242 :         int                     error;
     619             : 
     620   325666242 :         error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
     621   325291800 :         if (error)
     622             :                 return error;
     623             : 
     624   325291800 :         *isblock = false;
     625   325291800 :         if (XFS_FSB_TO_B(mp, eof) != args->geo->blksize)
     626             :                 return 0;
     627             : 
     628    22868923 :         *isblock = true;
     629    22868923 :         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   281090582 : xfs_dir2_isleaf(
     639             :         struct xfs_da_args      *args,
     640             :         bool                    *isleaf)
     641             : {
     642   281090582 :         xfs_fileoff_t           eof;
     643   281090582 :         int                     error;
     644             : 
     645   281090582 :         error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
     646   281922293 :         if (error)
     647             :                 return error;
     648             : 
     649   281922293 :         *isleaf = false;
     650   281922293 :         if (eof != args->geo->leafblk + args->geo->fsbcount)
     651             :                 return 0;
     652             : 
     653    62806952 :         *isleaf = true;
     654    62806952 :         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      243597 : xfs_dir2_shrink_inode(
     664             :         struct xfs_da_args      *args,
     665             :         xfs_dir2_db_t           db,
     666             :         struct xfs_buf          *bp)
     667             : {
     668      243597 :         xfs_fileoff_t           bno;            /* directory file offset */
     669      243597 :         xfs_dablk_t             da;             /* directory file offset */
     670      243597 :         int                     done;           /* bunmap is finished */
     671      243597 :         struct xfs_inode        *dp;
     672      243597 :         int                     error;
     673      243597 :         struct xfs_mount        *mp;
     674      243597 :         struct xfs_trans        *tp;
     675             : 
     676      243597 :         trace_xfs_dir2_shrink_inode(args, db);
     677             : 
     678      243595 :         dp = args->dp;
     679      243595 :         mp = dp->i_mount;
     680      243595 :         tp = args->trans;
     681      243595 :         da = xfs_dir2_db_to_da(args->geo, db);
     682             : 
     683             :         /* Unmap the fsblock(s). */
     684      243596 :         error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, &done);
     685      243593 :         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      243593 :         ASSERT(done);
     701             :         /*
     702             :          * Invalidate the buffer from the transaction.
     703             :          */
     704      243593 :         xfs_trans_binval(tp, bp);
     705             :         /*
     706             :          * If it's not a data block, we're done.
     707             :          */
     708      243598 :         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      236114 :         if (dp->i_disk_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
     714             :                 return 0;
     715      130696 :         bno = da;
     716      130696 :         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      130693 :         if (db == args->geo->datablk)
     723      118251 :                 ASSERT(bno == 0);
     724             :         else
     725       12442 :                 ASSERT(bno > 0);
     726             :         /*
     727             :          * Set the size to the new last block.
     728             :          */
     729      130693 :         dp->i_disk_size = XFS_FSB_TO_B(mp, bno);
     730      130693 :         xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
     731      130693 :         return 0;
     732             : }
     733             : 
     734             : /* Returns true if the directory entry name is valid. */
     735             : bool
     736 16676974216 : 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 16676974216 :         if (length >= MAXNAMELEN)
     745             :                 return false;
     746             : 
     747             :         /* There shouldn't be any slashes or nulls here */
     748 50151576711 :         return !memchr(name, '/', length) && !memchr(name, 0, length);
     749             : }
     750             : 
     751             : xfs_dahash_t
     752  2970519912 : xfs_dir2_hashname(
     753             :         struct xfs_mount        *mp,
     754             :         const struct xfs_name   *name)
     755             : {
     756  2970519912 :         if (unlikely(xfs_has_asciici(mp)))
     757     6775552 :                 return xfs_ascii_ci_hashname(name);
     758  2963744360 :         return xfs_da_hashname(name->name, name->len);
     759             : }
     760             : 
     761             : enum xfs_dacmp
     762  3995226051 : xfs_dir2_compname(
     763             :         struct xfs_da_args      *args,
     764             :         const unsigned char     *name,
     765             :         int                     len)
     766             : {
     767  3995226051 :         if (unlikely(xfs_has_asciici(args->dp->i_mount)))
     768  1906247819 :                 return xfs_ascii_ci_compname(args, name, len);
     769  2088978232 :         return xfs_da_compname(args, name, len);
     770             : }

Generated by: LCOV version 1.14