Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2020-2022, Red Hat, Inc.
0004  * All Rights Reserved.
0005  */
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_trans.h"
0015 #include "xfs_trans_priv.h"
0016 #include "xfs_ag.h"
0017 #include "xfs_iunlink_item.h"
0018 #include "xfs_trace.h"
0019 #include "xfs_error.h"
0020 
0021 struct kmem_cache   *xfs_iunlink_cache;
0022 
0023 static inline struct xfs_iunlink_item *IUL_ITEM(struct xfs_log_item *lip)
0024 {
0025     return container_of(lip, struct xfs_iunlink_item, item);
0026 }
0027 
0028 static void
0029 xfs_iunlink_item_release(
0030     struct xfs_log_item *lip)
0031 {
0032     struct xfs_iunlink_item *iup = IUL_ITEM(lip);
0033 
0034     xfs_perag_put(iup->pag);
0035     kmem_cache_free(xfs_iunlink_cache, IUL_ITEM(lip));
0036 }
0037 
0038 
0039 static uint64_t
0040 xfs_iunlink_item_sort(
0041     struct xfs_log_item *lip)
0042 {
0043     return IUL_ITEM(lip)->ip->i_ino;
0044 }
0045 
0046 /*
0047  * Look up the inode cluster buffer and log the on-disk unlinked inode change
0048  * we need to make.
0049  */
0050 static int
0051 xfs_iunlink_log_dinode(
0052     struct xfs_trans    *tp,
0053     struct xfs_iunlink_item *iup)
0054 {
0055     struct xfs_mount    *mp = tp->t_mountp;
0056     struct xfs_inode    *ip = iup->ip;
0057     struct xfs_dinode   *dip;
0058     struct xfs_buf      *ibp;
0059     int         offset;
0060     int         error;
0061 
0062     error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &ibp);
0063     if (error)
0064         return error;
0065     /*
0066      * Don't log the unlinked field on stale buffers as this may be the
0067      * transaction that frees the inode cluster and relogging the buffer
0068      * here will incorrectly remove the stale state.
0069      */
0070     if (ibp->b_flags & XBF_STALE)
0071         goto out;
0072 
0073     dip = xfs_buf_offset(ibp, ip->i_imap.im_boffset);
0074 
0075     /* Make sure the old pointer isn't garbage. */
0076     if (be32_to_cpu(dip->di_next_unlinked) != iup->old_agino) {
0077         xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
0078                 sizeof(*dip), __this_address);
0079         error = -EFSCORRUPTED;
0080         goto out;
0081     }
0082 
0083     trace_xfs_iunlink_update_dinode(mp, iup->pag->pag_agno,
0084             XFS_INO_TO_AGINO(mp, ip->i_ino),
0085             be32_to_cpu(dip->di_next_unlinked), iup->next_agino);
0086 
0087     dip->di_next_unlinked = cpu_to_be32(iup->next_agino);
0088     offset = ip->i_imap.im_boffset +
0089             offsetof(struct xfs_dinode, di_next_unlinked);
0090 
0091     xfs_dinode_calc_crc(mp, dip);
0092     xfs_trans_inode_buf(tp, ibp);
0093     xfs_trans_log_buf(tp, ibp, offset, offset + sizeof(xfs_agino_t) - 1);
0094     return 0;
0095 out:
0096     xfs_trans_brelse(tp, ibp);
0097     return error;
0098 }
0099 
0100 /*
0101  * On precommit, we grab the inode cluster buffer for the inode number we were
0102  * passed, then update the next unlinked field for that inode in the buffer and
0103  * log the buffer. This ensures that the inode cluster buffer was logged in the
0104  * correct order w.r.t. other inode cluster buffers. We can then remove the
0105  * iunlink item from the transaction and release it as it is has now served it's
0106  * purpose.
0107  */
0108 static int
0109 xfs_iunlink_item_precommit(
0110     struct xfs_trans    *tp,
0111     struct xfs_log_item *lip)
0112 {
0113     struct xfs_iunlink_item *iup = IUL_ITEM(lip);
0114     int         error;
0115 
0116     error = xfs_iunlink_log_dinode(tp, iup);
0117     list_del(&lip->li_trans);
0118     xfs_iunlink_item_release(lip);
0119     return error;
0120 }
0121 
0122 static const struct xfs_item_ops xfs_iunlink_item_ops = {
0123     .iop_release    = xfs_iunlink_item_release,
0124     .iop_sort   = xfs_iunlink_item_sort,
0125     .iop_precommit  = xfs_iunlink_item_precommit,
0126 };
0127 
0128 
0129 /*
0130  * Initialize the inode log item for a newly allocated (in-core) inode.
0131  *
0132  * Inode extents can only reside within an AG. Hence specify the starting
0133  * block for the inode chunk by offset within an AG as well as the
0134  * length of the allocated extent.
0135  *
0136  * This joins the item to the transaction and marks it dirty so
0137  * that we don't need a separate call to do this, nor does the
0138  * caller need to know anything about the iunlink item.
0139  */
0140 int
0141 xfs_iunlink_log_inode(
0142     struct xfs_trans    *tp,
0143     struct xfs_inode    *ip,
0144     struct xfs_perag    *pag,
0145     xfs_agino_t     next_agino)
0146 {
0147     struct xfs_mount    *mp = tp->t_mountp;
0148     struct xfs_iunlink_item *iup;
0149 
0150     ASSERT(xfs_verify_agino_or_null(pag, next_agino));
0151     ASSERT(xfs_verify_agino_or_null(pag, ip->i_next_unlinked));
0152 
0153     /*
0154      * Since we're updating a linked list, we should never find that the
0155      * current pointer is the same as the new value, unless we're
0156      * terminating the list.
0157      */
0158     if (ip->i_next_unlinked == next_agino) {
0159         if (next_agino != NULLAGINO)
0160             return -EFSCORRUPTED;
0161         return 0;
0162     }
0163 
0164     iup = kmem_cache_zalloc(xfs_iunlink_cache, GFP_KERNEL | __GFP_NOFAIL);
0165     xfs_log_item_init(mp, &iup->item, XFS_LI_IUNLINK,
0166               &xfs_iunlink_item_ops);
0167 
0168     iup->ip = ip;
0169     iup->next_agino = next_agino;
0170     iup->old_agino = ip->i_next_unlinked;
0171 
0172     atomic_inc(&pag->pag_ref);
0173     iup->pag = pag;
0174 
0175     xfs_trans_add_item(tp, &iup->item);
0176     tp->t_flags |= XFS_TRANS_DIRTY;
0177     set_bit(XFS_LI_DIRTY, &iup->item.li_flags);
0178     return 0;
0179 }
0180