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-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 56 62 90.3 %
Date: 2023-07-31 20:08:12 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   430802212 :         return round_up(sizeof(struct xfs_getparents_rec) + irec->p_namelen + 1,
      38             :                         sizeof(uint32_t));
      39             : }
      40             : 
      41             : static void
      42  4837895625 : 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  4837895625 :         struct xfs_getparent_ctx        *gp;
      51  4837895625 :         struct xfs_getparents           *ppi;
      52  4837895625 :         struct xfs_getparents_rec       *pptr;
      53  4837895625 :         struct xfs_parent_name_rec      *rec = (void *)name;
      54  4837895625 :         struct xfs_parent_name_irec     *irec;
      55  4837895625 :         struct xfs_mount                *mp = context->dp->i_mount;
      56  4837895625 :         int                             arraytop;
      57             : 
      58  4837895625 :         gp = container_of(context, struct xfs_getparent_ctx, context);
      59  4837895625 :         ppi = gp->ppi;
      60  4837895625 :         irec = &gp->pptr_irec;
      61             : 
      62             :         /* Ignore non-parent xattrs */
      63  4837895625 :         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   430976953 :         if (XFS_IS_CORRUPT(mp,
      71             :                         !xfs_parent_namecheck(mp, rec, namelen, flags)) ||
      72   431051668 :             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   430684686 :         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   430802212 :         arraytop = xfs_getparents_arraytop(ppi, ppi->gp_count + 1);
      87   430802212 :         context->firstu -= xfs_getparents_rec_sizeof(irec);
      88   430802212 :         if (context->firstu < arraytop) {
      89          48 :                 context->seen_enough = 1;
      90          48 :                 return;
      91             :         }
      92             : 
      93   430802164 :         trace_xfs_getparent_listent(context->dp, ppi, irec);
      94             : 
      95             :         /* Format the parent pointer directly into the caller buffer. */
      96   430433891 :         ppi->gp_offsets[ppi->gp_count] = context->firstu;
      97   430433891 :         pptr = xfs_getparents_rec(ppi, ppi->gp_count);
      98   430433891 :         pptr->gpr_ino = irec->p_ino;
      99   430433891 :         pptr->gpr_gen = irec->p_gen;
     100   430433891 :         pptr->gpr_pad = 0;
     101   430433891 :         pptr->gpr_rsvd = 0;
     102             : 
     103   860867782 :         memcpy(pptr->gpr_name, irec->p_name, irec->p_namelen);
     104   430433891 :         pptr->gpr_name[irec->p_namelen] = 0;
     105   430433891 :         ppi->gp_count++;
     106             : }
     107             : 
     108             : /* Retrieve the parent pointers for a given inode. */
     109             : int
     110   508986025 : xfs_getparent_pointers(
     111             :         struct xfs_inode                *ip,
     112             :         struct xfs_getparents           *ppi)
     113             : {
     114   508986025 :         struct xfs_getparent_ctx        *gp;
     115   508986025 :         int                             error;
     116             : 
     117   508986025 :         gp = kzalloc(sizeof(struct xfs_getparent_ctx), GFP_KERNEL);
     118   508773556 :         if (!gp)
     119             :                 return -ENOMEM;
     120   508773556 :         gp->ppi = ppi;
     121   508773556 :         gp->context.dp = ip;
     122   508773556 :         gp->context.resynch = 1;
     123   508773556 :         gp->context.put_listent = xfs_getparent_listent;
     124   508773556 :         gp->context.bufsize = round_down(ppi->gp_bufsize, sizeof(uint32_t));
     125   508773556 :         gp->context.firstu = gp->context.bufsize;
     126             : 
     127             :         /* Copy the cursor provided by caller */
     128  1017547112 :         memcpy(&gp->context.cursor, &ppi->gp_cursor,
     129             :                         sizeof(struct xfs_attrlist_cursor));
     130   508773556 :         ppi->gp_count = 0;
     131             : 
     132   508773556 :         trace_xfs_getparent_pointers(ip, ppi, &gp->context.cursor);
     133             : 
     134   508698661 :         error = xfs_attr_list(&gp->context);
     135   508213146 :         if (error)
     136           0 :                 goto out_free;
     137   508213146 :         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   508213146 :         if (ip->i_ino == ip->i_mount->m_sb.sb_rootino)
     144    78948322 :                 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   508213146 :         if (gp->context.seen_enough == 0)
     151   508240071 :                 ppi->gp_flags |= XFS_GETPARENTS_OFLAG_DONE;
     152             : 
     153             :         /* Update the caller with the current cursor position */
     154  1016426292 :         memcpy(&ppi->gp_cursor, &gp->context.cursor,
     155             :                         sizeof(struct xfs_attrlist_cursor));
     156   508213146 : out_free:
     157   508213146 :         kfree(gp);
     158   508213146 :         return error;
     159             : }

Generated by: LCOV version 1.14