LCOV - code coverage report
Current view: top level - fs/xfs - xfs_symlink.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 228 251 90.8 %
Date: 2023-07-31 20:08:22 Functions: 5 5 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (c) 2000-2006 Silicon Graphics, Inc.
       4             :  * Copyright (c) 2012-2013 Red Hat, Inc.
       5             :  * All rights reserved.
       6             :  */
       7             : #include "xfs.h"
       8             : #include "xfs_shared.h"
       9             : #include "xfs_fs.h"
      10             : #include "xfs_format.h"
      11             : #include "xfs_log_format.h"
      12             : #include "xfs_trans_resv.h"
      13             : #include "xfs_bit.h"
      14             : #include "xfs_mount.h"
      15             : #include "xfs_dir2.h"
      16             : #include "xfs_inode.h"
      17             : #include "xfs_bmap.h"
      18             : #include "xfs_bmap_btree.h"
      19             : #include "xfs_quota.h"
      20             : #include "xfs_symlink.h"
      21             : #include "xfs_trans_space.h"
      22             : #include "xfs_trace.h"
      23             : #include "xfs_trans.h"
      24             : #include "xfs_ialloc.h"
      25             : #include "xfs_error.h"
      26             : 
      27             : /* ----- Kernel only functions below ----- */
      28             : int
      29   191397703 : xfs_readlink_bmap_ilocked(
      30             :         struct xfs_inode        *ip,
      31             :         char                    *link)
      32             : {
      33   191397703 :         struct xfs_mount        *mp = ip->i_mount;
      34   191397703 :         struct xfs_bmbt_irec    mval[XFS_SYMLINK_MAPS];
      35   191397703 :         struct xfs_buf          *bp;
      36   191397703 :         xfs_daddr_t             d;
      37   191397703 :         char                    *cur_chunk;
      38   191397703 :         int                     pathlen = ip->i_disk_size;
      39   191397703 :         int                     nmaps = XFS_SYMLINK_MAPS;
      40   191397703 :         int                     byte_cnt;
      41   191397703 :         int                     n;
      42   191397703 :         int                     error = 0;
      43   191397703 :         int                     fsblocks = 0;
      44   191397703 :         int                     offset;
      45             : 
      46   191397703 :         ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
      47             : 
      48   191235751 :         fsblocks = xfs_symlink_blocks(mp, pathlen);
      49   191254496 :         error = xfs_bmapi_read(ip, 0, fsblocks, mval, &nmaps, 0);
      50   191337013 :         if (error)
      51           0 :                 goto out;
      52             : 
      53             :         offset = 0;
      54   382876073 :         for (n = 0; n < nmaps; n++) {
      55   191337816 :                 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
      56   191152146 :                 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
      57             : 
      58   191293005 :                 error = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0,
      59             :                                 &bp, &xfs_symlink_buf_ops);
      60   191298577 :                 if (error)
      61          10 :                         return error;
      62   191298567 :                 byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
      63   191298567 :                 if (pathlen < byte_cnt)
      64             :                         byte_cnt = pathlen;
      65             : 
      66   191298567 :                 cur_chunk = bp->b_addr;
      67   191298567 :                 if (xfs_has_crc(mp)) {
      68   191294837 :                         if (!xfs_symlink_hdr_ok(ip->i_ino, offset,
      69             :                                                         byte_cnt, bp)) {
      70           0 :                                 error = -EFSCORRUPTED;
      71           0 :                                 xfs_alert(mp,
      72             : "symlink header does not match required off/len/owner (0x%x/Ox%x,0x%llx)",
      73             :                                         offset, byte_cnt, ip->i_ino);
      74           0 :                                 xfs_buf_relse(bp);
      75           0 :                                 goto out;
      76             : 
      77             :                         }
      78             : 
      79   191443488 :                         cur_chunk += sizeof(struct xfs_dsymlink_hdr);
      80             :                 }
      81             : 
      82   382894436 :                 memcpy(link + offset, cur_chunk, byte_cnt);
      83             : 
      84   191447218 :                 pathlen -= byte_cnt;
      85   191447218 :                 offset += byte_cnt;
      86             : 
      87   191447218 :                 xfs_buf_relse(bp);
      88             :         }
      89   191538257 :         ASSERT(pathlen == 0);
      90             : 
      91   191538257 :         link[ip->i_disk_size] = '\0';
      92   191538257 :         error = 0;
      93             : 
      94             :  out:
      95             :         return error;
      96             : }
      97             : 
      98             : int
      99   244590881 : xfs_readlink(
     100             :         struct xfs_inode        *ip,
     101             :         char                    *link)
     102             : {
     103   244590881 :         struct xfs_mount        *mp = ip->i_mount;
     104   244590881 :         xfs_fsize_t             pathlen;
     105   244590881 :         int                     error = -EFSCORRUPTED;
     106             : 
     107   244590881 :         trace_xfs_readlink(ip);
     108             : 
     109   488436070 :         if (xfs_is_shutdown(mp))
     110             :                 return -EIO;
     111             : 
     112   244217998 :         xfs_ilock(ip, XFS_ILOCK_SHARED);
     113             : 
     114   244646868 :         pathlen = ip->i_disk_size;
     115   244646868 :         if (!pathlen)
     116           0 :                 goto out;
     117             : 
     118   244646868 :         if (pathlen < 0 || pathlen > XFS_SYMLINK_MAXLEN) {
     119           0 :                 xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)",
     120             :                          __func__, (unsigned long long) ip->i_ino,
     121             :                          (long long) pathlen);
     122           0 :                 ASSERT(0);
     123           0 :                 goto out;
     124             :         }
     125             : 
     126   244646868 :         if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     127             :                 /*
     128             :                  * The VFS crashes on a NULL pointer, so return -EFSCORRUPTED
     129             :                  * if if_data is junk.
     130             :                  */
     131    80612983 :                 if (XFS_IS_CORRUPT(ip->i_mount, !ip->i_df.if_u1.if_data))
     132           0 :                         goto out;
     133             : 
     134   161225966 :                 memcpy(link, ip->i_df.if_u1.if_data, pathlen + 1);
     135    80612983 :                 error = 0;
     136             :         } else {
     137   164033885 :                 error = xfs_readlink_bmap_ilocked(ip, link);
     138             :         }
     139             : 
     140   244807691 :  out:
     141   244807691 :         xfs_iunlock(ip, XFS_ILOCK_SHARED);
     142   244807691 :         return error;
     143             : }
     144             : 
     145             : int
     146   295429483 : xfs_symlink(
     147             :         struct mnt_idmap        *idmap,
     148             :         struct xfs_inode        *dp,
     149             :         struct xfs_name         *link_name,
     150             :         const char              *target_path,
     151             :         umode_t                 mode,
     152             :         struct xfs_inode        **ipp)
     153             : {
     154   295429483 :         struct xfs_mount        *mp = dp->i_mount;
     155   295429483 :         struct xfs_trans        *tp = NULL;
     156   295429483 :         struct xfs_inode        *ip = NULL;
     157   295429483 :         int                     error = 0;
     158   295429483 :         int                     pathlen;
     159   295429483 :         bool                    unlock_dp_on_error = false;
     160   295429483 :         xfs_fileoff_t           first_fsb;
     161   295429483 :         xfs_filblks_t           fs_blocks;
     162   295429483 :         int                     nmaps;
     163   295429483 :         struct xfs_bmbt_irec    mval[XFS_SYMLINK_MAPS];
     164   295429483 :         xfs_daddr_t             d;
     165   295429483 :         const char              *cur_chunk;
     166   295429483 :         int                     byte_cnt;
     167   295429483 :         int                     n;
     168   295429483 :         struct xfs_buf          *bp;
     169   295429483 :         prid_t                  prid;
     170   295429483 :         struct xfs_dquot        *udqp = NULL;
     171   295429483 :         struct xfs_dquot        *gdqp = NULL;
     172   295429483 :         struct xfs_dquot        *pdqp = NULL;
     173   295429483 :         uint                    resblks;
     174   295429483 :         xfs_ino_t               ino;
     175             : 
     176   295429483 :         *ipp = NULL;
     177             : 
     178   295429483 :         trace_xfs_symlink(dp, link_name);
     179             : 
     180   590487340 :         if (xfs_is_shutdown(mp))
     181             :                 return -EIO;
     182             : 
     183             :         /*
     184             :          * Check component lengths of the target path name.
     185             :          */
     186   295243670 :         pathlen = strlen(target_path);
     187   295243670 :         if (pathlen >= XFS_SYMLINK_MAXLEN)      /* total string too long */
     188             :                 return -ENAMETOOLONG;
     189    25257645 :         ASSERT(pathlen > 0);
     190             : 
     191    25257645 :         prid = xfs_get_initial_prid(dp);
     192             : 
     193             :         /*
     194             :          * Make sure that we have allocated dquot(s) on disk.
     195             :          */
     196    25257645 :         error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(idmap, &init_user_ns),
     197             :                         mapped_fsgid(idmap, &init_user_ns), prid,
     198             :                         XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
     199             :                         &udqp, &gdqp, &pdqp);
     200    25762151 :         if (error)
     201             :                 return error;
     202             : 
     203             :         /*
     204             :          * The symlink will fit into the inode data fork?
     205             :          * There can't be any attributes so we get the whole variable part.
     206             :          */
     207    25762146 :         if (pathlen <= XFS_LITINO(mp))
     208             :                 fs_blocks = 0;
     209             :         else
     210    17243593 :                 fs_blocks = xfs_symlink_blocks(mp, pathlen);
     211    25761277 :         resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
     212             : 
     213    25761277 :         error = xfs_trans_alloc_icreate(mp, &M_RES(mp)->tr_symlink, udqp, gdqp,
     214             :                         pdqp, resblks, &tp);
     215    25754718 :         if (error)
     216       30614 :                 goto out_release_dquots;
     217             : 
     218    25724104 :         xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
     219    25721824 :         unlock_dp_on_error = true;
     220             : 
     221             :         /*
     222             :          * Check whether the directory allows new symlinks or not.
     223             :          */
     224    25721824 :         if (dp->i_diflags & XFS_DIFLAG_NOSYMLINKS) {
     225          11 :                 error = -EPERM;
     226          11 :                 goto out_trans_cancel;
     227             :         }
     228             : 
     229             :         /*
     230             :          * Allocate an inode for the symlink.
     231             :          */
     232    25721813 :         error = xfs_dialloc(&tp, dp->i_ino, S_IFLNK, &ino);
     233    25735822 :         if (!error)
     234    25734730 :                 error = xfs_init_new_inode(idmap, tp, dp, ino,
     235    25734730 :                                 S_IFLNK | (mode & ~S_IFMT), 1, 0, prid,
     236             :                                 false, &ip);
     237    25716655 :         if (error)
     238          40 :                 goto out_trans_cancel;
     239             : 
     240             :         /*
     241             :          * Now we join the directory inode to the transaction.  We do not do it
     242             :          * earlier because xfs_dir_ialloc might commit the previous transaction
     243             :          * (and release all the locks).  An error from here on will result in
     244             :          * the transaction cancel unlocking dp so don't do it explicitly in the
     245             :          * error path.
     246             :          */
     247    25716615 :         xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
     248    25726566 :         unlock_dp_on_error = false;
     249             : 
     250             :         /*
     251             :          * Also attach the dquot(s) to it, if applicable.
     252             :          */
     253    25726566 :         xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
     254             : 
     255    25718362 :         resblks -= XFS_IALLOC_SPACE_RES(mp);
     256             :         /*
     257             :          * If the symlink will fit into the inode, write it inline.
     258             :          */
     259    25718362 :         if (pathlen <= xfs_inode_data_fork_size(ip)) {
     260     8502345 :                 xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
     261             : 
     262     8502721 :                 ip->i_disk_size = pathlen;
     263     8502721 :                 ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
     264     8502721 :                 xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
     265             :         } else {
     266    17216017 :                 int     offset;
     267             : 
     268    17216017 :                 first_fsb = 0;
     269    17216017 :                 nmaps = XFS_SYMLINK_MAPS;
     270             : 
     271    17216017 :                 error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks,
     272             :                                   XFS_BMAPI_METADATA, resblks, mval, &nmaps);
     273    17192948 :                 if (error)
     274           6 :                         goto out_trans_cancel;
     275             : 
     276    17192942 :                 resblks -= fs_blocks;
     277    17192942 :                 ip->i_disk_size = pathlen;
     278    17192942 :                 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     279             : 
     280    17192942 :                 cur_chunk = target_path;
     281    17192942 :                 offset = 0;
     282    51635155 :                 for (n = 0; n < nmaps; n++) {
     283    17228690 :                         char    *buf;
     284             : 
     285    17228690 :                         d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
     286    17197584 :                         byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
     287    17197801 :                         error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
     288    17197801 :                                                BTOBB(byte_cnt), 0, &bp);
     289    17203220 :                         if (error)
     290           0 :                                 goto out_trans_cancel;
     291    17203220 :                         bp->b_ops = &xfs_symlink_buf_ops;
     292             : 
     293    17203220 :                         byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
     294    17203220 :                         byte_cnt = min(byte_cnt, pathlen);
     295             : 
     296    17203220 :                         buf = bp->b_addr;
     297    17203220 :                         buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset,
     298             :                                                    byte_cnt, bp);
     299             : 
     300    34351516 :                         memcpy(buf, cur_chunk, byte_cnt);
     301             : 
     302    17175758 :                         cur_chunk += byte_cnt;
     303    17175758 :                         pathlen -= byte_cnt;
     304    17175758 :                         offset += byte_cnt;
     305             : 
     306    17175758 :                         xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
     307    17202054 :                         xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
     308    17202054 :                                                         (char *)bp->b_addr);
     309             :                 }
     310    17213523 :                 ASSERT(pathlen == 0);
     311             :         }
     312    25719404 :         i_size_write(VFS_I(ip), ip->i_disk_size);
     313             : 
     314             :         /*
     315             :          * Create the directory entry for the symlink.
     316             :          */
     317    25719404 :         error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, resblks);
     318    25725324 :         if (error)
     319           0 :                 goto out_trans_cancel;
     320    25725324 :         xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
     321    25711120 :         xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
     322             : 
     323             :         /*
     324             :          * If this is a synchronous mount, make sure that the
     325             :          * symlink transaction goes to disk before returning to
     326             :          * the user.
     327             :          */
     328    25732829 :         if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
     329           0 :                 xfs_trans_set_sync(tp);
     330             : 
     331    25732829 :         error = xfs_trans_commit(tp);
     332    25699771 :         if (error)
     333           7 :                 goto out_release_inode;
     334             : 
     335    25699764 :         xfs_qm_dqrele(udqp);
     336    25695294 :         xfs_qm_dqrele(gdqp);
     337    25698608 :         xfs_qm_dqrele(pdqp);
     338             : 
     339    25703183 :         *ipp = ip;
     340    25703183 :         return 0;
     341             : 
     342          57 : out_trans_cancel:
     343          57 :         xfs_trans_cancel(tp);
     344          64 : out_release_inode:
     345             :         /*
     346             :          * Wait until after the current transaction is aborted to finish the
     347             :          * setup of the inode and release the inode.  This prevents recursive
     348             :          * transactions and deadlocks from xfs_inactive.
     349             :          */
     350          64 :         if (ip) {
     351          13 :                 xfs_finish_inode_setup(ip);
     352          13 :                 xfs_irele(ip);
     353             :         }
     354          51 : out_release_dquots:
     355       30678 :         xfs_qm_dqrele(udqp);
     356       30679 :         xfs_qm_dqrele(gdqp);
     357       30679 :         xfs_qm_dqrele(pdqp);
     358             : 
     359       30679 :         if (unlock_dp_on_error)
     360          51 :                 xfs_iunlock(dp, XFS_ILOCK_EXCL);
     361             :         return error;
     362             : }
     363             : 
     364             : /*
     365             :  * Free a symlink that has blocks associated with it.
     366             :  *
     367             :  * Note: zero length symlinks are not allowed to exist. When we set the size to
     368             :  * zero, also change it to a regular file so that it does not get written to
     369             :  * disk as a zero length symlink. The inode is on the unlinked list already, so
     370             :  * userspace cannot find this inode anymore, so this change is not user visible
     371             :  * but allows us to catch corrupt zero-length symlinks in the verifiers.
     372             :  */
     373             : STATIC int
     374    16528494 : xfs_inactive_symlink_rmt(
     375             :         struct xfs_inode *ip)
     376             : {
     377    16528494 :         struct xfs_buf  *bp;
     378    16528494 :         int             done;
     379    16528494 :         int             error;
     380    16528494 :         int             i;
     381    16528494 :         xfs_mount_t     *mp;
     382    16528494 :         xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS];
     383    16528494 :         int             nmaps;
     384    16528494 :         int             size;
     385    16528494 :         xfs_trans_t     *tp;
     386             : 
     387    16528494 :         mp = ip->i_mount;
     388    16528494 :         ASSERT(!xfs_need_iread_extents(&ip->i_df));
     389             :         /*
     390             :          * We're freeing a symlink that has some
     391             :          * blocks allocated to it.  Free the
     392             :          * blocks here.  We know that we've got
     393             :          * either 1 or 2 extents and that we can
     394             :          * free them all in one bunmapi call.
     395             :          */
     396    16528150 :         ASSERT(ip->i_df.if_nextents > 0 && ip->i_df.if_nextents <= 2);
     397             : 
     398    16528150 :         error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
     399    16517184 :         if (error)
     400             :                 return error;
     401             : 
     402    16517423 :         xfs_ilock(ip, XFS_ILOCK_EXCL);
     403    16521834 :         xfs_trans_ijoin(tp, ip, 0);
     404             : 
     405             :         /*
     406             :          * Lock the inode, fix the size, turn it into a regular file and join it
     407             :          * to the transaction.  Hold it so in the normal path, we still have it
     408             :          * locked for the second transaction.  In the error paths we need it
     409             :          * held so the cancel won't rele it, see below.
     410             :          */
     411    16523507 :         size = (int)ip->i_disk_size;
     412    16523507 :         ip->i_disk_size = 0;
     413    16523507 :         VFS_I(ip)->i_mode = (VFS_I(ip)->i_mode & ~S_IFMT) | S_IFREG;
     414    16523507 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     415             :         /*
     416             :          * Find the block(s) so we can inval and unmap them.
     417             :          */
     418    16538426 :         done = 0;
     419    16538426 :         nmaps = ARRAY_SIZE(mval);
     420    16538426 :         error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size),
     421             :                                 mval, &nmaps, 0);
     422    16509718 :         if (error)
     423           0 :                 goto error_trans_cancel;
     424             :         /*
     425             :          * Invalidate the block(s). No validation is done.
     426             :          */
     427    33053336 :         for (i = 0; i < nmaps; i++) {
     428    82529418 :                 error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
     429    16510133 :                                 XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
     430    16511422 :                                 XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0,
     431             :                                 &bp);
     432    16525425 :                 if (error)
     433           0 :                         goto error_trans_cancel;
     434    16525425 :                 xfs_trans_binval(tp, bp);
     435             :         }
     436             :         /*
     437             :          * Unmap the dead block(s) to the dfops.
     438             :          */
     439    16541914 :         error = xfs_bunmapi(tp, ip, 0, size, 0, nmaps, &done);
     440    16527796 :         if (error)
     441           0 :                 goto error_trans_cancel;
     442    16527796 :         ASSERT(done);
     443             : 
     444             :         /*
     445             :          * Commit the transaction. This first logs the EFI and the inode, then
     446             :          * rolls and commits the transaction that frees the extents.
     447             :          */
     448    16527796 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     449    16538366 :         error = xfs_trans_commit(tp);
     450    16532549 :         if (error) {
     451           8 :                 ASSERT(xfs_is_shutdown(mp));
     452           4 :                 goto error_unlock;
     453             :         }
     454             : 
     455             :         /*
     456             :          * Remove the memory for extent descriptions (just bookkeeping).
     457             :          */
     458    16532545 :         if (ip->i_df.if_bytes)
     459           0 :                 xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK);
     460    16532545 :         ASSERT(ip->i_df.if_bytes == 0);
     461             : 
     462    16532545 :         xfs_iunlock(ip, XFS_ILOCK_EXCL);
     463    16532545 :         return 0;
     464             : 
     465           0 : error_trans_cancel:
     466           0 :         xfs_trans_cancel(tp);
     467           4 : error_unlock:
     468           4 :         xfs_iunlock(ip, XFS_ILOCK_EXCL);
     469           4 :         return error;
     470             : }
     471             : 
     472             : /*
     473             :  * xfs_inactive_symlink - free a symlink
     474             :  */
     475             : int
     476    24644249 : xfs_inactive_symlink(
     477             :         struct xfs_inode        *ip)
     478             : {
     479    24644249 :         struct xfs_mount        *mp = ip->i_mount;
     480    24644249 :         int                     pathlen;
     481             : 
     482    24644249 :         trace_xfs_inactive_symlink(ip);
     483             : 
     484    49246406 :         if (xfs_is_shutdown(mp))
     485             :                 return -EIO;
     486             : 
     487    24623192 :         xfs_ilock(ip, XFS_ILOCK_EXCL);
     488    24668587 :         pathlen = (int)ip->i_disk_size;
     489    24668587 :         ASSERT(pathlen);
     490             : 
     491    24668587 :         if (pathlen <= 0 || pathlen > XFS_SYMLINK_MAXLEN) {
     492           0 :                 xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)",
     493             :                          __func__, (unsigned long long)ip->i_ino, pathlen);
     494           0 :                 xfs_iunlock(ip, XFS_ILOCK_EXCL);
     495           0 :                 ASSERT(0);
     496           0 :                 return -EFSCORRUPTED;
     497             :         }
     498             : 
     499             :         /*
     500             :          * Inline fork state gets removed by xfs_difree() so we have nothing to
     501             :          * do here in that case.
     502             :          */
     503    24668587 :         if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     504     8139487 :                 xfs_iunlock(ip, XFS_ILOCK_EXCL);
     505     8139487 :                 return 0;
     506             :         }
     507             : 
     508    16529100 :         xfs_iunlock(ip, XFS_ILOCK_EXCL);
     509             : 
     510             :         /* remove the remote symlink */
     511    16535258 :         return xfs_inactive_symlink_rmt(ip);
     512             : }

Generated by: LCOV version 1.14