1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020-2022, Red Hat, Inc.
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"
17 #include "xfs_iunlink_item.h"
18 #include "xfs_trace.h"
19 #include "xfs_error.h"
21 struct kmem_cache
*xfs_iunlink_cache
;
23 static inline struct xfs_iunlink_item
*IUL_ITEM(struct xfs_log_item
*lip
)
25 return container_of(lip
, struct xfs_iunlink_item
, item
);
29 xfs_iunlink_item_release(
30 struct xfs_log_item
*lip
)
32 struct xfs_iunlink_item
*iup
= IUL_ITEM(lip
);
34 xfs_perag_put(iup
->pag
);
35 kmem_cache_free(xfs_iunlink_cache
, IUL_ITEM(lip
));
40 xfs_iunlink_item_sort(
41 struct xfs_log_item
*lip
)
43 return IUL_ITEM(lip
)->ip
->i_ino
;
47 * Look up the inode cluster buffer and log the on-disk unlinked inode change
51 xfs_iunlink_log_dinode(
53 struct xfs_iunlink_item
*iup
)
55 struct xfs_inode
*ip
= iup
->ip
;
56 struct xfs_dinode
*dip
;
62 error
= xfs_imap_to_bp(tp
->t_mountp
, tp
, &ip
->i_imap
, &ibp
);
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.
70 if (ibp
->b_flags
& XBF_STALE
)
73 dip
= xfs_buf_offset(ibp
, ip
->i_imap
.im_boffset
);
75 /* Make sure the old pointer isn't garbage. */
76 old_ptr
= be32_to_cpu(dip
->di_next_unlinked
);
77 if (old_ptr
!= iup
->old_agino
) {
78 xfs_inode_verifier_error(ip
, -EFSCORRUPTED
, __func__
, dip
,
79 sizeof(*dip
), __this_address
);
80 error
= -EFSCORRUPTED
;
84 trace_xfs_iunlink_update_dinode(iup
, old_ptr
);
86 dip
->di_next_unlinked
= cpu_to_be32(iup
->next_agino
);
87 offset
= ip
->i_imap
.im_boffset
+
88 offsetof(struct xfs_dinode
, di_next_unlinked
);
90 xfs_dinode_calc_crc(tp
->t_mountp
, dip
);
91 xfs_trans_inode_buf(tp
, ibp
);
92 xfs_trans_log_buf(tp
, ibp
, offset
, offset
+ sizeof(xfs_agino_t
) - 1);
95 xfs_trans_brelse(tp
, ibp
);
100 * On precommit, we grab the inode cluster buffer for the inode number we were
101 * passed, then update the next unlinked field for that inode in the buffer and
102 * log the buffer. This ensures that the inode cluster buffer was logged in the
103 * correct order w.r.t. other inode cluster buffers. We can then remove the
104 * iunlink item from the transaction and release it as it is has now served it's
108 xfs_iunlink_item_precommit(
109 struct xfs_trans
*tp
,
110 struct xfs_log_item
*lip
)
112 struct xfs_iunlink_item
*iup
= IUL_ITEM(lip
);
115 error
= xfs_iunlink_log_dinode(tp
, iup
);
116 list_del(&lip
->li_trans
);
117 xfs_iunlink_item_release(lip
);
121 static const struct xfs_item_ops xfs_iunlink_item_ops
= {
122 .iop_release
= xfs_iunlink_item_release
,
123 .iop_sort
= xfs_iunlink_item_sort
,
124 .iop_precommit
= xfs_iunlink_item_precommit
,
129 * Initialize the inode log item for a newly allocated (in-core) inode.
131 * Inode extents can only reside within an AG. Hence specify the starting
132 * block for the inode chunk by offset within an AG as well as the
133 * length of the allocated extent.
135 * This joins the item to the transaction and marks it dirty so
136 * that we don't need a separate call to do this, nor does the
137 * caller need to know anything about the iunlink item.
140 xfs_iunlink_log_inode(
141 struct xfs_trans
*tp
,
142 struct xfs_inode
*ip
,
143 struct xfs_perag
*pag
,
144 xfs_agino_t next_agino
)
146 struct xfs_mount
*mp
= tp
->t_mountp
;
147 struct xfs_iunlink_item
*iup
;
149 ASSERT(xfs_verify_agino_or_null(pag
, next_agino
));
150 ASSERT(xfs_verify_agino_or_null(pag
, ip
->i_next_unlinked
));
153 * Since we're updating a linked list, we should never find that the
154 * current pointer is the same as the new value, unless we're
155 * terminating the list.
157 if (ip
->i_next_unlinked
== next_agino
) {
158 if (next_agino
!= NULLAGINO
)
159 return -EFSCORRUPTED
;
163 iup
= kmem_cache_zalloc(xfs_iunlink_cache
, GFP_KERNEL
| __GFP_NOFAIL
);
164 xfs_log_item_init(mp
, &iup
->item
, XFS_LI_IUNLINK
,
165 &xfs_iunlink_item_ops
);
168 iup
->next_agino
= next_agino
;
169 iup
->old_agino
= ip
->i_next_unlinked
;
170 iup
->pag
= xfs_perag_hold(pag
);
172 xfs_trans_add_item(tp
, &iup
->item
);
173 tp
->t_flags
|= XFS_TRANS_DIRTY
;
174 set_bit(XFS_LI_DIRTY
, &iup
->item
.li_flags
);