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-rc4-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 575 595 96.6 %
Date: 2023-07-31 20:08:27 Functions: 30 31 96.8 %

          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             : #include "xfs_bmap_btree.h"
      23             : #include "xfs_trans_space.h"
      24             : #include "xfs_parent.h"
      25             : #include "xfs_ag.h"
      26             : #include "xfs_ialloc.h"
      27             : 
      28             : const struct xfs_name xfs_name_dotdot = {
      29             :         .name   = (const unsigned char *)"..",
      30             :         .len    = 2,
      31             :         .type   = XFS_DIR3_FT_DIR,
      32             : };
      33             : 
      34             : const struct xfs_name xfs_name_dot = {
      35             :         .name   = (const unsigned char *)".",
      36             :         .len    = 1,
      37             :         .type   = XFS_DIR3_FT_DIR,
      38             : };
      39             : 
      40             : /*
      41             :  * Convert inode mode to directory entry filetype
      42             :  */
      43             : unsigned char
      44  1124148062 : xfs_mode_to_ftype(
      45             :         int             mode)
      46             : {
      47  1124148062 :         switch (mode & S_IFMT) {
      48             :         case S_IFREG:
      49             :                 return XFS_DIR3_FT_REG_FILE;
      50   127375594 :         case S_IFDIR:
      51   127375594 :                 return XFS_DIR3_FT_DIR;
      52   260091628 :         case S_IFCHR:
      53   260091628 :                 return XFS_DIR3_FT_CHRDEV;
      54          91 :         case S_IFBLK:
      55          91 :                 return XFS_DIR3_FT_BLKDEV;
      56        2080 :         case S_IFIFO:
      57        2080 :                 return XFS_DIR3_FT_FIFO;
      58          16 :         case S_IFSOCK:
      59          16 :                 return XFS_DIR3_FT_SOCK;
      60   475310747 :         case S_IFLNK:
      61   475310747 :                 return XFS_DIR3_FT_SYMLINK;
      62    22934670 :         default:
      63    22934670 :                 return XFS_DIR3_FT_UNKNOWN;
      64             :         }
      65             : }
      66             : 
      67             : /*
      68             :  * ASCII case-insensitive (ie. A-Z) support for directories that was
      69             :  * used in IRIX.
      70             :  */
      71             : xfs_dahash_t
      72     1682432 : xfs_ascii_ci_hashname(
      73             :         const struct xfs_name   *name)
      74             : {
      75     1682432 :         xfs_dahash_t            hash;
      76     1682432 :         int                     i;
      77             : 
      78    40375975 :         for (i = 0, hash = 0; i < name->len; i++)
      79    38693543 :                 hash = xfs_ascii_ci_xfrm(name->name[i]) ^ rol32(hash, 7);
      80             : 
      81     1682432 :         return hash;
      82             : }
      83             : 
      84             : enum xfs_dacmp
      85   345836347 : xfs_ascii_ci_compname(
      86             :         struct xfs_da_args      *args,
      87             :         const unsigned char     *name,
      88             :         int                     len)
      89             : {
      90   345836347 :         enum xfs_dacmp          result;
      91   345836347 :         int                     i;
      92             : 
      93   345836347 :         if (args->namelen != len)
      94             :                 return XFS_CMP_DIFFERENT;
      95             : 
      96             :         result = XFS_CMP_EXACT;
      97    18601479 :         for (i = 0; i < len; i++) {
      98    18459984 :                 if (args->name[i] == name[i])
      99     3860241 :                         continue;
     100    14599743 :                 if (xfs_ascii_ci_xfrm(args->name[i]) !=
     101    14599743 :                     xfs_ascii_ci_xfrm(name[i]))
     102             :                         return XFS_CMP_DIFFERENT;
     103             :                 result = XFS_CMP_CASE;
     104             :         }
     105             : 
     106             :         return result;
     107             : }
     108             : 
     109             : int
     110       24333 : xfs_da_mount(
     111             :         struct xfs_mount        *mp)
     112             : {
     113       24333 :         struct xfs_da_geometry  *dageo;
     114             : 
     115             : 
     116       24333 :         ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
     117       24333 :         ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE);
     118             : 
     119       24333 :         mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
     120             :                                     KM_MAYFAIL);
     121       24333 :         mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
     122             :                                      KM_MAYFAIL);
     123       24333 :         if (!mp->m_dir_geo || !mp->m_attr_geo) {
     124           0 :                 kmem_free(mp->m_dir_geo);
     125           0 :                 kmem_free(mp->m_attr_geo);
     126           0 :                 return -ENOMEM;
     127             :         }
     128             : 
     129             :         /* set up directory geometry */
     130       24333 :         dageo = mp->m_dir_geo;
     131       24333 :         dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
     132       24333 :         dageo->fsblog = mp->m_sb.sb_blocklog;
     133       24333 :         dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb);
     134       24333 :         dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
     135       24333 :         if (xfs_has_crc(mp)) {
     136       24291 :                 dageo->node_hdr_size = sizeof(struct xfs_da3_node_hdr);
     137       24291 :                 dageo->leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr);
     138       24291 :                 dageo->free_hdr_size = sizeof(struct xfs_dir3_free_hdr);
     139       24291 :                 dageo->data_entry_offset =
     140             :                                 sizeof(struct xfs_dir3_data_hdr);
     141             :         } else {
     142          42 :                 dageo->node_hdr_size = sizeof(struct xfs_da_node_hdr);
     143          42 :                 dageo->leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr);
     144          42 :                 dageo->free_hdr_size = sizeof(struct xfs_dir2_free_hdr);
     145          42 :                 dageo->data_entry_offset =
     146             :                                 sizeof(struct xfs_dir2_data_hdr);
     147             :         }
     148       24333 :         dageo->leaf_max_ents = (dageo->blksize - dageo->leaf_hdr_size) /
     149             :                         sizeof(struct xfs_dir2_leaf_entry);
     150       24333 :         dageo->free_max_bests = (dageo->blksize - dageo->free_hdr_size) /
     151             :                         sizeof(xfs_dir2_data_off_t);
     152             : 
     153       24333 :         dageo->data_first_offset = dageo->data_entry_offset +
     154       24333 :                         xfs_dir2_data_entsize(mp, 1) +
     155             :                         xfs_dir2_data_entsize(mp, 2);
     156             : 
     157             :         /*
     158             :          * Now we've set up the block conversion variables, we can calculate the
     159             :          * segment block constants using the geometry structure.
     160             :          */
     161       24333 :         dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
     162       24333 :         dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
     163       24333 :         dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
     164       24333 :         dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
     165             :                                 (uint)sizeof(xfs_da_node_entry_t);
     166       24333 :         dageo->max_extents = (XFS_DIR2_MAX_SPACES * XFS_DIR2_SPACE_SIZE) >>
     167       24333 :                                         mp->m_sb.sb_blocklog;
     168       24333 :         dageo->magicpct = (dageo->blksize * 37) / 100;
     169             : 
     170             :         /* set up attribute geometry - single fsb only */
     171       24333 :         dageo = mp->m_attr_geo;
     172       24333 :         dageo->blklog = mp->m_sb.sb_blocklog;
     173       24333 :         dageo->fsblog = mp->m_sb.sb_blocklog;
     174       24333 :         dageo->blksize = 1 << dageo->blklog;
     175       24333 :         dageo->fsbcount = 1;
     176       24333 :         dageo->node_hdr_size = mp->m_dir_geo->node_hdr_size;
     177       24333 :         dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
     178             :                                 (uint)sizeof(xfs_da_node_entry_t);
     179             : 
     180       24333 :         if (xfs_has_large_extent_counts(mp))
     181       24289 :                 dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_LARGE;
     182             :         else
     183          44 :                 dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_SMALL;
     184             : 
     185       24333 :         dageo->magicpct = (dageo->blksize * 37) / 100;
     186       24333 :         return 0;
     187             : }
     188             : 
     189             : void
     190       24339 : xfs_da_unmount(
     191             :         struct xfs_mount        *mp)
     192             : {
     193       24339 :         kmem_free(mp->m_dir_geo);
     194       24339 :         kmem_free(mp->m_attr_geo);
     195       24339 : }
     196             : 
     197             : /*
     198             :  * Return 1 if directory contains only "." and "..".
     199             :  */
     200             : int
     201     1221771 : xfs_dir_isempty(
     202             :         xfs_inode_t     *dp)
     203             : {
     204     1221771 :         xfs_dir2_sf_hdr_t       *sfp;
     205             : 
     206     1221771 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     207     1221771 :         if (dp->i_disk_size == 0)    /* might happen during shutdown. */
     208             :                 return 1;
     209     1221771 :         if (dp->i_disk_size > xfs_inode_data_fork_size(dp))
     210             :                 return 0;
     211     1219894 :         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
     212     1219894 :         return !sfp->count;
     213             : }
     214             : 
     215             : /*
     216             :  * Validate a given inode number.
     217             :  */
     218             : int
     219   909868288 : xfs_dir_ino_validate(
     220             :         xfs_mount_t     *mp,
     221             :         xfs_ino_t       ino)
     222             : {
     223   909868288 :         bool            ino_ok = xfs_verify_dir_ino(mp, ino);
     224             : 
     225  1819752404 :         if (XFS_IS_CORRUPT(mp, !ino_ok) ||
     226   909863967 :             XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DIR_INO_VALIDATE)) {
     227           2 :                 xfs_warn(mp, "Invalid inode number 0x%Lx",
     228             :                                 (unsigned long long) ino);
     229           2 :                 return -EFSCORRUPTED;
     230             :         }
     231             :         return 0;
     232             : }
     233             : 
     234             : /*
     235             :  * Initialize a directory with its "." and ".." entries.
     236             :  */
     237             : int
     238     6855677 : xfs_dir_init(
     239             :         xfs_trans_t     *tp,
     240             :         xfs_inode_t     *dp,
     241             :         xfs_inode_t     *pdp)
     242             : {
     243     6855677 :         struct xfs_da_args *args;
     244     6855677 :         int             error;
     245             : 
     246     6855677 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     247     6855677 :         error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
     248     6855682 :         if (error)
     249             :                 return error;
     250             : 
     251     6855704 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     252     6855665 :         if (!args)
     253             :                 return -ENOMEM;
     254             : 
     255     6855665 :         args->geo = dp->i_mount->m_dir_geo;
     256     6855665 :         args->dp = dp;
     257     6855665 :         args->trans = tp;
     258     6855665 :         args->owner = dp->i_ino;
     259     6855665 :         error = xfs_dir2_sf_create(args, pdp->i_ino);
     260     6855627 :         kmem_free(args);
     261     6855627 :         return error;
     262             : }
     263             : 
     264             : /*
     265             :  * Enter a name in a directory, or check for available space.
     266             :  * If inum is 0, only the available space test is performed.
     267             :  */
     268             : int
     269    89047124 : xfs_dir_createname(
     270             :         struct xfs_trans        *tp,
     271             :         struct xfs_inode        *dp,
     272             :         const struct xfs_name   *name,
     273             :         xfs_ino_t               inum,           /* new entry inode number */
     274             :         xfs_extlen_t            total)          /* bmap's total block count */
     275             : {
     276    89047124 :         struct xfs_da_args      *args;
     277    89047124 :         int                     rval;
     278    89047124 :         bool                    v;
     279             : 
     280    89047124 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     281             : 
     282    89047124 :         if (inum) {
     283    89047533 :                 rval = xfs_dir_ino_validate(tp->t_mountp, inum);
     284    89046827 :                 if (rval)
     285             :                         return rval;
     286    89046827 :                 XFS_STATS_INC(dp->i_mount, xs_dir_create);
     287             :         }
     288             : 
     289    89046418 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     290    89049580 :         if (!args)
     291             :                 return -ENOMEM;
     292             : 
     293    89049580 :         args->geo = dp->i_mount->m_dir_geo;
     294    89049580 :         args->name = name->name;
     295    89049580 :         args->namelen = name->len;
     296    89049580 :         args->filetype = name->type;
     297    89049580 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     298    89048598 :         args->inumber = inum;
     299    89048598 :         args->dp = dp;
     300    89048598 :         args->total = total;
     301    89048598 :         args->whichfork = XFS_DATA_FORK;
     302    89048598 :         args->trans = tp;
     303    89048598 :         args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
     304    89048598 :         args->owner = dp->i_ino;
     305    89048598 :         if (!inum)
     306           0 :                 args->op_flags |= XFS_DA_OP_JUSTCHECK;
     307             : 
     308    89048598 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     309    50743325 :                 rval = xfs_dir2_sf_addname(args);
     310    50744832 :                 goto out_free;
     311             :         }
     312             : 
     313    38305273 :         rval = xfs_dir2_isblock(args, &v);
     314    38305787 :         if (rval)
     315           0 :                 goto out_free;
     316    38305787 :         if (v) {
     317     2410701 :                 rval = xfs_dir2_block_addname(args);
     318     2410742 :                 goto out_free;
     319             :         }
     320             : 
     321    35895086 :         rval = xfs_dir2_isleaf(args, &v);
     322    35894198 :         if (rval)
     323           0 :                 goto out_free;
     324    35894198 :         if (v)
     325     3900267 :                 rval = xfs_dir2_leaf_addname(args);
     326             :         else
     327    31993931 :                 rval = xfs_dir2_node_addname(args);
     328             : 
     329    89050113 : out_free:
     330    89050113 :         kmem_free(args);
     331    89050113 :         return rval;
     332             : }
     333             : 
     334             : /*
     335             :  * If doing a CI lookup and case-insensitive match, dup actual name into
     336             :  * args.value. Return EEXIST for success (ie. name found) or an error.
     337             :  */
     338             : int
     339    30940764 : xfs_dir_cilookup_result(
     340             :         struct xfs_da_args *args,
     341             :         const unsigned char *name,
     342             :         int             len)
     343             : {
     344    30940764 :         if (args->cmpresult == XFS_CMP_DIFFERENT)
     345             :                 return -ENOENT;
     346    30940764 :         if (args->cmpresult != XFS_CMP_CASE ||
     347             :                                         !(args->op_flags & XFS_DA_OP_CILOOKUP))
     348             :                 return -EEXIST;
     349             : 
     350       88096 :         args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
     351       88096 :         if (!args->value)
     352             :                 return -ENOMEM;
     353             : 
     354      176192 :         memcpy(args->value, name, len);
     355       88096 :         args->valuelen = len;
     356       88096 :         return -EEXIST;
     357             : }
     358             : 
     359             : /*
     360             :  * Lookup a name in a directory, give back the inode number.
     361             :  * If ci_name is not NULL, returns the actual name in ci_name if it differs
     362             :  * to name, or ci_name->name is set to NULL for an exact match.
     363             :  */
     364             : 
     365             : int
     366   229924524 : xfs_dir_lookup(
     367             :         struct xfs_trans        *tp,
     368             :         struct xfs_inode        *dp,
     369             :         const struct xfs_name   *name,
     370             :         xfs_ino_t               *inum,    /* out: inode number */
     371             :         struct xfs_name         *ci_name) /* out: actual name if CI match */
     372             : {
     373   229924524 :         struct xfs_da_args      *args;
     374   229924524 :         int                     rval;
     375   229924524 :         bool                    v;
     376   229924524 :         int                     lock_mode;
     377             : 
     378   229924524 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     379   229924524 :         XFS_STATS_INC(dp->i_mount, xs_dir_lookup);
     380             : 
     381             :         /*
     382             :          * We need to use KM_NOFS here so that lockdep will not throw false
     383             :          * positive deadlock warnings on a non-transactional lookup path. It is
     384             :          * safe to recurse into inode recalim in that case, but lockdep can't
     385             :          * easily be taught about it. Hence KM_NOFS avoids having to add more
     386             :          * lockdep Doing this avoids having to add a bunch of lockdep class
     387             :          * annotations into the reclaim path for the ilock.
     388             :          */
     389   229924524 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     390   229927037 :         args->geo = dp->i_mount->m_dir_geo;
     391   229927037 :         args->name = name->name;
     392   229927037 :         args->namelen = name->len;
     393   229927037 :         args->filetype = name->type;
     394   229927037 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     395   229927297 :         args->dp = dp;
     396   229927297 :         args->whichfork = XFS_DATA_FORK;
     397   229927297 :         args->trans = tp;
     398   229927297 :         args->op_flags = XFS_DA_OP_OKNOENT;
     399   229927297 :         args->owner = dp->i_ino;
     400   229927297 :         if (ci_name)
     401      195894 :                 args->op_flags |= XFS_DA_OP_CILOOKUP;
     402             : 
     403   229927297 :         lock_mode = xfs_ilock_data_map_shared(dp);
     404   229930591 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     405   180185572 :                 rval = xfs_dir2_sf_lookup(args);
     406   180184761 :                 goto out_check_rval;
     407             :         }
     408             : 
     409    49745019 :         rval = xfs_dir2_isblock(args, &v);
     410    49746001 :         if (rval)
     411           0 :                 goto out_free;
     412    49746001 :         if (v) {
     413    26377412 :                 rval = xfs_dir2_block_lookup(args);
     414    26377509 :                 goto out_check_rval;
     415             :         }
     416             : 
     417    23368589 :         rval = xfs_dir2_isleaf(args, &v);
     418    23369771 :         if (rval)
     419           0 :                 goto out_free;
     420    23369771 :         if (v)
     421     8767879 :                 rval = xfs_dir2_leaf_lookup(args);
     422             :         else
     423    14601892 :                 rval = xfs_dir2_node_lookup(args);
     424             : 
     425   229932674 : out_check_rval:
     426   229932674 :         if (rval == -EEXIST)
     427             :                 rval = 0;
     428    80747379 :         if (!rval) {
     429   149183919 :                 *inum = args->inumber;
     430   149183919 :                 if (ci_name) {
     431      107531 :                         ci_name->name = args->value;
     432      107531 :                         ci_name->len = args->valuelen;
     433             :                 }
     434             :         }
     435   229825143 : out_free:
     436   229932674 :         xfs_iunlock(dp, lock_mode);
     437   229930473 :         kmem_free(args);
     438   229930621 :         return rval;
     439             : }
     440             : 
     441             : /*
     442             :  * Remove an entry from a directory.
     443             :  */
     444             : int
     445    59272810 : xfs_dir_removename(
     446             :         struct xfs_trans        *tp,
     447             :         struct xfs_inode        *dp,
     448             :         const struct xfs_name   *name,
     449             :         xfs_ino_t               ino,
     450             :         xfs_extlen_t            total)          /* bmap's total block count */
     451             : {
     452    59272810 :         struct xfs_da_args      *args;
     453    59272810 :         int                     rval;
     454    59272810 :         bool                    v;
     455             : 
     456    59272810 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     457    59272810 :         XFS_STATS_INC(dp->i_mount, xs_dir_remove);
     458             : 
     459    59272810 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     460    59274061 :         if (!args)
     461             :                 return -ENOMEM;
     462             : 
     463    59274061 :         args->geo = dp->i_mount->m_dir_geo;
     464    59274061 :         args->name = name->name;
     465    59274061 :         args->namelen = name->len;
     466    59274061 :         args->filetype = name->type;
     467    59274061 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     468    59273936 :         args->inumber = ino;
     469    59273936 :         args->dp = dp;
     470    59273936 :         args->total = total;
     471    59273936 :         args->whichfork = XFS_DATA_FORK;
     472    59273936 :         args->trans = tp;
     473    59273936 :         args->owner = dp->i_ino;
     474             : 
     475    59273936 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     476    24921847 :                 rval = xfs_dir2_sf_removename(args);
     477    24922008 :                 goto out_free;
     478             :         }
     479             : 
     480    34352089 :         rval = xfs_dir2_isblock(args, &v);
     481    34352269 :         if (rval)
     482           0 :                 goto out_free;
     483    34352269 :         if (v) {
     484     1837593 :                 rval = xfs_dir2_block_removename(args);
     485     1837592 :                 goto out_free;
     486             :         }
     487             : 
     488    32514676 :         rval = xfs_dir2_isleaf(args, &v);
     489    32514968 :         if (rval)
     490           0 :                 goto out_free;
     491    32514968 :         if (v)
     492     3804002 :                 rval = xfs_dir2_leaf_removename(args);
     493             :         else
     494    28710966 :                 rval = xfs_dir2_node_removename(args);
     495    59273487 : out_free:
     496    59273487 :         kmem_free(args);
     497    59273487 :         return rval;
     498             : }
     499             : 
     500             : /*
     501             :  * Replace the inode number of a directory entry.
     502             :  */
     503             : int
     504    33018990 : xfs_dir_replace(
     505             :         struct xfs_trans        *tp,
     506             :         struct xfs_inode        *dp,
     507             :         const struct xfs_name   *name,          /* name of entry to replace */
     508             :         xfs_ino_t               inum,           /* new inode number */
     509             :         xfs_extlen_t            total)          /* bmap's total block count */
     510             : {
     511    33018990 :         struct xfs_da_args      *args;
     512    33018990 :         int                     rval;
     513    33018990 :         bool                    v;
     514             : 
     515    33018990 :         ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
     516             : 
     517    33018990 :         rval = xfs_dir_ino_validate(tp->t_mountp, inum);
     518    33018979 :         if (rval)
     519             :                 return rval;
     520             : 
     521    33018979 :         args = kmem_zalloc(sizeof(*args), KM_NOFS);
     522    33018978 :         if (!args)
     523             :                 return -ENOMEM;
     524             : 
     525    33018978 :         args->geo = dp->i_mount->m_dir_geo;
     526    33018978 :         args->name = name->name;
     527    33018978 :         args->namelen = name->len;
     528    33018978 :         args->filetype = name->type;
     529    33018978 :         args->hashval = xfs_dir2_hashname(dp->i_mount, name);
     530    33018969 :         args->inumber = inum;
     531    33018969 :         args->dp = dp;
     532    33018969 :         args->total = total;
     533    33018969 :         args->whichfork = XFS_DATA_FORK;
     534    33018969 :         args->trans = tp;
     535    33018969 :         args->owner = dp->i_ino;
     536             : 
     537    33018969 :         if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     538    31161108 :                 rval = xfs_dir2_sf_replace(args);
     539    31161110 :                 goto out_free;
     540             :         }
     541             : 
     542     1857861 :         rval = xfs_dir2_isblock(args, &v);
     543     1857860 :         if (rval)
     544           0 :                 goto out_free;
     545     1857860 :         if (v) {
     546     1150061 :                 rval = xfs_dir2_block_replace(args);
     547     1150062 :                 goto out_free;
     548             :         }
     549             : 
     550      707799 :         rval = xfs_dir2_isleaf(args, &v);
     551      707799 :         if (rval)
     552           0 :                 goto out_free;
     553      707799 :         if (v)
     554      200877 :                 rval = xfs_dir2_leaf_replace(args);
     555             :         else
     556      506922 :                 rval = xfs_dir2_node_replace(args);
     557    33018970 : out_free:
     558    33018970 :         kmem_free(args);
     559    33018970 :         return rval;
     560             : }
     561             : 
     562             : /*
     563             :  * See if this entry can be added to the directory without allocating space.
     564             :  */
     565             : int
     566           0 : xfs_dir_canenter(
     567             :         struct xfs_trans        *tp,
     568             :         struct xfs_inode        *dp,
     569             :         const struct xfs_name   *name)          /* name of entry to add */
     570             : {
     571           0 :         return xfs_dir_createname(tp, dp, name, 0, 0);
     572             : }
     573             : 
     574             : /*
     575             :  * Utility routines.
     576             :  */
     577             : 
     578             : /*
     579             :  * Add a block to the directory.
     580             :  *
     581             :  * This routine is for data and free blocks, not leaf/node blocks which are
     582             :  * handled by xfs_da_grow_inode.
     583             :  */
     584             : int
     585      447721 : xfs_dir2_grow_inode(
     586             :         struct xfs_da_args      *args,
     587             :         int                     space,  /* v2 dir's space XFS_DIR2_xxx_SPACE */
     588             :         xfs_dir2_db_t           *dbp)   /* out: block number added */
     589             : {
     590      447721 :         struct xfs_inode        *dp = args->dp;
     591      447721 :         struct xfs_mount        *mp = dp->i_mount;
     592      447721 :         xfs_fileoff_t           bno;    /* directory offset of new block */
     593      447721 :         int                     count;  /* count of filesystem blocks */
     594      447721 :         int                     error;
     595             : 
     596      447721 :         trace_xfs_dir2_grow_inode(args, space);
     597             : 
     598             :         /*
     599             :          * Set lowest possible block in the space requested.
     600             :          */
     601      447721 :         bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
     602      447721 :         count = args->geo->fsbcount;
     603             : 
     604      447721 :         error = xfs_da_grow_inode_int(args, &bno, count);
     605      447721 :         if (error)
     606             :                 return error;
     607             : 
     608      447721 :         *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno);
     609             : 
     610             :         /*
     611             :          * Update file's size if this is the data space and it grew.
     612             :          */
     613      447721 :         if (space == XFS_DIR2_DATA_SPACE) {
     614      445996 :                 xfs_fsize_t     size;           /* directory file (data) size */
     615             : 
     616      445996 :                 size = XFS_FSB_TO_B(mp, bno + count);
     617      445996 :                 if (size > dp->i_disk_size) {
     618      443598 :                         dp->i_disk_size = size;
     619      443598 :                         xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
     620             :                 }
     621             :         }
     622             :         return 0;
     623             : }
     624             : 
     625             : /*
     626             :  * See if the directory is a single-block form directory.
     627             :  */
     628             : int
     629   225031329 : xfs_dir2_isblock(
     630             :         struct xfs_da_args      *args,
     631             :         bool                    *isblock)
     632             : {
     633   225031329 :         struct xfs_mount        *mp = args->dp->i_mount;
     634   225031329 :         xfs_fileoff_t           eof;
     635   225031329 :         int                     error;
     636             : 
     637   225031329 :         error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
     638   225059714 :         if (error)
     639             :                 return error;
     640             : 
     641   225059714 :         *isblock = false;
     642   225059714 :         if (XFS_FSB_TO_B(mp, eof) != args->geo->blksize)
     643             :                 return 0;
     644             : 
     645    54365693 :         *isblock = true;
     646    54365693 :         if (XFS_IS_CORRUPT(mp, args->dp->i_disk_size != args->geo->blksize)) {
     647           0 :                 xfs_da_mark_sick(args);
     648           0 :                 return -EFSCORRUPTED;
     649             :         }
     650             :         return 0;
     651             : }
     652             : 
     653             : /*
     654             :  * See if the directory is a single-leaf form directory.
     655             :  */
     656             : int
     657   152736423 : xfs_dir2_isleaf(
     658             :         struct xfs_da_args      *args,
     659             :         bool                    *isleaf)
     660             : {
     661   152736423 :         xfs_fileoff_t           eof;
     662   152736423 :         int                     error;
     663             : 
     664   152736423 :         error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
     665   152721108 :         if (error)
     666             :                 return error;
     667             : 
     668   152721108 :         *isleaf = false;
     669   152721108 :         if (eof != args->geo->leafblk + args->geo->fsbcount)
     670             :                 return 0;
     671             : 
     672    18101393 :         *isleaf = true;
     673    18101393 :         return 0;
     674             : }
     675             : 
     676             : /*
     677             :  * Remove the given block from the directory.
     678             :  * This routine is used for data and free blocks, leaf/node are done
     679             :  * by xfs_da_shrink_inode.
     680             :  */
     681             : int
     682      297129 : xfs_dir2_shrink_inode(
     683             :         struct xfs_da_args      *args,
     684             :         xfs_dir2_db_t           db,
     685             :         struct xfs_buf          *bp)
     686             : {
     687      297129 :         xfs_fileoff_t           bno;            /* directory file offset */
     688      297129 :         xfs_dablk_t             da;             /* directory file offset */
     689      297129 :         int                     done;           /* bunmap is finished */
     690      297129 :         struct xfs_inode        *dp;
     691      297129 :         int                     error;
     692      297129 :         struct xfs_mount        *mp;
     693      297129 :         struct xfs_trans        *tp;
     694             : 
     695      297129 :         trace_xfs_dir2_shrink_inode(args, db);
     696             : 
     697      297129 :         dp = args->dp;
     698      297129 :         mp = dp->i_mount;
     699      297129 :         tp = args->trans;
     700      297129 :         da = xfs_dir2_db_to_da(args->geo, db);
     701             : 
     702             :         /* Unmap the fsblock(s). */
     703      297129 :         error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, &done);
     704      297129 :         if (error) {
     705             :                 /*
     706             :                  * ENOSPC actually can happen if we're in a removename with no
     707             :                  * space reservation, and the resulting block removal would
     708             :                  * cause a bmap btree split or conversion from extents to btree.
     709             :                  * This can only happen for un-fragmented directory blocks,
     710             :                  * since you need to be punching out the middle of an extent.
     711             :                  * In this case we need to leave the block in the file, and not
     712             :                  * binval it.  So the block has to be in a consistent empty
     713             :                  * state and appropriately logged.  We don't free up the buffer,
     714             :                  * the caller can tell it hasn't happened since it got an error
     715             :                  * back.
     716             :                  */
     717             :                 return error;
     718             :         }
     719      297129 :         ASSERT(done);
     720             :         /*
     721             :          * Invalidate the buffer from the transaction.
     722             :          */
     723      297129 :         xfs_trans_binval(tp, bp);
     724             :         /*
     725             :          * If it's not a data block, we're done.
     726             :          */
     727      297129 :         if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET))
     728             :                 return 0;
     729             :         /*
     730             :          * If the block isn't the last one in the directory, we're done.
     731             :          */
     732      295911 :         if (dp->i_disk_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
     733             :                 return 0;
     734      275043 :         bno = da;
     735      275043 :         if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
     736             :                 /*
     737             :                  * This can't really happen unless there's kernel corruption.
     738             :                  */
     739             :                 return error;
     740             :         }
     741      275043 :         if (db == args->geo->datablk)
     742      272764 :                 ASSERT(bno == 0);
     743             :         else
     744        2279 :                 ASSERT(bno > 0);
     745             :         /*
     746             :          * Set the size to the new last block.
     747             :          */
     748      275043 :         dp->i_disk_size = XFS_FSB_TO_B(mp, bno);
     749      275043 :         xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
     750      275043 :         return 0;
     751             : }
     752             : 
     753             : /* Returns true if the directory entry name is valid. */
     754             : bool
     755 24617645166 : xfs_dir2_namecheck(
     756             :         const void      *name,
     757             :         size_t          length)
     758             : {
     759             :         /*
     760             :          * MAXNAMELEN includes the trailing null, but (name/length) leave it
     761             :          * out, so use >= for the length check.
     762             :          */
     763 24617645166 :         if (length >= MAXNAMELEN)
     764             :                 return false;
     765             : 
     766             :         /* There shouldn't be any slashes or nulls here */
     767 73830740975 :         return !memchr(name, '/', length) && !memchr(name, 0, length);
     768             : }
     769             : 
     770             : xfs_dahash_t
     771  2789448320 : xfs_dir2_hashname(
     772             :         struct xfs_mount        *mp,
     773             :         const struct xfs_name   *name)
     774             : {
     775  2789448320 :         if (unlikely(xfs_has_asciici(mp)))
     776     1681232 :                 return xfs_ascii_ci_hashname(name);
     777  2787767088 :         return xfs_da_hashname(name->name, name->len);
     778             : }
     779             : 
     780             : enum xfs_dacmp
     781  1716395152 : xfs_dir2_compname(
     782             :         struct xfs_da_args      *args,
     783             :         const unsigned char     *name,
     784             :         int                     len)
     785             : {
     786  1716395152 :         if (unlikely(xfs_has_asciici(args->dp->i_mount)))
     787   345836347 :                 return xfs_ascii_ci_compname(args, name, len);
     788  1370558805 :         return xfs_da_compname(args, name, len);
     789             : }
     790             : 
     791             : #ifdef CONFIG_XFS_LIVE_HOOKS
     792             : /*
     793             :  * Use a static key here to reduce the overhead of directory live update hooks.
     794             :  * If the compiler supports jump labels, the static branch will be replaced by
     795             :  * a nop sled when there are no hook users.  Online fsck is currently the only
     796             :  * caller, so this is a reasonable tradeoff.
     797             :  *
     798             :  * Note: Patching the kernel code requires taking the cpu hotplug lock.  Other
     799             :  * parts of the kernel allocate memory with that lock held, which means that
     800             :  * XFS callers cannot hold any locks that might be used by memory reclaim or
     801             :  * writeback when calling the static_branch_{inc,dec} functions.
     802             :  */
     803             : DEFINE_STATIC_XFS_HOOK_SWITCH(xfs_dir_hooks_switch);
     804             : 
     805             : void
     806    11957378 : xfs_dir_hook_disable(void)
     807             : {
     808    11957378 :         xfs_hooks_switch_off(&xfs_dir_hooks_switch);
     809    11958221 : }
     810             : 
     811             : void
     812    11957949 : xfs_dir_hook_enable(void)
     813             : {
     814    11957949 :         xfs_hooks_switch_on(&xfs_dir_hooks_switch);
     815    11957290 : }
     816             : 
     817             : /* Call hooks for a directory update relating to a child dirent update. */
     818             : inline void
     819   188025234 : xfs_dir_update_hook(
     820             :         struct xfs_inode                *dp,
     821             :         struct xfs_inode                *ip,
     822             :         int                             delta,
     823             :         const struct xfs_name           *name)
     824             : {
     825   255557041 :         if (xfs_hooks_switched_on(&xfs_dir_hooks_switch)) {
     826    67532221 :                 struct xfs_dir_update_params    p = {
     827             :                         .dp             = dp,
     828             :                         .ip             = ip,
     829             :                         .delta          = delta,
     830             :                         .name           = name,
     831             :                 };
     832    67532221 :                 struct xfs_mount        *mp = ip->i_mount;
     833             : 
     834    67532221 :                 xfs_hooks_call(&mp->m_dir_update_hooks, 0, &p);
     835             :         }
     836   188026675 : }
     837             : 
     838             : /* Call the specified function during a directory update. */
     839             : int
     840    11805640 : xfs_dir_hook_add(
     841             :         struct xfs_mount        *mp,
     842             :         struct xfs_dir_hook     *hook)
     843             : {
     844    11805640 :         return xfs_hooks_add(&mp->m_dir_update_hooks, &hook->dirent_hook);
     845             : }
     846             : 
     847             : /* Stop calling the specified function during a directory update. */
     848             : void
     849    11810796 : xfs_dir_hook_del(
     850             :         struct xfs_mount        *mp,
     851             :         struct xfs_dir_hook     *hook)
     852             : {
     853    11810796 :         xfs_hooks_del(&mp->m_dir_update_hooks, &hook->dirent_hook);
     854    11811473 : }
     855             : #endif /* CONFIG_XFS_LIVE_HOOKS */
     856             : 
     857             : /*
     858             :  * Given a directory @dp, a newly allocated inode @ip, and a @name, link @ip
     859             :  * into @dp under the given @name.  If @ip is a directory, it will be
     860             :  * initialized.  Both inodes must have the ILOCK held and the transaction must
     861             :  * have sufficient blocks reserved.
     862             :  */
     863             : int
     864    60407489 : xfs_dir_create_child(
     865             :         struct xfs_trans        *tp,
     866             :         unsigned int            resblks,
     867             :         struct xfs_dir_update   *du)
     868             : {
     869    60407489 :         struct xfs_inode        *dp = du->dp;
     870    60407489 :         const struct xfs_name   *name = du->name;
     871    60407489 :         struct xfs_inode        *ip = du->ip;
     872    60407489 :         struct xfs_parent_defer *parent = du->parent;
     873    60407489 :         int                     error;
     874             : 
     875    60407489 :         ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
     876    60409439 :         ASSERT(xfs_isilocked(dp, XFS_ILOCK_EXCL));
     877             : 
     878    60407863 :         error = xfs_dir_createname(tp, dp, name, ip->i_ino, resblks);
     879    60409011 :         if (error) {
     880         371 :                 ASSERT(error != -ENOSPC);
     881         371 :                 return error;
     882             :         }
     883             : 
     884    60408640 :         xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
     885    60409154 :         xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
     886             : 
     887    60410462 :         if (S_ISDIR(VFS_I(ip)->i_mode)) {
     888     6830600 :                 error = xfs_dir_init(tp, ip, dp);
     889     6830559 :                 if (error)
     890             :                         return error;
     891             : 
     892     6830554 :                 xfs_bumplink(tp, dp);
     893             :         }
     894             : 
     895             :         /*
     896             :          * If we have parent pointers, we need to add the attribute containing
     897             :          * the parent information now.
     898             :          */
     899    60410418 :         if (parent) {
     900    60254892 :                 error = xfs_parent_add(tp, parent, dp, name, ip);
     901    60253657 :                 if (error)
     902             :                         return error;
     903             :         }
     904             : 
     905    60409183 :         xfs_dir_update_hook(dp, ip, 1, name);
     906    60409183 :         return 0;
     907             : }
     908             : 
     909             : /*
     910             :  * Given a directory @dp, an existing non-directory inode @ip, and a @name,
     911             :  * link @ip into @dp under the given @name.  Both inodes must have the ILOCK
     912             :  * held.
     913             :  */
     914             : int
     915     6175065 : xfs_dir_add_child(
     916             :         struct xfs_trans        *tp,
     917             :         unsigned int            resblks,
     918             :         struct xfs_dir_update   *du)
     919             : {
     920     6175065 :         struct xfs_inode        *dp = du->dp;
     921     6175065 :         const struct xfs_name   *name = du->name;
     922     6175065 :         struct xfs_inode        *ip = du->ip;
     923     6175065 :         struct xfs_parent_defer *parent = du->parent;
     924     6175065 :         struct xfs_mount        *mp = tp->t_mountp;
     925     6175065 :         int                     error;
     926             : 
     927     6175065 :         ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
     928     6175068 :         ASSERT(xfs_isilocked(dp, XFS_ILOCK_EXCL));
     929     6175044 :         ASSERT(!S_ISDIR(VFS_I(ip)->i_mode));
     930             : 
     931     6175044 :         if (!resblks) {
     932           0 :                 error = xfs_dir_canenter(tp, dp, name);
     933           0 :                 if (error)
     934             :                         return error;
     935             :         }
     936             : 
     937             :         /*
     938             :          * Handle initial link state of O_TMPFILE inode
     939             :          */
     940     6175044 :         if (VFS_I(ip)->i_nlink == 0) {
     941        8290 :                 struct xfs_perag        *pag;
     942             : 
     943        8290 :                 pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
     944        8290 :                 error = xfs_iunlink_remove(tp, pag, ip);
     945        8290 :                 xfs_perag_put(pag);
     946        8290 :                 if (error)
     947             :                         return error;
     948             :         }
     949             : 
     950     6175044 :         error = xfs_dir_createname(tp, dp, name, ip->i_ino, resblks);
     951     6175064 :         if (error)
     952             :                 return error;
     953             : 
     954     6175093 :         xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
     955     6175038 :         xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
     956             : 
     957     6175056 :         xfs_bumplink(tp, ip);
     958             : 
     959             :         /*
     960             :          * If we have parent pointers, we now need to add the parent record to
     961             :          * the attribute fork of the inode. If this is the initial parent
     962             :          * attribute, we need to create it correctly, otherwise we can just add
     963             :          * the parent to the inode.
     964             :          */
     965     6175084 :         if (parent) {
     966     6142809 :                 error = xfs_parent_add(tp, parent, dp, name, ip);
     967     6142795 :                 if (error)
     968             :                         return error;
     969             :         }
     970             : 
     971     6175070 :         xfs_dir_update_hook(dp, ip, 1, name);
     972     6175070 :         return 0;
     973             : }
     974             : 
     975             : /*
     976             :  * Given a directory @dp, a child @ip, and a @name, remove the (@name, @ip)
     977             :  * entry from the directory.  Both inodes must have the ILOCK held.
     978             :  */
     979             : int
     980    40996685 : xfs_dir_remove_child(
     981             :         struct xfs_trans        *tp,
     982             :         unsigned int            resblks,
     983             :         struct xfs_dir_update   *du)
     984             : {
     985    40996685 :         struct xfs_inode        *dp = du->dp;
     986    40996685 :         const struct xfs_name   *name = du->name;
     987    40996685 :         struct xfs_inode        *ip = du->ip;
     988    40996685 :         struct xfs_parent_defer *parent = du->parent;
     989    40996685 :         int                     error;
     990             : 
     991    40996685 :         ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
     992    40996793 :         ASSERT(xfs_isilocked(dp, XFS_ILOCK_EXCL));
     993             : 
     994             :         /*
     995             :          * If we're removing a directory perform some additional validation.
     996             :          */
     997    40995959 :         if (S_ISDIR(VFS_I(ip)->i_mode)) {
     998     2519997 :                 ASSERT(VFS_I(ip)->i_nlink >= 2);
     999     2519997 :                 if (VFS_I(ip)->i_nlink != 2)
    1000             :                         return -ENOTEMPTY;
    1001     1221455 :                 if (!xfs_dir_isempty(ip))
    1002             :                         return -ENOTEMPTY;
    1003             : 
    1004             :                 /* Drop the link from ip's "..".  */
    1005      464774 :                 error = xfs_droplink(tp, dp);
    1006      464781 :                 if (error)
    1007             :                         return error;
    1008             : 
    1009             :                 /* Drop the "." link from ip to self.  */
    1010      464781 :                 error = xfs_droplink(tp, ip);
    1011      464784 :                 if (error)
    1012             :                         return error;
    1013             : 
    1014             :                 /*
    1015             :                  * Point the unlinked child directory's ".." entry to the root
    1016             :                  * directory to eliminate back-references to inodes that may
    1017             :                  * get freed before the child directory is closed.  If the fs
    1018             :                  * gets shrunk, this can lead to dirent inode validation errors.
    1019             :                  */
    1020      464784 :                 if (dp->i_ino != tp->t_mountp->m_sb.sb_rootino) {
    1021      437678 :                         error = xfs_dir_replace(tp, ip, &xfs_name_dotdot,
    1022             :                                         tp->t_mountp->m_sb.sb_rootino, 0);
    1023      437668 :                         if (error)
    1024             :                                 return error;
    1025             :                 }
    1026             :         } else {
    1027             :                 /*
    1028             :                  * When removing a non-directory we need to log the parent
    1029             :                  * inode here.  For a directory this is done implicitly
    1030             :                  * by the xfs_droplink call for the ".." entry.
    1031             :                  */
    1032    38475962 :                 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
    1033             :         }
    1034    38941625 :         xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    1035             : 
    1036             :         /* Drop the link from dp to ip. */
    1037    38940678 :         error = xfs_droplink(tp, ip);
    1038    38940676 :         if (error)
    1039             :                 return error;
    1040             : 
    1041    38940699 :         error = xfs_dir_removename(tp, dp, name, ip->i_ino, resblks);
    1042    38940048 :         if (error) {
    1043           3 :                 ASSERT(error != -ENOENT);
    1044           3 :                 return error;
    1045             :         }
    1046             : 
    1047    38940045 :         if (parent) {
    1048    38818568 :                 error = xfs_parent_remove(tp, parent, dp, name, ip);
    1049    38818684 :                 if (error)
    1050             :                         return error;
    1051             :         }
    1052             : 
    1053    38940161 :         xfs_dir_update_hook(dp, ip, -1, name);
    1054    38940161 :         return 0;
    1055             : }
    1056             : 
    1057             : /*
    1058             :  * Exchange the entry (@name1, @ip1) in directory @dp1 with the entry (@name2,
    1059             :  * @ip2) in directory @dp2, and update '..' @ip1 and @ip2's entries as needed.
    1060             :  * @ip1 and @ip2 need not be of the same type.
    1061             :  *
    1062             :  * All inodes must have the ILOCK held, and both entries must already exist.
    1063             :  */
    1064             : int
    1065     8608839 : xfs_dir_exchange_children(
    1066             :         struct xfs_trans        *tp,
    1067             :         struct xfs_dir_update   *i1,
    1068             :         struct xfs_dir_update   *i2,
    1069             :         unsigned int            spaceres)
    1070             : {
    1071     8608839 :         struct xfs_inode        *dp1 = i1->dp;
    1072     8608839 :         const struct xfs_name   *name1 = i1->name;
    1073     8608839 :         struct xfs_inode        *ip1 = i1->ip;
    1074     8608839 :         struct xfs_parent_defer *ip1_pptr = i1->parent;
    1075     8608839 :         struct xfs_inode        *dp2 = i2->dp;
    1076     8608839 :         const struct xfs_name   *name2 = i2->name;
    1077     8608839 :         struct xfs_inode        *ip2 = i2->ip;
    1078     8608839 :         struct xfs_parent_defer *ip2_pptr = i2->parent;
    1079     8608839 :         int                     ip1_flags = 0;
    1080     8608839 :         int                     ip2_flags = 0;
    1081     8608839 :         int                     dp2_flags = 0;
    1082     8608839 :         int                     error;
    1083             : 
    1084             :         /* Swap inode number for dirent in first parent */
    1085     8608839 :         error = xfs_dir_replace(tp, dp1, name1, ip2->i_ino, spaceres);
    1086     8608839 :         if (error)
    1087             :                 return error;
    1088             : 
    1089             :         /* Swap inode number for dirent in second parent */
    1090     8608714 :         error = xfs_dir_replace(tp, dp2, name2, ip1->i_ino, spaceres);
    1091     8608714 :         if (error)
    1092             :                 return error;
    1093             : 
    1094             :         /*
    1095             :          * If we're renaming one or more directories across different parents,
    1096             :          * update the respective ".." entries (and link counts) to match the new
    1097             :          * parents.
    1098             :          */
    1099     8608712 :         if (dp1 != dp2) {
    1100     8376796 :                 dp2_flags = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
    1101             : 
    1102     8376796 :                 if (S_ISDIR(VFS_I(ip2)->i_mode)) {
    1103     2533903 :                         error = xfs_dir_replace(tp, ip2, &xfs_name_dotdot,
    1104             :                                                 dp1->i_ino, spaceres);
    1105     2533903 :                         if (error)
    1106             :                                 return error;
    1107             : 
    1108             :                         /* transfer ip2 ".." reference to dp1 */
    1109     2533903 :                         if (!S_ISDIR(VFS_I(ip1)->i_mode)) {
    1110           8 :                                 error = xfs_droplink(tp, dp2);
    1111           8 :                                 if (error)
    1112             :                                         return error;
    1113           8 :                                 xfs_bumplink(tp, dp1);
    1114             :                         }
    1115             : 
    1116             :                         /*
    1117             :                          * Although ip1 isn't changed here, userspace needs
    1118             :                          * to be warned about the change, so that applications
    1119             :                          * relying on it (like backup ones), will properly
    1120             :                          * notify the change
    1121             :                          */
    1122             :                         ip1_flags |= XFS_ICHGTIME_CHG;
    1123             :                         ip2_flags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
    1124             :                 }
    1125             : 
    1126     8376796 :                 if (S_ISDIR(VFS_I(ip1)->i_mode)) {
    1127     2533903 :                         error = xfs_dir_replace(tp, ip1, &xfs_name_dotdot,
    1128             :                                                 dp2->i_ino, spaceres);
    1129     2533903 :                         if (error)
    1130             :                                 return error;
    1131             : 
    1132             :                         /* transfer ip1 ".." reference to dp2 */
    1133     2533903 :                         if (!S_ISDIR(VFS_I(ip2)->i_mode)) {
    1134           8 :                                 error = xfs_droplink(tp, dp1);
    1135           8 :                                 if (error)
    1136             :                                         return error;
    1137           8 :                                 xfs_bumplink(tp, dp2);
    1138             :                         }
    1139             : 
    1140             :                         /*
    1141             :                          * Although ip2 isn't changed here, userspace needs
    1142             :                          * to be warned about the change, so that applications
    1143             :                          * relying on it (like backup ones), will properly
    1144             :                          * notify the change
    1145             :                          */
    1146     2533903 :                         ip1_flags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
    1147     2533903 :                         ip2_flags |= XFS_ICHGTIME_CHG;
    1148             :                 }
    1149             :         }
    1150             : 
    1151     8608712 :         if (ip1_flags) {
    1152     2533911 :                 xfs_trans_ichgtime(tp, ip1, ip1_flags);
    1153     2533911 :                 xfs_trans_log_inode(tp, ip1, XFS_ILOG_CORE);
    1154             :         }
    1155     8608712 :         if (ip2_flags) {
    1156     2533911 :                 xfs_trans_ichgtime(tp, ip2, ip2_flags);
    1157     2533911 :                 xfs_trans_log_inode(tp, ip2, XFS_ILOG_CORE);
    1158             :         }
    1159     8608712 :         if (dp2_flags) {
    1160     8376796 :                 xfs_trans_ichgtime(tp, dp2, dp2_flags);
    1161     8376796 :                 xfs_trans_log_inode(tp, dp2, XFS_ILOG_CORE);
    1162             :         }
    1163     8608712 :         xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    1164     8608710 :         xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE);
    1165             : 
    1166     8608712 :         if (ip1_pptr) {
    1167     8606310 :                 error = xfs_parent_replace(tp, ip1_pptr, dp1, name1, dp2,
    1168             :                                 name2, ip1);
    1169     8606310 :                 if (error)
    1170             :                         return error;
    1171             :         }
    1172             : 
    1173     8608712 :         if (ip2_pptr) {
    1174     8606310 :                 error = xfs_parent_replace(tp, ip2_pptr, dp2, name2, dp1,
    1175             :                                 name1, ip2);
    1176     8606310 :                 if (error)
    1177             :                         return error;
    1178             :         }
    1179             : 
    1180             :         /*
    1181             :          * Inform our hook clients that we've finished an exchange operation as
    1182             :          * follows: removed the source and target files from their directories;
    1183             :          * added the target to the source directory; and added the source to
    1184             :          * the target directory.  All inodes are locked, so it's ok to model a
    1185             :          * rename this way so long as we say we deleted entries before we add
    1186             :          * new ones.
    1187             :          */
    1188     8608712 :         xfs_dir_update_hook(dp1, ip1, -1, name1);
    1189     8608712 :         xfs_dir_update_hook(dp2, ip2, -1, name2);
    1190     8608712 :         xfs_dir_update_hook(dp1, ip2, 1, name1);
    1191     8608712 :         xfs_dir_update_hook(dp2, ip1, 1, name2);
    1192     8608712 :         return 0;
    1193             : }
    1194             : 
    1195             : /*
    1196             :  * Given an entry (@src_name, @src_ip) in directory @src_dp, make the entry
    1197             :  * @target_name in directory @target_dp point to @src_ip and remove the
    1198             :  * original entry, cleaning up everything left behind.
    1199             :  *
    1200             :  * Cleanup involves dropping a link count on @target_ip, and either removing
    1201             :  * the (@src_name, @src_ip) entry from @src_dp or simply replacing the entry
    1202             :  * with (@src_name, @wip) if a whiteout inode @wip is supplied.
    1203             :  *
    1204             :  * All inodes must have the ILOCK held.  We assume that if @src_ip is a
    1205             :  * directory then its '..' doesn't already point to @target_dp, and that @wip
    1206             :  * is a freshly allocated whiteout.
    1207             :  */
    1208             : int
    1209    22719257 : xfs_dir_rename_children(
    1210             :         struct xfs_trans        *tp,
    1211             :         struct xfs_dir_update   *src,
    1212             :         struct xfs_dir_update   *tgt,
    1213             :         unsigned int            spaceres,
    1214             :         struct xfs_inode        *wip,
    1215             :         struct xfs_parent_defer *wip_pptr)
    1216             : {
    1217    22719257 :         struct xfs_mount        *mp = tp->t_mountp;
    1218    22719257 :         struct xfs_inode        *src_dp = src->dp;
    1219    22719257 :         const struct xfs_name   *src_name = src->name;
    1220    22719257 :         struct xfs_inode        *src_ip = src->ip;
    1221    22719257 :         struct xfs_parent_defer *src_ip_pptr = src->parent;
    1222    22719257 :         struct xfs_inode        *target_dp = tgt->dp;
    1223    22719257 :         const struct xfs_name   *target_name = tgt->name;
    1224    22719257 :         struct xfs_inode        *target_ip = tgt->ip;
    1225    22719257 :         struct xfs_parent_defer *target_ip_pptr = tgt->parent;
    1226    22719257 :         bool                    new_parent = (src_dp != target_dp);
    1227    22719257 :         bool                    src_is_directory;
    1228    22719257 :         int                     error;
    1229             : 
    1230    22719257 :         src_is_directory = S_ISDIR(VFS_I(src_ip)->i_mode);
    1231             : 
    1232             :         /*
    1233             :          * Check for expected errors before we dirty the transaction
    1234             :          * so we can return an error without a transaction abort.
    1235             :          */
    1236    22719257 :         if (target_ip == NULL) {
    1237             :                 /*
    1238             :                  * If there's no space reservation, check the entry will
    1239             :                  * fit before actually inserting it.
    1240             :                  */
    1241    22466249 :                 if (!spaceres) {
    1242           0 :                         error = xfs_dir_canenter(tp, target_dp, target_name);
    1243           0 :                         if (error)
    1244             :                                 return error;
    1245             :                 }
    1246             :         } else {
    1247             :                 /*
    1248             :                  * If target exists and it's a directory, check that whether
    1249             :                  * it can be destroyed.
    1250             :                  */
    1251      253327 :                 if (S_ISDIR(VFS_I(target_ip)->i_mode) &&
    1252         319 :                     (!xfs_dir_isempty(target_ip) ||
    1253         301 :                      (VFS_I(target_ip)->i_nlink > 2)))
    1254             :                         return -EEXIST;
    1255             :         }
    1256             : 
    1257             :         /*
    1258             :          * Directory entry creation below may acquire the AGF. Remove
    1259             :          * the whiteout from the unlinked list first to preserve correct
    1260             :          * AGI/AGF locking order. This dirties the transaction so failures
    1261             :          * after this point will abort and log recovery will clean up the
    1262             :          * mess.
    1263             :          *
    1264             :          * For whiteouts, we need to bump the link count on the whiteout
    1265             :          * inode. After this point, we have a real link, clear the tmpfile
    1266             :          * state flag from the inode so it doesn't accidentally get misused
    1267             :          * in future.
    1268             :          */
    1269    22719239 :         if (wip) {
    1270     2385662 :                 struct xfs_perag        *pag;
    1271             : 
    1272     2385662 :                 ASSERT(VFS_I(wip)->i_nlink == 0);
    1273             : 
    1274     2385662 :                 pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, wip->i_ino));
    1275     2385662 :                 error = xfs_iunlink_remove(tp, pag, wip);
    1276     2385659 :                 xfs_perag_put(pag);
    1277     2385661 :                 if (error)
    1278             :                         return error;
    1279             : 
    1280     2385660 :                 xfs_bumplink(tp, wip);
    1281             :         }
    1282             : 
    1283             :         /*
    1284             :          * Set up the target.
    1285             :          */
    1286    22719241 :         if (target_ip == NULL) {
    1287             :                 /*
    1288             :                  * If target does not exist and the rename crosses
    1289             :                  * directories, adjust the target directory link count
    1290             :                  * to account for the ".." reference from the new entry.
    1291             :                  */
    1292    22466250 :                 error = xfs_dir_createname(tp, target_dp, target_name,
    1293             :                                            src_ip->i_ino, spaceres);
    1294    22466251 :                 if (error)
    1295             :                         return error;
    1296             : 
    1297    22466236 :                 xfs_trans_ichgtime(tp, target_dp,
    1298             :                                         XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    1299             : 
    1300    22466235 :                 if (new_parent && src_is_directory) {
    1301     7657301 :                         xfs_bumplink(tp, target_dp);
    1302             :                 }
    1303             :         } else { /* target_ip != NULL */
    1304             :                 /*
    1305             :                  * Link the source inode under the target name.
    1306             :                  * If the source inode is a directory and we are moving
    1307             :                  * it across directories, its ".." entry will be
    1308             :                  * inconsistent until we replace that down below.
    1309             :                  *
    1310             :                  * In case there is already an entry with the same
    1311             :                  * name at the destination directory, remove it first.
    1312             :                  */
    1313      252991 :                 error = xfs_dir_replace(tp, target_dp, target_name,
    1314             :                                         src_ip->i_ino, spaceres);
    1315      252991 :                 if (error)
    1316             :                         return error;
    1317             : 
    1318      252990 :                 xfs_trans_ichgtime(tp, target_dp,
    1319             :                                         XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    1320             : 
    1321             :                 /*
    1322             :                  * Decrement the link count on the target since the target
    1323             :                  * dir no longer points to it.
    1324             :                  */
    1325      252986 :                 error = xfs_droplink(tp, target_ip);
    1326      252989 :                 if (error)
    1327             :                         return error;
    1328             : 
    1329      252989 :                 if (src_is_directory) {
    1330             :                         /*
    1331             :                          * Drop the link from the old "." entry.
    1332             :                          */
    1333         301 :                         error = xfs_droplink(tp, target_ip);
    1334         301 :                         if (error)
    1335             :                                 return error;
    1336             :                 }
    1337             :         } /* target_ip != NULL */
    1338             : 
    1339             :         /*
    1340             :          * Remove the source.
    1341             :          */
    1342    22719224 :         if (new_parent && src_is_directory) {
    1343             :                 /*
    1344             :                  * Rewrite the ".." entry to point to the new
    1345             :                  * directory.
    1346             :                  */
    1347     7657309 :                 error = xfs_dir_replace(tp, src_ip, &xfs_name_dotdot,
    1348             :                                         target_dp->i_ino, spaceres);
    1349     7657309 :                 ASSERT(error != -EEXIST);
    1350     7657309 :                 if (error)
    1351             :                         return error;
    1352             :         }
    1353             : 
    1354             :         /*
    1355             :          * We always want to hit the ctime on the source inode.
    1356             :          *
    1357             :          * This isn't strictly required by the standards since the source
    1358             :          * inode isn't really being changed, but old unix file systems did
    1359             :          * it and some incremental backup programs won't work without it.
    1360             :          */
    1361    22719224 :         xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG);
    1362    22719222 :         xfs_trans_log_inode(tp, src_ip, XFS_ILOG_CORE);
    1363             : 
    1364             :         /*
    1365             :          * Adjust the link count on src_dp.  This is necessary when
    1366             :          * renaming a directory, either within one parent when
    1367             :          * the target existed, or across two parent directories.
    1368             :          */
    1369    22719227 :         if (src_is_directory && (new_parent || target_ip != NULL)) {
    1370             : 
    1371             :                 /*
    1372             :                  * Decrement link count on src_directory since the
    1373             :                  * entry that's moved no longer points to it.
    1374             :                  */
    1375     7657602 :                 error = xfs_droplink(tp, src_dp);
    1376     7657602 :                 if (error)
    1377             :                         return error;
    1378             :         }
    1379             : 
    1380             :         /*
    1381             :          * For whiteouts, we only need to update the source dirent with the
    1382             :          * inode number of the whiteout inode rather than removing it
    1383             :          * altogether.
    1384             :          */
    1385    22719227 :         if (wip)
    1386     2385663 :                 error = xfs_dir_replace(tp, src_dp, src_name, wip->i_ino,
    1387             :                                         spaceres);
    1388             :         else
    1389    20333564 :                 error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino,
    1390             :                                            spaceres);
    1391    22719226 :         if (error)
    1392             :                 return error;
    1393             : 
    1394    22719219 :         xfs_trans_ichgtime(tp, src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    1395    22719217 :         xfs_trans_log_inode(tp, src_dp, XFS_ILOG_CORE);
    1396    22719220 :         if (new_parent)
    1397    21739598 :                 xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE);
    1398             : 
    1399    22719214 :         if (wip_pptr) {
    1400     2383244 :                 error = xfs_parent_add(tp, wip_pptr, src_dp, src_name, wip);
    1401     2383240 :                 if (error)
    1402             :                         return error;
    1403             :         }
    1404             : 
    1405    22719210 :         if (src_ip_pptr) {
    1406    22568497 :                 error = xfs_parent_replace(tp, src_ip_pptr, src_dp, src_name,
    1407             :                                 target_dp, target_name, src_ip);
    1408    22568495 :                 if (error)
    1409             :                         return error;
    1410             :         }
    1411             : 
    1412    22719208 :         if (target_ip_pptr) {
    1413      252986 :                 error = xfs_parent_remove(tp, target_ip_pptr, target_dp,
    1414             :                                 target_name, target_ip);
    1415      252987 :                 if (error)
    1416             :                         return error;
    1417             :         }
    1418             : 
    1419             :         /*
    1420             :          * Inform our hook clients that we've finished a rename operation as
    1421             :          * follows: removed the source and target files from their directories;
    1422             :          * that we've added the source to the target directory; and finally
    1423             :          * that we've added the whiteout, if there was one.  All inodes are
    1424             :          * locked, so it's ok to model a rename this way so long as we say we
    1425             :          * deleted entries before we add new ones.
    1426             :          */
    1427    22719209 :         if (target_ip)
    1428      252987 :                 xfs_dir_update_hook(target_dp, target_ip, -1, target_name);
    1429    22719212 :         xfs_dir_update_hook(src_dp, src_ip, -1, src_name);
    1430    22719217 :         xfs_dir_update_hook(target_dp, src_ip, 1, target_name);
    1431    22719218 :         if (wip)
    1432     2385662 :                 xfs_dir_update_hook(src_dp, wip, 1, src_name);
    1433             :         return 0;
    1434             : }

Generated by: LCOV version 1.14