• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016 Oracle.  All Rights Reserved.
4  * Author: Darrick J. Wong <darrick.wong@oracle.com>
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"
11 #include "xfs_bit.h"
12 #include "xfs_shared.h"
13 #include "xfs_mount.h"
14 #include "xfs_defer.h"
15 #include "xfs_trans.h"
16 #include "xfs_trans_priv.h"
17 #include "xfs_refcount_item.h"
18 #include "xfs_log.h"
19 #include "xfs_refcount.h"
20 #include "xfs_error.h"
21 
22 kmem_zone_t	*xfs_cui_zone;
23 kmem_zone_t	*xfs_cud_zone;
24 
CUI_ITEM(struct xfs_log_item * lip)25 static inline struct xfs_cui_log_item *CUI_ITEM(struct xfs_log_item *lip)
26 {
27 	return container_of(lip, struct xfs_cui_log_item, cui_item);
28 }
29 
30 void
xfs_cui_item_free(struct xfs_cui_log_item * cuip)31 xfs_cui_item_free(
32 	struct xfs_cui_log_item	*cuip)
33 {
34 	if (cuip->cui_format.cui_nextents > XFS_CUI_MAX_FAST_EXTENTS)
35 		kmem_free(cuip);
36 	else
37 		kmem_zone_free(xfs_cui_zone, cuip);
38 }
39 
40 /*
41  * Freeing the CUI requires that we remove it from the AIL if it has already
42  * been placed there. However, the CUI may not yet have been placed in the AIL
43  * when called by xfs_cui_release() from CUD processing due to the ordering of
44  * committed vs unpin operations in bulk insert operations. Hence the reference
45  * count to ensure only the last caller frees the CUI.
46  */
47 void
xfs_cui_release(struct xfs_cui_log_item * cuip)48 xfs_cui_release(
49 	struct xfs_cui_log_item	*cuip)
50 {
51 	ASSERT(atomic_read(&cuip->cui_refcount) > 0);
52 	if (atomic_dec_and_test(&cuip->cui_refcount)) {
53 		xfs_trans_ail_remove(&cuip->cui_item, SHUTDOWN_LOG_IO_ERROR);
54 		xfs_cui_item_free(cuip);
55 	}
56 }
57 
58 
59 STATIC void
xfs_cui_item_size(struct xfs_log_item * lip,int * nvecs,int * nbytes)60 xfs_cui_item_size(
61 	struct xfs_log_item	*lip,
62 	int			*nvecs,
63 	int			*nbytes)
64 {
65 	struct xfs_cui_log_item	*cuip = CUI_ITEM(lip);
66 
67 	*nvecs += 1;
68 	*nbytes += xfs_cui_log_format_sizeof(cuip->cui_format.cui_nextents);
69 }
70 
71 /*
72  * This is called to fill in the vector of log iovecs for the
73  * given cui log item. We use only 1 iovec, and we point that
74  * at the cui_log_format structure embedded in the cui item.
75  * It is at this point that we assert that all of the extent
76  * slots in the cui item have been filled.
77  */
78 STATIC void
xfs_cui_item_format(struct xfs_log_item * lip,struct xfs_log_vec * lv)79 xfs_cui_item_format(
80 	struct xfs_log_item	*lip,
81 	struct xfs_log_vec	*lv)
82 {
83 	struct xfs_cui_log_item	*cuip = CUI_ITEM(lip);
84 	struct xfs_log_iovec	*vecp = NULL;
85 
86 	ASSERT(atomic_read(&cuip->cui_next_extent) ==
87 			cuip->cui_format.cui_nextents);
88 
89 	cuip->cui_format.cui_type = XFS_LI_CUI;
90 	cuip->cui_format.cui_size = 1;
91 
92 	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_CUI_FORMAT, &cuip->cui_format,
93 			xfs_cui_log_format_sizeof(cuip->cui_format.cui_nextents));
94 }
95 
96 /*
97  * The unpin operation is the last place an CUI is manipulated in the log. It is
98  * either inserted in the AIL or aborted in the event of a log I/O error. In
99  * either case, the CUI transaction has been successfully committed to make it
100  * this far. Therefore, we expect whoever committed the CUI to either construct
101  * and commit the CUD or drop the CUD's reference in the event of error. Simply
102  * drop the log's CUI reference now that the log is done with it.
103  */
104 STATIC void
xfs_cui_item_unpin(struct xfs_log_item * lip,int remove)105 xfs_cui_item_unpin(
106 	struct xfs_log_item	*lip,
107 	int			remove)
108 {
109 	struct xfs_cui_log_item	*cuip = CUI_ITEM(lip);
110 
111 	xfs_cui_release(cuip);
112 }
113 
114 /*
115  * The CUI has been either committed or aborted if the transaction has been
116  * cancelled. If the transaction was cancelled, an CUD isn't going to be
117  * constructed and thus we free the CUI here directly.
118  */
119 STATIC void
xfs_cui_item_release(struct xfs_log_item * lip)120 xfs_cui_item_release(
121 	struct xfs_log_item	*lip)
122 {
123 	xfs_cui_release(CUI_ITEM(lip));
124 }
125 
CUD_ITEM(struct xfs_log_item * lip)126 static inline struct xfs_cud_log_item *CUD_ITEM(struct xfs_log_item *lip)
127 {
128 	return container_of(lip, struct xfs_cud_log_item, cud_item);
129 }
130 
131 STATIC void
xfs_cud_item_size(struct xfs_log_item * lip,int * nvecs,int * nbytes)132 xfs_cud_item_size(
133 	struct xfs_log_item	*lip,
134 	int			*nvecs,
135 	int			*nbytes)
136 {
137 	*nvecs += 1;
138 	*nbytes += sizeof(struct xfs_cud_log_format);
139 }
140 
141 /*
142  * This is called to fill in the vector of log iovecs for the
143  * given cud log item. We use only 1 iovec, and we point that
144  * at the cud_log_format structure embedded in the cud item.
145  * It is at this point that we assert that all of the extent
146  * slots in the cud item have been filled.
147  */
148 STATIC void
xfs_cud_item_format(struct xfs_log_item * lip,struct xfs_log_vec * lv)149 xfs_cud_item_format(
150 	struct xfs_log_item	*lip,
151 	struct xfs_log_vec	*lv)
152 {
153 	struct xfs_cud_log_item	*cudp = CUD_ITEM(lip);
154 	struct xfs_log_iovec	*vecp = NULL;
155 
156 	cudp->cud_format.cud_type = XFS_LI_CUD;
157 	cudp->cud_format.cud_size = 1;
158 
159 	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_CUD_FORMAT, &cudp->cud_format,
160 			sizeof(struct xfs_cud_log_format));
161 }
162 
163 /*
164  * The CUD is either committed or aborted if the transaction is cancelled. If
165  * the transaction is cancelled, drop our reference to the CUI and free the
166  * CUD.
167  */
168 STATIC void
xfs_cud_item_release(struct xfs_log_item * lip)169 xfs_cud_item_release(
170 	struct xfs_log_item	*lip)
171 {
172 	struct xfs_cud_log_item	*cudp = CUD_ITEM(lip);
173 
174 	xfs_cui_release(cudp->cud_cuip);
175 	kmem_zone_free(xfs_cud_zone, cudp);
176 }
177 
178 static const struct xfs_item_ops xfs_cud_item_ops = {
179 	.flags		= XFS_ITEM_RELEASE_WHEN_COMMITTED,
180 	.iop_size	= xfs_cud_item_size,
181 	.iop_format	= xfs_cud_item_format,
182 	.iop_release	= xfs_cud_item_release,
183 };
184 
185 static struct xfs_cud_log_item *
xfs_trans_get_cud(struct xfs_trans * tp,struct xfs_cui_log_item * cuip)186 xfs_trans_get_cud(
187 	struct xfs_trans		*tp,
188 	struct xfs_cui_log_item		*cuip)
189 {
190 	struct xfs_cud_log_item		*cudp;
191 
192 	cudp = kmem_zone_zalloc(xfs_cud_zone, 0);
193 	xfs_log_item_init(tp->t_mountp, &cudp->cud_item, XFS_LI_CUD,
194 			  &xfs_cud_item_ops);
195 	cudp->cud_cuip = cuip;
196 	cudp->cud_format.cud_cui_id = cuip->cui_format.cui_id;
197 
198 	xfs_trans_add_item(tp, &cudp->cud_item);
199 	return cudp;
200 }
201 
202 /*
203  * Finish an refcount update and log it to the CUD. Note that the
204  * transaction is marked dirty regardless of whether the refcount
205  * update succeeds or fails to support the CUI/CUD lifecycle rules.
206  */
207 static int
xfs_trans_log_finish_refcount_update(struct xfs_trans * tp,struct xfs_cud_log_item * cudp,enum xfs_refcount_intent_type type,xfs_fsblock_t startblock,xfs_extlen_t blockcount,xfs_fsblock_t * new_fsb,xfs_extlen_t * new_len,struct xfs_btree_cur ** pcur)208 xfs_trans_log_finish_refcount_update(
209 	struct xfs_trans		*tp,
210 	struct xfs_cud_log_item		*cudp,
211 	enum xfs_refcount_intent_type	type,
212 	xfs_fsblock_t			startblock,
213 	xfs_extlen_t			blockcount,
214 	xfs_fsblock_t			*new_fsb,
215 	xfs_extlen_t			*new_len,
216 	struct xfs_btree_cur		**pcur)
217 {
218 	int				error;
219 
220 	error = xfs_refcount_finish_one(tp, type, startblock,
221 			blockcount, new_fsb, new_len, pcur);
222 
223 	/*
224 	 * Mark the transaction dirty, even on error. This ensures the
225 	 * transaction is aborted, which:
226 	 *
227 	 * 1.) releases the CUI and frees the CUD
228 	 * 2.) shuts down the filesystem
229 	 */
230 	tp->t_flags |= XFS_TRANS_DIRTY;
231 	set_bit(XFS_LI_DIRTY, &cudp->cud_item.li_flags);
232 
233 	return error;
234 }
235 
236 /* Sort refcount intents by AG. */
237 static int
xfs_refcount_update_diff_items(void * priv,struct list_head * a,struct list_head * b)238 xfs_refcount_update_diff_items(
239 	void				*priv,
240 	struct list_head		*a,
241 	struct list_head		*b)
242 {
243 	struct xfs_mount		*mp = priv;
244 	struct xfs_refcount_intent	*ra;
245 	struct xfs_refcount_intent	*rb;
246 
247 	ra = container_of(a, struct xfs_refcount_intent, ri_list);
248 	rb = container_of(b, struct xfs_refcount_intent, ri_list);
249 	return  XFS_FSB_TO_AGNO(mp, ra->ri_startblock) -
250 		XFS_FSB_TO_AGNO(mp, rb->ri_startblock);
251 }
252 
253 /* Set the phys extent flags for this reverse mapping. */
254 static void
xfs_trans_set_refcount_flags(struct xfs_phys_extent * refc,enum xfs_refcount_intent_type type)255 xfs_trans_set_refcount_flags(
256 	struct xfs_phys_extent		*refc,
257 	enum xfs_refcount_intent_type	type)
258 {
259 	refc->pe_flags = 0;
260 	switch (type) {
261 	case XFS_REFCOUNT_INCREASE:
262 	case XFS_REFCOUNT_DECREASE:
263 	case XFS_REFCOUNT_ALLOC_COW:
264 	case XFS_REFCOUNT_FREE_COW:
265 		refc->pe_flags |= type;
266 		break;
267 	default:
268 		ASSERT(0);
269 	}
270 }
271 
272 /* Log refcount updates in the intent item. */
273 STATIC void
xfs_refcount_update_log_item(struct xfs_trans * tp,struct xfs_cui_log_item * cuip,struct xfs_refcount_intent * refc)274 xfs_refcount_update_log_item(
275 	struct xfs_trans		*tp,
276 	struct xfs_cui_log_item		*cuip,
277 	struct xfs_refcount_intent	*refc)
278 {
279 	uint				next_extent;
280 	struct xfs_phys_extent		*ext;
281 
282 	tp->t_flags |= XFS_TRANS_DIRTY;
283 	set_bit(XFS_LI_DIRTY, &cuip->cui_item.li_flags);
284 
285 	/*
286 	 * atomic_inc_return gives us the value after the increment;
287 	 * we want to use it as an array index so we need to subtract 1 from
288 	 * it.
289 	 */
290 	next_extent = atomic_inc_return(&cuip->cui_next_extent) - 1;
291 	ASSERT(next_extent < cuip->cui_format.cui_nextents);
292 	ext = &cuip->cui_format.cui_extents[next_extent];
293 	ext->pe_startblock = refc->ri_startblock;
294 	ext->pe_len = refc->ri_blockcount;
295 	xfs_trans_set_refcount_flags(ext, refc->ri_type);
296 }
297 
298 static struct xfs_log_item *
xfs_refcount_update_create_intent(struct xfs_trans * tp,struct list_head * items,unsigned int count,bool sort)299 xfs_refcount_update_create_intent(
300 	struct xfs_trans		*tp,
301 	struct list_head		*items,
302 	unsigned int			count,
303 	bool				sort)
304 {
305 	struct xfs_mount		*mp = tp->t_mountp;
306 	struct xfs_cui_log_item		*cuip = xfs_cui_init(mp, count);
307 	struct xfs_refcount_intent	*refc;
308 
309 	ASSERT(count > 0);
310 
311 	xfs_trans_add_item(tp, &cuip->cui_item);
312 	if (sort)
313 		list_sort(mp, items, xfs_refcount_update_diff_items);
314 	list_for_each_entry(refc, items, ri_list)
315 		xfs_refcount_update_log_item(tp, cuip, refc);
316 	return &cuip->cui_item;
317 }
318 
319 /* Get an CUD so we can process all the deferred refcount updates. */
320 STATIC void *
xfs_refcount_update_create_done(struct xfs_trans * tp,struct xfs_log_item * intent,unsigned int count)321 xfs_refcount_update_create_done(
322 	struct xfs_trans		*tp,
323 	struct xfs_log_item		*intent,
324 	unsigned int			count)
325 {
326 	return xfs_trans_get_cud(tp, CUI_ITEM(intent));
327 }
328 
329 /* Process a deferred refcount update. */
330 STATIC int
xfs_refcount_update_finish_item(struct xfs_trans * tp,struct list_head * item,void * done_item,void ** state)331 xfs_refcount_update_finish_item(
332 	struct xfs_trans		*tp,
333 	struct list_head		*item,
334 	void				*done_item,
335 	void				**state)
336 {
337 	struct xfs_refcount_intent	*refc;
338 	xfs_fsblock_t			new_fsb;
339 	xfs_extlen_t			new_aglen;
340 	int				error;
341 
342 	refc = container_of(item, struct xfs_refcount_intent, ri_list);
343 	error = xfs_trans_log_finish_refcount_update(tp, done_item,
344 			refc->ri_type,
345 			refc->ri_startblock,
346 			refc->ri_blockcount,
347 			&new_fsb, &new_aglen,
348 			(struct xfs_btree_cur **)state);
349 	/* Did we run out of reservation?  Requeue what we didn't finish. */
350 	if (!error && new_aglen > 0) {
351 		ASSERT(refc->ri_type == XFS_REFCOUNT_INCREASE ||
352 		       refc->ri_type == XFS_REFCOUNT_DECREASE);
353 		refc->ri_startblock = new_fsb;
354 		refc->ri_blockcount = new_aglen;
355 		return -EAGAIN;
356 	}
357 	kmem_free(refc);
358 	return error;
359 }
360 
361 /* Clean up after processing deferred refcounts. */
362 STATIC void
xfs_refcount_update_finish_cleanup(struct xfs_trans * tp,void * state,int error)363 xfs_refcount_update_finish_cleanup(
364 	struct xfs_trans	*tp,
365 	void			*state,
366 	int			error)
367 {
368 	struct xfs_btree_cur	*rcur = state;
369 
370 	xfs_refcount_finish_one_cleanup(tp, rcur, error);
371 }
372 
373 /* Abort all pending CUIs. */
374 STATIC void
xfs_refcount_update_abort_intent(struct xfs_log_item * intent)375 xfs_refcount_update_abort_intent(
376 	struct xfs_log_item		*intent)
377 {
378 	xfs_cui_release(CUI_ITEM(intent));
379 }
380 
381 /* Cancel a deferred refcount update. */
382 STATIC void
xfs_refcount_update_cancel_item(struct list_head * item)383 xfs_refcount_update_cancel_item(
384 	struct list_head		*item)
385 {
386 	struct xfs_refcount_intent	*refc;
387 
388 	refc = container_of(item, struct xfs_refcount_intent, ri_list);
389 	kmem_free(refc);
390 }
391 
392 const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
393 	.max_items	= XFS_CUI_MAX_FAST_EXTENTS,
394 	.create_intent	= xfs_refcount_update_create_intent,
395 	.abort_intent	= xfs_refcount_update_abort_intent,
396 	.create_done	= xfs_refcount_update_create_done,
397 	.finish_item	= xfs_refcount_update_finish_item,
398 	.finish_cleanup = xfs_refcount_update_finish_cleanup,
399 	.cancel_item	= xfs_refcount_update_cancel_item,
400 };
401 
402 /*
403  * Process a refcount update intent item that was recovered from the log.
404  * We need to update the refcountbt.
405  */
406 int
xfs_cui_recover(struct xfs_cui_log_item * cuip,struct list_head * capture_list)407 xfs_cui_recover(
408 	struct xfs_cui_log_item		*cuip,
409 	struct list_head		*capture_list)
410 {
411 	int				i;
412 	int				error = 0;
413 	unsigned int			refc_type;
414 	struct xfs_phys_extent		*refc;
415 	xfs_fsblock_t			startblock_fsb;
416 	bool				op_ok;
417 	struct xfs_cud_log_item		*cudp;
418 	struct xfs_trans		*tp;
419 	struct xfs_btree_cur		*rcur = NULL;
420 	enum xfs_refcount_intent_type	type;
421 	xfs_fsblock_t			new_fsb;
422 	xfs_extlen_t			new_len;
423 	struct xfs_bmbt_irec		irec;
424 	bool				requeue_only = false;
425 	struct xfs_mount		*mp = cuip->cui_item.li_mountp;
426 
427 	ASSERT(!test_bit(XFS_CUI_RECOVERED, &cuip->cui_flags));
428 
429 	/*
430 	 * First check the validity of the extents described by the
431 	 * CUI.  If any are bad, then assume that all are bad and
432 	 * just toss the CUI.
433 	 */
434 	for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
435 		refc = &cuip->cui_format.cui_extents[i];
436 		startblock_fsb = XFS_BB_TO_FSB(mp,
437 				   XFS_FSB_TO_DADDR(mp, refc->pe_startblock));
438 		switch (refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) {
439 		case XFS_REFCOUNT_INCREASE:
440 		case XFS_REFCOUNT_DECREASE:
441 		case XFS_REFCOUNT_ALLOC_COW:
442 		case XFS_REFCOUNT_FREE_COW:
443 			op_ok = true;
444 			break;
445 		default:
446 			op_ok = false;
447 			break;
448 		}
449 		if (!op_ok || startblock_fsb == 0 ||
450 		    refc->pe_len == 0 ||
451 		    startblock_fsb >= mp->m_sb.sb_dblocks ||
452 		    refc->pe_len >= mp->m_sb.sb_agblocks ||
453 		    (refc->pe_flags & ~XFS_REFCOUNT_EXTENT_FLAGS)) {
454 			/*
455 			 * This will pull the CUI from the AIL and
456 			 * free the memory associated with it.
457 			 */
458 			set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
459 			xfs_cui_release(cuip);
460 			return -EFSCORRUPTED;
461 		}
462 	}
463 
464 	/*
465 	 * Under normal operation, refcount updates are deferred, so we
466 	 * wouldn't be adding them directly to a transaction.  All
467 	 * refcount updates manage reservation usage internally and
468 	 * dynamically by deferring work that won't fit in the
469 	 * transaction.  Normally, any work that needs to be deferred
470 	 * gets attached to the same defer_ops that scheduled the
471 	 * refcount update.  However, we're in log recovery here, so we
472 	 * we use the passed in defer_ops and to finish up any work that
473 	 * doesn't fit.  We need to reserve enough blocks to handle a
474 	 * full btree split on either end of the refcount range.
475 	 */
476 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
477 			mp->m_refc_maxlevels * 2, 0, XFS_TRANS_RESERVE, &tp);
478 	if (error)
479 		return error;
480 
481 	cudp = xfs_trans_get_cud(tp, cuip);
482 
483 	for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
484 		refc = &cuip->cui_format.cui_extents[i];
485 		refc_type = refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK;
486 		switch (refc_type) {
487 		case XFS_REFCOUNT_INCREASE:
488 		case XFS_REFCOUNT_DECREASE:
489 		case XFS_REFCOUNT_ALLOC_COW:
490 		case XFS_REFCOUNT_FREE_COW:
491 			type = refc_type;
492 			break;
493 		default:
494 			XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
495 			error = -EFSCORRUPTED;
496 			goto abort_error;
497 		}
498 		if (requeue_only) {
499 			new_fsb = refc->pe_startblock;
500 			new_len = refc->pe_len;
501 		} else
502 			error = xfs_trans_log_finish_refcount_update(tp, cudp,
503 				type, refc->pe_startblock, refc->pe_len,
504 				&new_fsb, &new_len, &rcur);
505 		if (error)
506 			goto abort_error;
507 
508 		/* Requeue what we didn't finish. */
509 		if (new_len > 0) {
510 			irec.br_startblock = new_fsb;
511 			irec.br_blockcount = new_len;
512 			switch (type) {
513 			case XFS_REFCOUNT_INCREASE:
514 				xfs_refcount_increase_extent(tp, &irec);
515 				break;
516 			case XFS_REFCOUNT_DECREASE:
517 				xfs_refcount_decrease_extent(tp, &irec);
518 				break;
519 			case XFS_REFCOUNT_ALLOC_COW:
520 				xfs_refcount_alloc_cow_extent(tp,
521 						irec.br_startblock,
522 						irec.br_blockcount);
523 				break;
524 			case XFS_REFCOUNT_FREE_COW:
525 				xfs_refcount_free_cow_extent(tp,
526 						irec.br_startblock,
527 						irec.br_blockcount);
528 				break;
529 			default:
530 				ASSERT(0);
531 			}
532 			requeue_only = true;
533 		}
534 	}
535 
536 	xfs_refcount_finish_one_cleanup(tp, rcur, error);
537 	set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
538 	return xfs_defer_ops_capture_and_commit(tp, NULL, capture_list);
539 
540 abort_error:
541 	xfs_refcount_finish_one_cleanup(tp, rcur, error);
542 	xfs_trans_cancel(tp);
543 	return error;
544 }
545 
546 /* Relog an intent item to push the log tail forward. */
547 static struct xfs_log_item *
xfs_cui_item_relog(struct xfs_log_item * intent,struct xfs_trans * tp)548 xfs_cui_item_relog(
549 	struct xfs_log_item		*intent,
550 	struct xfs_trans		*tp)
551 {
552 	struct xfs_cud_log_item		*cudp;
553 	struct xfs_cui_log_item		*cuip;
554 	struct xfs_phys_extent		*extp;
555 	unsigned int			count;
556 
557 	count = CUI_ITEM(intent)->cui_format.cui_nextents;
558 	extp = CUI_ITEM(intent)->cui_format.cui_extents;
559 
560 	tp->t_flags |= XFS_TRANS_DIRTY;
561 	cudp = xfs_trans_get_cud(tp, CUI_ITEM(intent));
562 	set_bit(XFS_LI_DIRTY, &cudp->cud_item.li_flags);
563 
564 	cuip = xfs_cui_init(tp->t_mountp, count);
565 	memcpy(cuip->cui_format.cui_extents, extp, count * sizeof(*extp));
566 	atomic_set(&cuip->cui_next_extent, count);
567 	xfs_trans_add_item(tp, &cuip->cui_item);
568 	set_bit(XFS_LI_DIRTY, &cuip->cui_item.li_flags);
569 	return &cuip->cui_item;
570 }
571 
572 static const struct xfs_item_ops xfs_cui_item_ops = {
573 	.iop_size	= xfs_cui_item_size,
574 	.iop_format	= xfs_cui_item_format,
575 	.iop_unpin	= xfs_cui_item_unpin,
576 	.iop_release	= xfs_cui_item_release,
577 	.iop_relog	= xfs_cui_item_relog,
578 };
579 
580 /*
581  * Allocate and initialize an cui item with the given number of extents.
582  */
583 struct xfs_cui_log_item *
xfs_cui_init(struct xfs_mount * mp,uint nextents)584 xfs_cui_init(
585 	struct xfs_mount		*mp,
586 	uint				nextents)
587 
588 {
589 	struct xfs_cui_log_item		*cuip;
590 
591 	ASSERT(nextents > 0);
592 	if (nextents > XFS_CUI_MAX_FAST_EXTENTS)
593 		cuip = kmem_zalloc(xfs_cui_log_item_sizeof(nextents),
594 				0);
595 	else
596 		cuip = kmem_zone_zalloc(xfs_cui_zone, 0);
597 
598 	xfs_log_item_init(mp, &cuip->cui_item, XFS_LI_CUI, &xfs_cui_item_ops);
599 	cuip->cui_format.cui_nextents = nextents;
600 	cuip->cui_format.cui_id = (uintptr_t)(void *)cuip;
601 	atomic_set(&cuip->cui_next_extent, 0);
602 	atomic_set(&cuip->cui_refcount, 2);
603 
604 	return cuip;
605 }
606