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-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 229 251 91.2 %
Date: 2023-07-31 20:08:17 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   204241425 : xfs_readlink_bmap_ilocked(
      30             :         struct xfs_inode        *ip,
      31             :         char                    *link)
      32             : {
      33   204241425 :         struct xfs_mount        *mp = ip->i_mount;
      34   204241425 :         struct xfs_bmbt_irec    mval[XFS_SYMLINK_MAPS];
      35   204241425 :         struct xfs_buf          *bp;
      36   204241425 :         xfs_daddr_t             d;
      37   204241425 :         char                    *cur_chunk;
      38   204241425 :         int                     pathlen = ip->i_disk_size;
      39   204241425 :         int                     nmaps = XFS_SYMLINK_MAPS;
      40   204241425 :         int                     byte_cnt;
      41   204241425 :         int                     n;
      42   204241425 :         int                     error = 0;
      43   204241425 :         int                     fsblocks = 0;
      44   204241425 :         int                     offset;
      45             : 
      46   204241425 :         ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
      47             : 
      48   204277711 :         fsblocks = xfs_symlink_blocks(mp, pathlen);
      49   204273653 :         error = xfs_bmapi_read(ip, 0, fsblocks, mval, &nmaps, 0);
      50   204337830 :         if (error)
      51           0 :                 goto out;
      52             : 
      53             :         offset = 0;
      54   408674157 :         for (n = 0; n < nmaps; n++) {
      55   204341462 :                 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
      56   204341460 :                 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
      57             : 
      58   204275183 :                 error = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0,
      59             :                                 &bp, &xfs_symlink_buf_ops);
      60   204308095 :                 if (error)
      61           2 :                         return error;
      62   204308093 :                 byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
      63   204308093 :                 if (pathlen < byte_cnt)
      64             :                         byte_cnt = pathlen;
      65             : 
      66   204308093 :                 cur_chunk = bp->b_addr;
      67   204308093 :                 if (xfs_has_crc(mp)) {
      68   204331584 :                         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   204244637 :                         cur_chunk += sizeof(struct xfs_dsymlink_hdr);
      80             :                 }
      81             : 
      82   408442292 :                 memcpy(link + offset, cur_chunk, byte_cnt);
      83             : 
      84   204221146 :                 pathlen -= byte_cnt;
      85   204221146 :                 offset += byte_cnt;
      86             : 
      87   204221146 :                 xfs_buf_relse(bp);
      88             :         }
      89   204332695 :         ASSERT(pathlen == 0);
      90             : 
      91   204332695 :         link[ip->i_disk_size] = '\0';
      92   204332695 :         error = 0;
      93             : 
      94             :  out:
      95             :         return error;
      96             : }
      97             : 
      98             : int
      99   265910751 : xfs_readlink(
     100             :         struct xfs_inode        *ip,
     101             :         char                    *link)
     102             : {
     103   265910751 :         struct xfs_mount        *mp = ip->i_mount;
     104   265910751 :         xfs_fsize_t             pathlen;
     105   265910751 :         int                     error = -EFSCORRUPTED;
     106             : 
     107   265910751 :         trace_xfs_readlink(ip);
     108             : 
     109   531854706 :         if (xfs_is_shutdown(mp))
     110             :                 return -EIO;
     111             : 
     112   265927317 :         xfs_ilock(ip, XFS_ILOCK_SHARED);
     113             : 
     114   266050157 :         pathlen = ip->i_disk_size;
     115   266050157 :         if (!pathlen)
     116           0 :                 goto out;
     117             : 
     118   266050157 :         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   266050157 :         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    87454392 :                 if (XFS_IS_CORRUPT(ip->i_mount, !ip->i_df.if_u1.if_data))
     132           0 :                         goto out;
     133             : 
     134   174908784 :                 memcpy(link, ip->i_df.if_u1.if_data, pathlen + 1);
     135    87454392 :                 error = 0;
     136             :         } else {
     137   178595765 :                 error = xfs_readlink_bmap_ilocked(ip, link);
     138             :         }
     139             : 
     140   266104684 :  out:
     141   266104684 :         xfs_iunlock(ip, XFS_ILOCK_SHARED);
     142   266104684 :         return error;
     143             : }
     144             : 
     145             : int
     146   238010029 : 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   238010029 :         struct xfs_mount        *mp = dp->i_mount;
     155   238010029 :         struct xfs_trans        *tp = NULL;
     156   238010029 :         struct xfs_inode        *ip = NULL;
     157   238010029 :         int                     error = 0;
     158   238010029 :         int                     pathlen;
     159   238010029 :         bool                    unlock_dp_on_error = false;
     160   238010029 :         xfs_fileoff_t           first_fsb;
     161   238010029 :         xfs_filblks_t           fs_blocks;
     162   238010029 :         int                     nmaps;
     163   238010029 :         struct xfs_bmbt_irec    mval[XFS_SYMLINK_MAPS];
     164   238010029 :         xfs_daddr_t             d;
     165   238010029 :         const char              *cur_chunk;
     166   238010029 :         int                     byte_cnt;
     167   238010029 :         int                     n;
     168   238010029 :         struct xfs_buf          *bp;
     169   238010029 :         prid_t                  prid;
     170   238010029 :         struct xfs_dquot        *udqp = NULL;
     171   238010029 :         struct xfs_dquot        *gdqp = NULL;
     172   238010029 :         struct xfs_dquot        *pdqp = NULL;
     173   238010029 :         uint                    resblks;
     174   238010029 :         xfs_ino_t               ino;
     175             : 
     176   238010029 :         *ipp = NULL;
     177             : 
     178   238010029 :         trace_xfs_symlink(dp, link_name);
     179             : 
     180   476056792 :         if (xfs_is_shutdown(mp))
     181             :                 return -EIO;
     182             : 
     183             :         /*
     184             :          * Check component lengths of the target path name.
     185             :          */
     186   238028396 :         pathlen = strlen(target_path);
     187   238028396 :         if (pathlen >= XFS_SYMLINK_MAXLEN)      /* total string too long */
     188             :                 return -ENAMETOOLONG;
     189    27320086 :         ASSERT(pathlen > 0);
     190             : 
     191    27320086 :         prid = xfs_get_initial_prid(dp);
     192             : 
     193             :         /*
     194             :          * Make sure that we have allocated dquot(s) on disk.
     195             :          */
     196    27320086 :         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    27296043 :         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    27296032 :         if (pathlen <= XFS_LITINO(mp))
     208             :                 fs_blocks = 0;
     209             :         else
     210    18328253 :                 fs_blocks = xfs_symlink_blocks(mp, pathlen);
     211    27296007 :         resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
     212             : 
     213    27296007 :         error = xfs_trans_alloc_icreate(mp, &M_RES(mp)->tr_symlink, udqp, gdqp,
     214             :                         pdqp, resblks, &tp);
     215    27296502 :         if (error)
     216       16510 :                 goto out_release_dquots;
     217             : 
     218    27279992 :         xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
     219    27279740 :         unlock_dp_on_error = true;
     220             : 
     221             :         /*
     222             :          * Check whether the directory allows new symlinks or not.
     223             :          */
     224    27279740 :         if (dp->i_diflags & XFS_DIFLAG_NOSYMLINKS) {
     225           2 :                 error = -EPERM;
     226           2 :                 goto out_trans_cancel;
     227             :         }
     228             : 
     229             :         /*
     230             :          * Allocate an inode for the symlink.
     231             :          */
     232    27279738 :         error = xfs_dialloc(&tp, dp->i_ino, S_IFLNK, &ino);
     233    27279796 :         if (!error)
     234    27279875 :                 error = xfs_init_new_inode(idmap, tp, dp, ino,
     235    27279875 :                                 S_IFLNK | (mode & ~S_IFMT), 1, 0, prid,
     236             :                                 false, &ip);
     237    27279748 :         if (error)
     238           7 :                 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    27279741 :         xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
     248    27279680 :         unlock_dp_on_error = false;
     249             : 
     250             :         /*
     251             :          * Also attach the dquot(s) to it, if applicable.
     252             :          */
     253    27279680 :         xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
     254             : 
     255    27279758 :         resblks -= XFS_IALLOC_SPACE_RES(mp);
     256             :         /*
     257             :          * If the symlink will fit into the inode, write it inline.
     258             :          */
     259    27279758 :         if (pathlen <= xfs_inode_data_fork_size(ip)) {
     260     8962648 :                 xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
     261             : 
     262     8962792 :                 ip->i_disk_size = pathlen;
     263     8962792 :                 ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
     264     8962792 :                 xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
     265             :         } else {
     266    18317110 :                 int     offset;
     267             : 
     268    18317110 :                 first_fsb = 0;
     269    18317110 :                 nmaps = XFS_SYMLINK_MAPS;
     270             : 
     271    18317110 :                 error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks,
     272             :                                   XFS_BMAPI_METADATA, resblks, mval, &nmaps);
     273    18315882 :                 if (error)
     274           3 :                         goto out_trans_cancel;
     275             : 
     276    18315879 :                 resblks -= fs_blocks;
     277    18315879 :                 ip->i_disk_size = pathlen;
     278    18315879 :                 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     279             : 
     280    18315879 :                 cur_chunk = target_path;
     281    18315879 :                 offset = 0;
     282    54948529 :                 for (n = 0; n < nmaps; n++) {
     283    18315896 :                         char    *buf;
     284             : 
     285    18315896 :                         d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
     286    18316470 :                         byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
     287    18316487 :                         error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
     288    18316487 :                                                BTOBB(byte_cnt), 0, &bp);
     289    18316712 :                         if (error)
     290           0 :                                 goto out_trans_cancel;
     291    18316712 :                         bp->b_ops = &xfs_symlink_buf_ops;
     292             : 
     293    18316712 :                         byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
     294    18316712 :                         byte_cnt = min(byte_cnt, pathlen);
     295             : 
     296    18316712 :                         buf = bp->b_addr;
     297    18316712 :                         buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset,
     298             :                                                    byte_cnt, bp);
     299             : 
     300    36633080 :                         memcpy(buf, cur_chunk, byte_cnt);
     301             : 
     302    18316540 :                         cur_chunk += byte_cnt;
     303    18316540 :                         pathlen -= byte_cnt;
     304    18316540 :                         offset += byte_cnt;
     305             : 
     306    18316540 :                         xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
     307    18316220 :                         xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
     308    18316220 :                                                         (char *)bp->b_addr);
     309             :                 }
     310    18316754 :                 ASSERT(pathlen == 0);
     311             :         }
     312    27279611 :         i_size_write(VFS_I(ip), ip->i_disk_size);
     313             : 
     314             :         /*
     315             :          * Create the directory entry for the symlink.
     316             :          */
     317    27279611 :         error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, resblks);
     318    27278318 :         if (error)
     319           2 :                 goto out_trans_cancel;
     320    27278316 :         xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
     321    27278422 :         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    27279738 :         if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
     329           0 :                 xfs_trans_set_sync(tp);
     330             : 
     331    27279738 :         error = xfs_trans_commit(tp);
     332    27279906 :         if (error)
     333          17 :                 goto out_release_inode;
     334             : 
     335    27279889 :         xfs_qm_dqrele(udqp);
     336    27280103 :         xfs_qm_dqrele(gdqp);
     337    27280138 :         xfs_qm_dqrele(pdqp);
     338             : 
     339    27280152 :         *ipp = ip;
     340    27280152 :         return 0;
     341             : 
     342          14 : out_trans_cancel:
     343          14 :         xfs_trans_cancel(tp);
     344          31 : 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          31 :         if (ip) {
     351          22 :                 xfs_finish_inode_setup(ip);
     352          22 :                 xfs_irele(ip);
     353             :         }
     354           9 : out_release_dquots:
     355       16541 :         xfs_qm_dqrele(udqp);
     356       16540 :         xfs_qm_dqrele(gdqp);
     357       16541 :         xfs_qm_dqrele(pdqp);
     358             : 
     359       16541 :         if (unlock_dp_on_error)
     360           9 :                 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    17909836 : xfs_inactive_symlink_rmt(
     375             :         struct xfs_inode *ip)
     376             : {
     377    17909836 :         struct xfs_buf  *bp;
     378    17909836 :         int             done;
     379    17909836 :         int             error;
     380    17909836 :         int             i;
     381    17909836 :         xfs_mount_t     *mp;
     382    17909836 :         xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS];
     383    17909836 :         int             nmaps;
     384    17909836 :         int             size;
     385    17909836 :         xfs_trans_t     *tp;
     386             : 
     387    17909836 :         mp = ip->i_mount;
     388    17909836 :         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    17910227 :         ASSERT(ip->i_df.if_nextents > 0 && ip->i_df.if_nextents <= 2);
     397             : 
     398    17910227 :         error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
     399    17910559 :         if (error)
     400             :                 return error;
     401             : 
     402    17910573 :         xfs_ilock(ip, XFS_ILOCK_EXCL);
     403    17910599 :         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    17909626 :         size = (int)ip->i_disk_size;
     412    17909626 :         ip->i_disk_size = 0;
     413    17909626 :         VFS_I(ip)->i_mode = (VFS_I(ip)->i_mode & ~S_IFMT) | S_IFREG;
     414    17909626 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     415             :         /*
     416             :          * Find the block(s) so we can inval and unmap them.
     417             :          */
     418    17910453 :         done = 0;
     419    17910453 :         nmaps = ARRAY_SIZE(mval);
     420    17910453 :         error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size),
     421             :                                 mval, &nmaps, 0);
     422    17910149 :         if (error)
     423           0 :                 goto error_trans_cancel;
     424             :         /*
     425             :          * Invalidate the block(s). No validation is done.
     426             :          */
     427    35820431 :         for (i = 0; i < nmaps; i++) {
     428    71640993 :                 error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
     429    17910132 :                                 XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
     430    17910273 :                                 XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0,
     431             :                                 &bp);
     432    17908981 :                 if (error)
     433           0 :                         goto error_trans_cancel;
     434    17908981 :                 xfs_trans_binval(tp, bp);
     435             :         }
     436             :         /*
     437             :          * Unmap the dead block(s) to the dfops.
     438             :          */
     439    17910299 :         error = xfs_bunmapi(tp, ip, 0, size, 0, nmaps, &done);
     440    17910156 :         if (error)
     441           0 :                 goto error_trans_cancel;
     442    17910156 :         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    17910156 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     449    17910177 :         error = xfs_trans_commit(tp);
     450    17910611 :         if (error) {
     451           4 :                 ASSERT(xfs_is_shutdown(mp));
     452           2 :                 goto error_unlock;
     453             :         }
     454             : 
     455             :         /*
     456             :          * Remove the memory for extent descriptions (just bookkeeping).
     457             :          */
     458    17910609 :         if (ip->i_df.if_bytes)
     459           0 :                 xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK);
     460    17910609 :         ASSERT(ip->i_df.if_bytes == 0);
     461             : 
     462    17910609 :         xfs_iunlock(ip, XFS_ILOCK_EXCL);
     463    17910609 :         return 0;
     464             : 
     465           0 : error_trans_cancel:
     466           0 :         xfs_trans_cancel(tp);
     467           2 : error_unlock:
     468           2 :         xfs_iunlock(ip, XFS_ILOCK_EXCL);
     469           2 :         return error;
     470             : }
     471             : 
     472             : /*
     473             :  * xfs_inactive_symlink - free a symlink
     474             :  */
     475             : int
     476    26671020 : xfs_inactive_symlink(
     477             :         struct xfs_inode        *ip)
     478             : {
     479    26671020 :         struct xfs_mount        *mp = ip->i_mount;
     480    26671020 :         int                     pathlen;
     481             : 
     482    26671020 :         trace_xfs_inactive_symlink(ip);
     483             : 
     484    53341960 :         if (xfs_is_shutdown(mp))
     485             :                 return -EIO;
     486             : 
     487    26670973 :         xfs_ilock(ip, XFS_ILOCK_EXCL);
     488    26672525 :         pathlen = (int)ip->i_disk_size;
     489    26672525 :         ASSERT(pathlen);
     490             : 
     491    26672525 :         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    26672525 :         if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
     504     8762591 :                 xfs_iunlock(ip, XFS_ILOCK_EXCL);
     505     8762591 :                 return 0;
     506             :         }
     507             : 
     508    17909934 :         xfs_iunlock(ip, XFS_ILOCK_EXCL);
     509             : 
     510             :         /* remove the remote symlink */
     511    17909583 :         return xfs_inactive_symlink_rmt(ip);
     512             : }

Generated by: LCOV version 1.14