Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (c) 2020-2022, Red Hat, Inc.
4 : * All Rights Reserved.
5 : */
6 : #include "xfs.h"
7 : #include "xfs_fs.h"
8 : #include "xfs_shared.h"
9 : #include "xfs_format.h"
10 : #include "xfs_log_format.h"
11 : #include "xfs_trans_resv.h"
12 : #include "xfs_mount.h"
13 : #include "xfs_inode.h"
14 : #include "xfs_trans.h"
15 : #include "xfs_trans_priv.h"
16 : #include "xfs_ag.h"
17 : #include "xfs_iunlink_item.h"
18 : #include "xfs_trace.h"
19 : #include "xfs_error.h"
20 :
21 : struct kmem_cache *xfs_iunlink_cache;
22 :
23 : static inline struct xfs_iunlink_item *IUL_ITEM(struct xfs_log_item *lip)
24 : {
25 : return container_of(lip, struct xfs_iunlink_item, item);
26 : }
27 :
28 : static void
29 72954963 : xfs_iunlink_item_release(
30 : struct xfs_log_item *lip)
31 : {
32 72954963 : struct xfs_iunlink_item *iup = IUL_ITEM(lip);
33 :
34 72954963 : xfs_perag_put(iup->pag);
35 73322317 : kmem_cache_free(xfs_iunlink_cache, IUL_ITEM(lip));
36 73331343 : }
37 :
38 :
39 : static uint64_t
40 103189679 : xfs_iunlink_item_sort(
41 : struct xfs_log_item *lip)
42 : {
43 103189679 : return IUL_ITEM(lip)->ip->i_ino;
44 : }
45 :
46 : /*
47 : * Look up the inode cluster buffer and log the on-disk unlinked inode change
48 : * we need to make.
49 : */
50 : static int
51 72861372 : xfs_iunlink_log_dinode(
52 : struct xfs_trans *tp,
53 : struct xfs_iunlink_item *iup)
54 : {
55 72861372 : struct xfs_mount *mp = tp->t_mountp;
56 72861372 : struct xfs_inode *ip = iup->ip;
57 72861372 : struct xfs_dinode *dip;
58 72861372 : struct xfs_buf *ibp;
59 72861372 : int offset;
60 72861372 : int error;
61 :
62 72861372 : error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &ibp);
63 73261668 : if (error)
64 : return error;
65 : /*
66 : * Don't log the unlinked field on stale buffers as this may be the
67 : * transaction that frees the inode cluster and relogging the buffer
68 : * here will incorrectly remove the stale state.
69 : */
70 73261668 : if (ibp->b_flags & XBF_STALE)
71 148079 : goto out;
72 :
73 73113589 : dip = xfs_buf_offset(ibp, ip->i_imap.im_boffset);
74 :
75 : /* Make sure the old pointer isn't garbage. */
76 72904202 : if (be32_to_cpu(dip->di_next_unlinked) != iup->old_agino) {
77 0 : xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
78 0 : sizeof(*dip), __this_address);
79 0 : error = -EFSCORRUPTED;
80 0 : goto out;
81 : }
82 :
83 145808404 : trace_xfs_iunlink_update_dinode(mp, iup->pag->pag_agno,
84 72904202 : XFS_INO_TO_AGINO(mp, ip->i_ino),
85 : be32_to_cpu(dip->di_next_unlinked), iup->next_agino);
86 :
87 72930756 : dip->di_next_unlinked = cpu_to_be32(iup->next_agino);
88 72930756 : offset = ip->i_imap.im_boffset +
89 : offsetof(struct xfs_dinode, di_next_unlinked);
90 :
91 72930756 : xfs_dinode_calc_crc(mp, dip);
92 72547459 : xfs_trans_inode_buf(tp, ibp);
93 72747019 : xfs_trans_log_buf(tp, ibp, offset, offset + sizeof(xfs_agino_t) - 1);
94 72747019 : return 0;
95 148079 : out:
96 148079 : xfs_trans_brelse(tp, ibp);
97 148079 : return error;
98 : }
99 :
100 : /*
101 : * On precommit, we grab the inode cluster buffer for the inode number we were
102 : * passed, then update the next unlinked field for that inode in the buffer and
103 : * log the buffer. This ensures that the inode cluster buffer was logged in the
104 : * correct order w.r.t. other inode cluster buffers. We can then remove the
105 : * iunlink item from the transaction and release it as it is has now served it's
106 : * purpose.
107 : */
108 : static int
109 73397557 : xfs_iunlink_item_precommit(
110 : struct xfs_trans *tp,
111 : struct xfs_log_item *lip)
112 : {
113 73397557 : struct xfs_iunlink_item *iup = IUL_ITEM(lip);
114 73397557 : int error;
115 :
116 73397557 : error = xfs_iunlink_log_dinode(tp, iup);
117 73264543 : list_del(&lip->li_trans);
118 72874156 : xfs_iunlink_item_release(lip);
119 73257077 : return error;
120 : }
121 :
122 : static const struct xfs_item_ops xfs_iunlink_item_ops = {
123 : .iop_release = xfs_iunlink_item_release,
124 : .iop_sort = xfs_iunlink_item_sort,
125 : .iop_precommit = xfs_iunlink_item_precommit,
126 : };
127 :
128 :
129 : /*
130 : * Initialize the inode log item for a newly allocated (in-core) inode.
131 : *
132 : * Inode extents can only reside within an AG. Hence specify the starting
133 : * block for the inode chunk by offset within an AG as well as the
134 : * length of the allocated extent.
135 : *
136 : * This joins the item to the transaction and marks it dirty so
137 : * that we don't need a separate call to do this, nor does the
138 : * caller need to know anything about the iunlink item.
139 : */
140 : int
141 137232467 : xfs_iunlink_log_inode(
142 : struct xfs_trans *tp,
143 : struct xfs_inode *ip,
144 : struct xfs_perag *pag,
145 : xfs_agino_t next_agino)
146 : {
147 137232467 : struct xfs_mount *mp = tp->t_mountp;
148 137232467 : struct xfs_iunlink_item *iup;
149 :
150 179466679 : ASSERT(xfs_verify_agino_or_null(pag, next_agino));
151 179880847 : ASSERT(xfs_verify_agino_or_null(pag, ip->i_next_unlinked));
152 :
153 : /*
154 : * Since we're updating a linked list, we should never find that the
155 : * current pointer is the same as the new value, unless we're
156 : * terminating the list.
157 : */
158 137232467 : if (ip->i_next_unlinked == next_agino) {
159 64297899 : if (next_agino != NULLAGINO)
160 : return -EFSCORRUPTED;
161 64297899 : return 0;
162 : }
163 :
164 72934568 : iup = kmem_cache_zalloc(xfs_iunlink_cache, GFP_KERNEL | __GFP_NOFAIL);
165 73285957 : xfs_log_item_init(mp, &iup->item, XFS_LI_IUNLINK,
166 : &xfs_iunlink_item_ops);
167 :
168 73092904 : iup->ip = ip;
169 73092904 : iup->next_agino = next_agino;
170 73092904 : iup->old_agino = ip->i_next_unlinked;
171 73092904 : iup->pag = xfs_perag_hold(pag);
172 :
173 73322760 : xfs_trans_add_item(tp, &iup->item);
174 73129270 : tp->t_flags |= XFS_TRANS_DIRTY;
175 73129270 : set_bit(XFS_LI_DIRTY, &iup->item.li_flags);
176 73129270 : return 0;
177 : }
178 :
|