xfs: remove a pointless comment duplicated above all xfs_item_ops instances
[linux-2.6-block.git] / fs / xfs / xfs_refcount_item.c
CommitLineData
0b61f8a4 1// SPDX-License-Identifier: GPL-2.0+
baf4bcac
DW
2/*
3 * Copyright (C) 2016 Oracle. All Rights Reserved.
baf4bcac 4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
baf4bcac
DW
5 */
6#include "xfs.h"
7#include "xfs_fs.h"
8#include "xfs_format.h"
9#include "xfs_log_format.h"
10#include "xfs_trans_resv.h"
f997ee21 11#include "xfs_bit.h"
b31c2bdc 12#include "xfs_shared.h"
baf4bcac 13#include "xfs_mount.h"
f997ee21 14#include "xfs_defer.h"
baf4bcac
DW
15#include "xfs_trans.h"
16#include "xfs_trans_priv.h"
17#include "xfs_buf_item.h"
18#include "xfs_refcount_item.h"
19#include "xfs_log.h"
f997ee21 20#include "xfs_refcount.h"
baf4bcac
DW
21
22
23kmem_zone_t *xfs_cui_zone;
24kmem_zone_t *xfs_cud_zone;
25
26static inline struct xfs_cui_log_item *CUI_ITEM(struct xfs_log_item *lip)
27{
28 return container_of(lip, struct xfs_cui_log_item, cui_item);
29}
30
31void
32xfs_cui_item_free(
33 struct xfs_cui_log_item *cuip)
34{
35 if (cuip->cui_format.cui_nextents > XFS_CUI_MAX_FAST_EXTENTS)
36 kmem_free(cuip);
37 else
38 kmem_zone_free(xfs_cui_zone, cuip);
39}
40
0612d116
DC
41/*
42 * Freeing the CUI requires that we remove it from the AIL if it has already
43 * been placed there. However, the CUI may not yet have been placed in the AIL
44 * when called by xfs_cui_release() from CUD processing due to the ordering of
45 * committed vs unpin operations in bulk insert operations. Hence the reference
46 * count to ensure only the last caller frees the CUI.
47 */
48void
49xfs_cui_release(
50 struct xfs_cui_log_item *cuip)
51{
52 ASSERT(atomic_read(&cuip->cui_refcount) > 0);
53 if (atomic_dec_and_test(&cuip->cui_refcount)) {
54 xfs_trans_ail_remove(&cuip->cui_item, SHUTDOWN_LOG_IO_ERROR);
55 xfs_cui_item_free(cuip);
56 }
57}
58
59
baf4bcac
DW
60STATIC void
61xfs_cui_item_size(
62 struct xfs_log_item *lip,
63 int *nvecs,
64 int *nbytes)
65{
66 struct xfs_cui_log_item *cuip = CUI_ITEM(lip);
67
68 *nvecs += 1;
69 *nbytes += xfs_cui_log_format_sizeof(cuip->cui_format.cui_nextents);
70}
71
72/*
73 * This is called to fill in the vector of log iovecs for the
74 * given cui log item. We use only 1 iovec, and we point that
75 * at the cui_log_format structure embedded in the cui item.
76 * It is at this point that we assert that all of the extent
77 * slots in the cui item have been filled.
78 */
79STATIC void
80xfs_cui_item_format(
81 struct xfs_log_item *lip,
82 struct xfs_log_vec *lv)
83{
84 struct xfs_cui_log_item *cuip = CUI_ITEM(lip);
85 struct xfs_log_iovec *vecp = NULL;
86
87 ASSERT(atomic_read(&cuip->cui_next_extent) ==
88 cuip->cui_format.cui_nextents);
89
90 cuip->cui_format.cui_type = XFS_LI_CUI;
91 cuip->cui_format.cui_size = 1;
92
93 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_CUI_FORMAT, &cuip->cui_format,
94 xfs_cui_log_format_sizeof(cuip->cui_format.cui_nextents));
95}
96
baf4bcac
DW
97/*
98 * The unpin operation is the last place an CUI is manipulated in the log. It is
99 * either inserted in the AIL or aborted in the event of a log I/O error. In
100 * either case, the CUI transaction has been successfully committed to make it
101 * this far. Therefore, we expect whoever committed the CUI to either construct
102 * and commit the CUD or drop the CUD's reference in the event of error. Simply
103 * drop the log's CUI reference now that the log is done with it.
104 */
105STATIC void
106xfs_cui_item_unpin(
107 struct xfs_log_item *lip,
108 int remove)
109{
110 struct xfs_cui_log_item *cuip = CUI_ITEM(lip);
111
112 xfs_cui_release(cuip);
113}
114
baf4bcac
DW
115/*
116 * The CUI has been either committed or aborted if the transaction has been
117 * cancelled. If the transaction was cancelled, an CUD isn't going to be
118 * constructed and thus we free the CUI here directly.
119 */
120STATIC void
ddf92053 121xfs_cui_item_release(
baf4bcac
DW
122 struct xfs_log_item *lip)
123{
ddf92053 124 xfs_cui_release(CUI_ITEM(lip));
baf4bcac
DW
125}
126
baf4bcac
DW
127static const struct xfs_item_ops xfs_cui_item_ops = {
128 .iop_size = xfs_cui_item_size,
129 .iop_format = xfs_cui_item_format,
baf4bcac 130 .iop_unpin = xfs_cui_item_unpin,
ddf92053 131 .iop_release = xfs_cui_item_release,
baf4bcac
DW
132};
133
134/*
135 * Allocate and initialize an cui item with the given number of extents.
136 */
137struct xfs_cui_log_item *
138xfs_cui_init(
139 struct xfs_mount *mp,
140 uint nextents)
141
142{
143 struct xfs_cui_log_item *cuip;
144
145 ASSERT(nextents > 0);
146 if (nextents > XFS_CUI_MAX_FAST_EXTENTS)
147 cuip = kmem_zalloc(xfs_cui_log_item_sizeof(nextents),
148 KM_SLEEP);
149 else
150 cuip = kmem_zone_zalloc(xfs_cui_zone, KM_SLEEP);
151
152 xfs_log_item_init(mp, &cuip->cui_item, XFS_LI_CUI, &xfs_cui_item_ops);
153 cuip->cui_format.cui_nextents = nextents;
154 cuip->cui_format.cui_id = (uintptr_t)(void *)cuip;
155 atomic_set(&cuip->cui_next_extent, 0);
156 atomic_set(&cuip->cui_refcount, 2);
157
158 return cuip;
159}
160
baf4bcac
DW
161static inline struct xfs_cud_log_item *CUD_ITEM(struct xfs_log_item *lip)
162{
163 return container_of(lip, struct xfs_cud_log_item, cud_item);
164}
165
166STATIC void
167xfs_cud_item_size(
168 struct xfs_log_item *lip,
169 int *nvecs,
170 int *nbytes)
171{
172 *nvecs += 1;
173 *nbytes += sizeof(struct xfs_cud_log_format);
174}
175
176/*
177 * This is called to fill in the vector of log iovecs for the
178 * given cud log item. We use only 1 iovec, and we point that
179 * at the cud_log_format structure embedded in the cud item.
180 * It is at this point that we assert that all of the extent
181 * slots in the cud item have been filled.
182 */
183STATIC void
184xfs_cud_item_format(
185 struct xfs_log_item *lip,
186 struct xfs_log_vec *lv)
187{
188 struct xfs_cud_log_item *cudp = CUD_ITEM(lip);
189 struct xfs_log_iovec *vecp = NULL;
190
191 cudp->cud_format.cud_type = XFS_LI_CUD;
192 cudp->cud_format.cud_size = 1;
193
194 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_CUD_FORMAT, &cudp->cud_format,
195 sizeof(struct xfs_cud_log_format));
196}
197
baf4bcac
DW
198/*
199 * The CUD is either committed or aborted if the transaction is cancelled. If
200 * the transaction is cancelled, drop our reference to the CUI and free the
201 * CUD.
202 */
203STATIC void
ddf92053 204xfs_cud_item_release(
baf4bcac
DW
205 struct xfs_log_item *lip)
206{
207 struct xfs_cud_log_item *cudp = CUD_ITEM(lip);
208
ddf92053
CH
209 xfs_cui_release(cudp->cud_cuip);
210 kmem_zone_free(xfs_cud_zone, cudp);
baf4bcac
DW
211}
212
baf4bcac 213static const struct xfs_item_ops xfs_cud_item_ops = {
9ce632a2 214 .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED,
baf4bcac
DW
215 .iop_size = xfs_cud_item_size,
216 .iop_format = xfs_cud_item_format,
ddf92053 217 .iop_release = xfs_cud_item_release,
baf4bcac
DW
218};
219
220/*
221 * Allocate and initialize an cud item with the given number of extents.
222 */
223struct xfs_cud_log_item *
224xfs_cud_init(
225 struct xfs_mount *mp,
226 struct xfs_cui_log_item *cuip)
227
228{
229 struct xfs_cud_log_item *cudp;
230
231 cudp = kmem_zone_zalloc(xfs_cud_zone, KM_SLEEP);
232 xfs_log_item_init(mp, &cudp->cud_item, XFS_LI_CUD, &xfs_cud_item_ops);
233 cudp->cud_cuip = cuip;
234 cudp->cud_format.cud_cui_id = cuip->cui_format.cui_id;
235
236 return cudp;
237}
f997ee21
DW
238
239/*
240 * Process a refcount update intent item that was recovered from the log.
241 * We need to update the refcountbt.
242 */
243int
244xfs_cui_recover(
fbfa977d
BF
245 struct xfs_trans *parent_tp,
246 struct xfs_cui_log_item *cuip)
f997ee21
DW
247{
248 int i;
249 int error = 0;
33ba6129 250 unsigned int refc_type;
f997ee21
DW
251 struct xfs_phys_extent *refc;
252 xfs_fsblock_t startblock_fsb;
253 bool op_ok;
33ba6129
DW
254 struct xfs_cud_log_item *cudp;
255 struct xfs_trans *tp;
256 struct xfs_btree_cur *rcur = NULL;
257 enum xfs_refcount_intent_type type;
33ba6129
DW
258 xfs_fsblock_t new_fsb;
259 xfs_extlen_t new_len;
260 struct xfs_bmbt_irec irec;
33ba6129 261 bool requeue_only = false;
fbfa977d 262 struct xfs_mount *mp = parent_tp->t_mountp;
f997ee21
DW
263
264 ASSERT(!test_bit(XFS_CUI_RECOVERED, &cuip->cui_flags));
265
266 /*
267 * First check the validity of the extents described by the
268 * CUI. If any are bad, then assume that all are bad and
269 * just toss the CUI.
270 */
271 for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
272 refc = &cuip->cui_format.cui_extents[i];
273 startblock_fsb = XFS_BB_TO_FSB(mp,
274 XFS_FSB_TO_DADDR(mp, refc->pe_startblock));
275 switch (refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) {
276 case XFS_REFCOUNT_INCREASE:
277 case XFS_REFCOUNT_DECREASE:
278 case XFS_REFCOUNT_ALLOC_COW:
279 case XFS_REFCOUNT_FREE_COW:
280 op_ok = true;
281 break;
282 default:
283 op_ok = false;
284 break;
285 }
286 if (!op_ok || startblock_fsb == 0 ||
287 refc->pe_len == 0 ||
288 startblock_fsb >= mp->m_sb.sb_dblocks ||
289 refc->pe_len >= mp->m_sb.sb_agblocks ||
290 (refc->pe_flags & ~XFS_REFCOUNT_EXTENT_FLAGS)) {
291 /*
292 * This will pull the CUI from the AIL and
293 * free the memory associated with it.
294 */
295 set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
296 xfs_cui_release(cuip);
297 return -EIO;
298 }
299 }
300
33ba6129
DW
301 /*
302 * Under normal operation, refcount updates are deferred, so we
303 * wouldn't be adding them directly to a transaction. All
304 * refcount updates manage reservation usage internally and
305 * dynamically by deferring work that won't fit in the
306 * transaction. Normally, any work that needs to be deferred
307 * gets attached to the same defer_ops that scheduled the
308 * refcount update. However, we're in log recovery here, so we
b31c2bdc
DW
309 * we use the passed in defer_ops and to finish up any work that
310 * doesn't fit. We need to reserve enough blocks to handle a
311 * full btree split on either end of the refcount range.
33ba6129 312 */
b31c2bdc
DW
313 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
314 mp->m_refc_maxlevels * 2, 0, XFS_TRANS_RESERVE, &tp);
33ba6129
DW
315 if (error)
316 return error;
91ef75b6
BF
317 /*
318 * Recovery stashes all deferred ops during intent processing and
319 * finishes them on completion. Transfer current dfops state to this
320 * transaction and transfer the result back before we return.
321 */
ce356d64 322 xfs_defer_move(tp, parent_tp);
33ba6129
DW
323 cudp = xfs_trans_get_cud(tp, cuip);
324
33ba6129
DW
325 for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
326 refc = &cuip->cui_format.cui_extents[i];
327 refc_type = refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK;
328 switch (refc_type) {
329 case XFS_REFCOUNT_INCREASE:
330 case XFS_REFCOUNT_DECREASE:
331 case XFS_REFCOUNT_ALLOC_COW:
332 case XFS_REFCOUNT_FREE_COW:
333 type = refc_type;
334 break;
335 default:
336 error = -EFSCORRUPTED;
337 goto abort_error;
338 }
339 if (requeue_only) {
340 new_fsb = refc->pe_startblock;
341 new_len = refc->pe_len;
342 } else
343 error = xfs_trans_log_finish_refcount_update(tp, cudp,
7dbddbac
BF
344 type, refc->pe_startblock, refc->pe_len,
345 &new_fsb, &new_len, &rcur);
33ba6129
DW
346 if (error)
347 goto abort_error;
348
349 /* Requeue what we didn't finish. */
350 if (new_len > 0) {
351 irec.br_startblock = new_fsb;
352 irec.br_blockcount = new_len;
353 switch (type) {
354 case XFS_REFCOUNT_INCREASE:
0f37d178 355 error = xfs_refcount_increase_extent(tp, &irec);
33ba6129
DW
356 break;
357 case XFS_REFCOUNT_DECREASE:
0f37d178 358 error = xfs_refcount_decrease_extent(tp, &irec);
33ba6129 359 break;
174edb0e 360 case XFS_REFCOUNT_ALLOC_COW:
0f37d178 361 error = xfs_refcount_alloc_cow_extent(tp,
174edb0e
DW
362 irec.br_startblock,
363 irec.br_blockcount);
364 break;
365 case XFS_REFCOUNT_FREE_COW:
0f37d178 366 error = xfs_refcount_free_cow_extent(tp,
174edb0e
DW
367 irec.br_startblock,
368 irec.br_blockcount);
369 break;
33ba6129
DW
370 default:
371 ASSERT(0);
372 }
373 if (error)
374 goto abort_error;
375 requeue_only = true;
376 }
377 }
378
379 xfs_refcount_finish_one_cleanup(tp, rcur, error);
f997ee21 380 set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
ce356d64 381 xfs_defer_move(parent_tp, tp);
33ba6129
DW
382 error = xfs_trans_commit(tp);
383 return error;
384
385abort_error:
386 xfs_refcount_finish_one_cleanup(tp, rcur, error);
ce356d64 387 xfs_defer_move(parent_tp, tp);
33ba6129 388 xfs_trans_cancel(tp);
f997ee21
DW
389 return error;
390}