LCOV - code coverage report
Current view: top level - fs/xfs - xfs_parent_utils.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 56 62 90.3 %
Date: 2023-07-31 20:08:34 Functions: 2 2 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (c) 2022-2023 Oracle, Inc.
       4             :  * All rights reserved.
       5             :  */
       6             : #include "xfs.h"
       7             : #include "xfs_fs.h"
       8             : #include "xfs_format.h"
       9             : #include "xfs_log_format.h"
      10             : #include "xfs_shared.h"
      11             : #include "xfs_trans_resv.h"
      12             : #include "xfs_mount.h"
      13             : #include "xfs_bmap_btree.h"
      14             : #include "xfs_inode.h"
      15             : #include "xfs_error.h"
      16             : #include "xfs_trace.h"
      17             : #include "xfs_trans.h"
      18             : #include "xfs_da_format.h"
      19             : #include "xfs_da_btree.h"
      20             : #include "xfs_attr.h"
      21             : #include "xfs_ioctl.h"
      22             : #include "xfs_parent.h"
      23             : #include "xfs_da_btree.h"
      24             : #include "xfs_parent_utils.h"
      25             : #include "xfs_health.h"
      26             : 
      27             : struct xfs_getparent_ctx {
      28             :         struct xfs_attr_list_context    context;
      29             :         struct xfs_parent_name_irec     pptr_irec;
      30             :         struct xfs_getparents           *ppi;
      31             : };
      32             : 
      33             : static inline unsigned int
      34             : xfs_getparents_rec_sizeof(
      35             :         const struct xfs_parent_name_irec       *irec)
      36             : {
      37   215608261 :         return round_up(sizeof(struct xfs_getparents_rec) + irec->p_namelen + 1,
      38             :                         sizeof(uint32_t));
      39             : }
      40             : 
      41             : static void
      42  4610875373 : xfs_getparent_listent(
      43             :         struct xfs_attr_list_context    *context,
      44             :         int                             flags,
      45             :         unsigned char                   *name,
      46             :         int                             namelen,
      47             :         void                            *value,
      48             :         int                             valuelen)
      49             : {
      50  4610875373 :         struct xfs_getparent_ctx        *gp;
      51  4610875373 :         struct xfs_getparents           *ppi;
      52  4610875373 :         struct xfs_getparents_rec       *pptr;
      53  4610875373 :         struct xfs_parent_name_rec      *rec = (void *)name;
      54  4610875373 :         struct xfs_parent_name_irec     *irec;
      55  4610875373 :         struct xfs_mount                *mp = context->dp->i_mount;
      56  4610875373 :         int                             arraytop;
      57             : 
      58  4610875373 :         gp = container_of(context, struct xfs_getparent_ctx, context);
      59  4610875373 :         ppi = gp->ppi;
      60  4610875373 :         irec = &gp->pptr_irec;
      61             : 
      62             :         /* Ignore non-parent xattrs */
      63  4610875373 :         if (!(flags & XFS_ATTR_PARENT))
      64             :                 return;
      65             : 
      66             :         /*
      67             :          * Report corruption for anything that doesn't look like a parent
      68             :          * pointer.  The attr list functions filtered out INCOMPLETE attrs.
      69             :          */
      70   215672933 :         if (XFS_IS_CORRUPT(mp,
      71             :                         !xfs_parent_namecheck(mp, rec, namelen, flags)) ||
      72   215680383 :             XFS_IS_CORRUPT(mp,
      73             :                         !xfs_parent_valuecheck(mp, value, valuelen))) {
      74           0 :                 xfs_inode_mark_sick(context->dp, XFS_SICK_INO_PARENT);
      75           0 :                 context->seen_enough = -EFSCORRUPTED;
      76           0 :                 return;
      77             :         }
      78             : 
      79   215644133 :         xfs_parent_irec_from_disk(&gp->pptr_irec, rec, value, valuelen);
      80             : 
      81             :         /*
      82             :          * We found a parent pointer, but we've filled up the buffer.  Signal
      83             :          * to the caller that we did /not/ reach the end of the parent pointer
      84             :          * recordset.
      85             :          */
      86   215608261 :         arraytop = xfs_getparents_arraytop(ppi, ppi->gp_count + 1);
      87   215608261 :         context->firstu -= xfs_getparents_rec_sizeof(irec);
      88   215608261 :         if (context->firstu < arraytop) {
      89          66 :                 context->seen_enough = 1;
      90          66 :                 return;
      91             :         }
      92             : 
      93   215608195 :         trace_xfs_getparent_listent(context->dp, ppi, irec);
      94             : 
      95             :         /* Format the parent pointer directly into the caller buffer. */
      96   215618156 :         ppi->gp_offsets[ppi->gp_count] = context->firstu;
      97   215618156 :         pptr = xfs_getparents_rec(ppi, ppi->gp_count);
      98   215618156 :         pptr->gpr_ino = irec->p_ino;
      99   215618156 :         pptr->gpr_gen = irec->p_gen;
     100   215618156 :         pptr->gpr_pad = 0;
     101   215618156 :         pptr->gpr_rsvd = 0;
     102             : 
     103   431236312 :         memcpy(pptr->gpr_name, irec->p_name, irec->p_namelen);
     104   215618156 :         pptr->gpr_name[irec->p_namelen] = 0;
     105   215618156 :         ppi->gp_count++;
     106             : }
     107             : 
     108             : /* Retrieve the parent pointers for a given inode. */
     109             : int
     110   258603175 : xfs_getparent_pointers(
     111             :         struct xfs_inode                *ip,
     112             :         struct xfs_getparents           *ppi)
     113             : {
     114   258603175 :         struct xfs_getparent_ctx        *gp;
     115   258603175 :         int                             error;
     116             : 
     117   258603175 :         gp = kzalloc(sizeof(struct xfs_getparent_ctx), GFP_KERNEL);
     118   258595182 :         if (!gp)
     119             :                 return -ENOMEM;
     120   258595182 :         gp->ppi = ppi;
     121   258595182 :         gp->context.dp = ip;
     122   258595182 :         gp->context.resynch = 1;
     123   258595182 :         gp->context.put_listent = xfs_getparent_listent;
     124   258595182 :         gp->context.bufsize = round_down(ppi->gp_bufsize, sizeof(uint32_t));
     125   258595182 :         gp->context.firstu = gp->context.bufsize;
     126             : 
     127             :         /* Copy the cursor provided by caller */
     128   517190364 :         memcpy(&gp->context.cursor, &ppi->gp_cursor,
     129             :                         sizeof(struct xfs_attrlist_cursor));
     130   258595182 :         ppi->gp_count = 0;
     131             : 
     132   258595182 :         trace_xfs_getparent_pointers(ip, ppi, &gp->context.cursor);
     133             : 
     134   258583191 :         error = xfs_attr_list(&gp->context);
     135   258520660 :         if (error)
     136           0 :                 goto out_free;
     137   258520660 :         if (gp->context.seen_enough < 0) {
     138           0 :                 error = gp->context.seen_enough;
     139           0 :                 goto out_free;
     140             :         }
     141             : 
     142             :         /* Is this the root directory? */
     143   258520660 :         if (ip->i_ino == ip->i_mount->m_sb.sb_rootino)
     144    43850257 :                 ppi->gp_flags |= XFS_GETPARENTS_OFLAG_ROOT;
     145             : 
     146             :         /*
     147             :          * If we did not run out of buffer space, then we reached the end of
     148             :          * the pptr recordset, so set the DONE flag.
     149             :          */
     150   258520660 :         if (gp->context.seen_enough == 0)
     151   258523495 :                 ppi->gp_flags |= XFS_GETPARENTS_OFLAG_DONE;
     152             : 
     153             :         /* Update the caller with the current cursor position */
     154   517041320 :         memcpy(&ppi->gp_cursor, &gp->context.cursor,
     155             :                         sizeof(struct xfs_attrlist_cursor));
     156   258520660 : out_free:
     157   258520660 :         kfree(gp);
     158   258520660 :         return error;
     159             : }

Generated by: LCOV version 1.14