Merge tag 'input-for-v5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-block.git] / fs / xfs / xfs_bmap_item.c
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_inode.h"
16 #include "xfs_trans.h"
17 #include "xfs_trans_priv.h"
18 #include "xfs_bmap_item.h"
19 #include "xfs_log.h"
20 #include "xfs_bmap.h"
21 #include "xfs_icache.h"
22 #include "xfs_bmap_btree.h"
23 #include "xfs_trans_space.h"
24 #include "xfs_error.h"
25 #include "xfs_log_priv.h"
26 #include "xfs_log_recover.h"
27
28 struct kmem_cache       *xfs_bui_cache;
29 struct kmem_cache       *xfs_bud_cache;
30
31 static const struct xfs_item_ops xfs_bui_item_ops;
32
33 static inline struct xfs_bui_log_item *BUI_ITEM(struct xfs_log_item *lip)
34 {
35         return container_of(lip, struct xfs_bui_log_item, bui_item);
36 }
37
38 STATIC void
39 xfs_bui_item_free(
40         struct xfs_bui_log_item *buip)
41 {
42         kmem_free(buip->bui_item.li_lv_shadow);
43         kmem_cache_free(xfs_bui_cache, buip);
44 }
45
46 /*
47  * Freeing the BUI requires that we remove it from the AIL if it has already
48  * been placed there. However, the BUI may not yet have been placed in the AIL
49  * when called by xfs_bui_release() from BUD processing due to the ordering of
50  * committed vs unpin operations in bulk insert operations. Hence the reference
51  * count to ensure only the last caller frees the BUI.
52  */
53 STATIC void
54 xfs_bui_release(
55         struct xfs_bui_log_item *buip)
56 {
57         ASSERT(atomic_read(&buip->bui_refcount) > 0);
58         if (!atomic_dec_and_test(&buip->bui_refcount))
59                 return;
60
61         xfs_trans_ail_delete(&buip->bui_item, 0);
62         xfs_bui_item_free(buip);
63 }
64
65
66 STATIC void
67 xfs_bui_item_size(
68         struct xfs_log_item     *lip,
69         int                     *nvecs,
70         int                     *nbytes)
71 {
72         struct xfs_bui_log_item *buip = BUI_ITEM(lip);
73
74         *nvecs += 1;
75         *nbytes += xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents);
76 }
77
78 /*
79  * This is called to fill in the vector of log iovecs for the
80  * given bui log item. We use only 1 iovec, and we point that
81  * at the bui_log_format structure embedded in the bui item.
82  * It is at this point that we assert that all of the extent
83  * slots in the bui item have been filled.
84  */
85 STATIC void
86 xfs_bui_item_format(
87         struct xfs_log_item     *lip,
88         struct xfs_log_vec      *lv)
89 {
90         struct xfs_bui_log_item *buip = BUI_ITEM(lip);
91         struct xfs_log_iovec    *vecp = NULL;
92
93         ASSERT(atomic_read(&buip->bui_next_extent) ==
94                         buip->bui_format.bui_nextents);
95
96         buip->bui_format.bui_type = XFS_LI_BUI;
97         buip->bui_format.bui_size = 1;
98
99         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUI_FORMAT, &buip->bui_format,
100                         xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents));
101 }
102
103 /*
104  * The unpin operation is the last place an BUI is manipulated in the log. It is
105  * either inserted in the AIL or aborted in the event of a log I/O error. In
106  * either case, the BUI transaction has been successfully committed to make it
107  * this far. Therefore, we expect whoever committed the BUI to either construct
108  * and commit the BUD or drop the BUD's reference in the event of error. Simply
109  * drop the log's BUI reference now that the log is done with it.
110  */
111 STATIC void
112 xfs_bui_item_unpin(
113         struct xfs_log_item     *lip,
114         int                     remove)
115 {
116         struct xfs_bui_log_item *buip = BUI_ITEM(lip);
117
118         xfs_bui_release(buip);
119 }
120
121 /*
122  * The BUI has been either committed or aborted if the transaction has been
123  * cancelled. If the transaction was cancelled, an BUD isn't going to be
124  * constructed and thus we free the BUI here directly.
125  */
126 STATIC void
127 xfs_bui_item_release(
128         struct xfs_log_item     *lip)
129 {
130         xfs_bui_release(BUI_ITEM(lip));
131 }
132
133 /*
134  * Allocate and initialize an bui item with the given number of extents.
135  */
136 STATIC struct xfs_bui_log_item *
137 xfs_bui_init(
138         struct xfs_mount                *mp)
139
140 {
141         struct xfs_bui_log_item         *buip;
142
143         buip = kmem_cache_zalloc(xfs_bui_cache, GFP_KERNEL | __GFP_NOFAIL);
144
145         xfs_log_item_init(mp, &buip->bui_item, XFS_LI_BUI, &xfs_bui_item_ops);
146         buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS;
147         buip->bui_format.bui_id = (uintptr_t)(void *)buip;
148         atomic_set(&buip->bui_next_extent, 0);
149         atomic_set(&buip->bui_refcount, 2);
150
151         return buip;
152 }
153
154 static inline struct xfs_bud_log_item *BUD_ITEM(struct xfs_log_item *lip)
155 {
156         return container_of(lip, struct xfs_bud_log_item, bud_item);
157 }
158
159 STATIC void
160 xfs_bud_item_size(
161         struct xfs_log_item     *lip,
162         int                     *nvecs,
163         int                     *nbytes)
164 {
165         *nvecs += 1;
166         *nbytes += sizeof(struct xfs_bud_log_format);
167 }
168
169 /*
170  * This is called to fill in the vector of log iovecs for the
171  * given bud log item. We use only 1 iovec, and we point that
172  * at the bud_log_format structure embedded in the bud item.
173  * It is at this point that we assert that all of the extent
174  * slots in the bud item have been filled.
175  */
176 STATIC void
177 xfs_bud_item_format(
178         struct xfs_log_item     *lip,
179         struct xfs_log_vec      *lv)
180 {
181         struct xfs_bud_log_item *budp = BUD_ITEM(lip);
182         struct xfs_log_iovec    *vecp = NULL;
183
184         budp->bud_format.bud_type = XFS_LI_BUD;
185         budp->bud_format.bud_size = 1;
186
187         xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUD_FORMAT, &budp->bud_format,
188                         sizeof(struct xfs_bud_log_format));
189 }
190
191 /*
192  * The BUD is either committed or aborted if the transaction is cancelled. If
193  * the transaction is cancelled, drop our reference to the BUI and free the
194  * BUD.
195  */
196 STATIC void
197 xfs_bud_item_release(
198         struct xfs_log_item     *lip)
199 {
200         struct xfs_bud_log_item *budp = BUD_ITEM(lip);
201
202         xfs_bui_release(budp->bud_buip);
203         kmem_free(budp->bud_item.li_lv_shadow);
204         kmem_cache_free(xfs_bud_cache, budp);
205 }
206
207 static struct xfs_log_item *
208 xfs_bud_item_intent(
209         struct xfs_log_item     *lip)
210 {
211         return &BUD_ITEM(lip)->bud_buip->bui_item;
212 }
213
214 static const struct xfs_item_ops xfs_bud_item_ops = {
215         .flags          = XFS_ITEM_RELEASE_WHEN_COMMITTED |
216                           XFS_ITEM_INTENT_DONE,
217         .iop_size       = xfs_bud_item_size,
218         .iop_format     = xfs_bud_item_format,
219         .iop_release    = xfs_bud_item_release,
220         .iop_intent     = xfs_bud_item_intent,
221 };
222
223 static struct xfs_bud_log_item *
224 xfs_trans_get_bud(
225         struct xfs_trans                *tp,
226         struct xfs_bui_log_item         *buip)
227 {
228         struct xfs_bud_log_item         *budp;
229
230         budp = kmem_cache_zalloc(xfs_bud_cache, GFP_KERNEL | __GFP_NOFAIL);
231         xfs_log_item_init(tp->t_mountp, &budp->bud_item, XFS_LI_BUD,
232                           &xfs_bud_item_ops);
233         budp->bud_buip = buip;
234         budp->bud_format.bud_bui_id = buip->bui_format.bui_id;
235
236         xfs_trans_add_item(tp, &budp->bud_item);
237         return budp;
238 }
239
240 /*
241  * Finish an bmap update and log it to the BUD. Note that the
242  * transaction is marked dirty regardless of whether the bmap update
243  * succeeds or fails to support the BUI/BUD lifecycle rules.
244  */
245 static int
246 xfs_trans_log_finish_bmap_update(
247         struct xfs_trans                *tp,
248         struct xfs_bud_log_item         *budp,
249         enum xfs_bmap_intent_type       type,
250         struct xfs_inode                *ip,
251         int                             whichfork,
252         xfs_fileoff_t                   startoff,
253         xfs_fsblock_t                   startblock,
254         xfs_filblks_t                   *blockcount,
255         xfs_exntst_t                    state)
256 {
257         int                             error;
258
259         error = xfs_bmap_finish_one(tp, ip, type, whichfork, startoff,
260                         startblock, blockcount, state);
261
262         /*
263          * Mark the transaction dirty, even on error. This ensures the
264          * transaction is aborted, which:
265          *
266          * 1.) releases the BUI and frees the BUD
267          * 2.) shuts down the filesystem
268          */
269         tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
270         set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
271
272         return error;
273 }
274
275 /* Sort bmap intents by inode. */
276 static int
277 xfs_bmap_update_diff_items(
278         void                            *priv,
279         const struct list_head          *a,
280         const struct list_head          *b)
281 {
282         struct xfs_bmap_intent          *ba;
283         struct xfs_bmap_intent          *bb;
284
285         ba = container_of(a, struct xfs_bmap_intent, bi_list);
286         bb = container_of(b, struct xfs_bmap_intent, bi_list);
287         return ba->bi_owner->i_ino - bb->bi_owner->i_ino;
288 }
289
290 /* Set the map extent flags for this mapping. */
291 static void
292 xfs_trans_set_bmap_flags(
293         struct xfs_map_extent           *bmap,
294         enum xfs_bmap_intent_type       type,
295         int                             whichfork,
296         xfs_exntst_t                    state)
297 {
298         bmap->me_flags = 0;
299         switch (type) {
300         case XFS_BMAP_MAP:
301         case XFS_BMAP_UNMAP:
302                 bmap->me_flags = type;
303                 break;
304         default:
305                 ASSERT(0);
306         }
307         if (state == XFS_EXT_UNWRITTEN)
308                 bmap->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN;
309         if (whichfork == XFS_ATTR_FORK)
310                 bmap->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK;
311 }
312
313 /* Log bmap updates in the intent item. */
314 STATIC void
315 xfs_bmap_update_log_item(
316         struct xfs_trans                *tp,
317         struct xfs_bui_log_item         *buip,
318         struct xfs_bmap_intent          *bmap)
319 {
320         uint                            next_extent;
321         struct xfs_map_extent           *map;
322
323         tp->t_flags |= XFS_TRANS_DIRTY;
324         set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
325
326         /*
327          * atomic_inc_return gives us the value after the increment;
328          * we want to use it as an array index so we need to subtract 1 from
329          * it.
330          */
331         next_extent = atomic_inc_return(&buip->bui_next_extent) - 1;
332         ASSERT(next_extent < buip->bui_format.bui_nextents);
333         map = &buip->bui_format.bui_extents[next_extent];
334         map->me_owner = bmap->bi_owner->i_ino;
335         map->me_startblock = bmap->bi_bmap.br_startblock;
336         map->me_startoff = bmap->bi_bmap.br_startoff;
337         map->me_len = bmap->bi_bmap.br_blockcount;
338         xfs_trans_set_bmap_flags(map, bmap->bi_type, bmap->bi_whichfork,
339                         bmap->bi_bmap.br_state);
340 }
341
342 static struct xfs_log_item *
343 xfs_bmap_update_create_intent(
344         struct xfs_trans                *tp,
345         struct list_head                *items,
346         unsigned int                    count,
347         bool                            sort)
348 {
349         struct xfs_mount                *mp = tp->t_mountp;
350         struct xfs_bui_log_item         *buip = xfs_bui_init(mp);
351         struct xfs_bmap_intent          *bmap;
352
353         ASSERT(count == XFS_BUI_MAX_FAST_EXTENTS);
354
355         xfs_trans_add_item(tp, &buip->bui_item);
356         if (sort)
357                 list_sort(mp, items, xfs_bmap_update_diff_items);
358         list_for_each_entry(bmap, items, bi_list)
359                 xfs_bmap_update_log_item(tp, buip, bmap);
360         return &buip->bui_item;
361 }
362
363 /* Get an BUD so we can process all the deferred rmap updates. */
364 static struct xfs_log_item *
365 xfs_bmap_update_create_done(
366         struct xfs_trans                *tp,
367         struct xfs_log_item             *intent,
368         unsigned int                    count)
369 {
370         return &xfs_trans_get_bud(tp, BUI_ITEM(intent))->bud_item;
371 }
372
373 /* Process a deferred rmap update. */
374 STATIC int
375 xfs_bmap_update_finish_item(
376         struct xfs_trans                *tp,
377         struct xfs_log_item             *done,
378         struct list_head                *item,
379         struct xfs_btree_cur            **state)
380 {
381         struct xfs_bmap_intent          *bmap;
382         xfs_filblks_t                   count;
383         int                             error;
384
385         bmap = container_of(item, struct xfs_bmap_intent, bi_list);
386         count = bmap->bi_bmap.br_blockcount;
387         error = xfs_trans_log_finish_bmap_update(tp, BUD_ITEM(done),
388                         bmap->bi_type,
389                         bmap->bi_owner, bmap->bi_whichfork,
390                         bmap->bi_bmap.br_startoff,
391                         bmap->bi_bmap.br_startblock,
392                         &count,
393                         bmap->bi_bmap.br_state);
394         if (!error && count > 0) {
395                 ASSERT(bmap->bi_type == XFS_BMAP_UNMAP);
396                 bmap->bi_bmap.br_blockcount = count;
397                 return -EAGAIN;
398         }
399         kmem_cache_free(xfs_bmap_intent_cache, bmap);
400         return error;
401 }
402
403 /* Abort all pending BUIs. */
404 STATIC void
405 xfs_bmap_update_abort_intent(
406         struct xfs_log_item             *intent)
407 {
408         xfs_bui_release(BUI_ITEM(intent));
409 }
410
411 /* Cancel a deferred rmap update. */
412 STATIC void
413 xfs_bmap_update_cancel_item(
414         struct list_head                *item)
415 {
416         struct xfs_bmap_intent          *bmap;
417
418         bmap = container_of(item, struct xfs_bmap_intent, bi_list);
419         kmem_cache_free(xfs_bmap_intent_cache, bmap);
420 }
421
422 const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
423         .max_items      = XFS_BUI_MAX_FAST_EXTENTS,
424         .create_intent  = xfs_bmap_update_create_intent,
425         .abort_intent   = xfs_bmap_update_abort_intent,
426         .create_done    = xfs_bmap_update_create_done,
427         .finish_item    = xfs_bmap_update_finish_item,
428         .cancel_item    = xfs_bmap_update_cancel_item,
429 };
430
431 /* Is this recovered BUI ok? */
432 static inline bool
433 xfs_bui_validate(
434         struct xfs_mount                *mp,
435         struct xfs_bui_log_item         *buip)
436 {
437         struct xfs_map_extent           *bmap;
438
439         /* Only one mapping operation per BUI... */
440         if (buip->bui_format.bui_nextents != XFS_BUI_MAX_FAST_EXTENTS)
441                 return false;
442
443         bmap = &buip->bui_format.bui_extents[0];
444
445         if (bmap->me_flags & ~XFS_BMAP_EXTENT_FLAGS)
446                 return false;
447
448         switch (bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) {
449         case XFS_BMAP_MAP:
450         case XFS_BMAP_UNMAP:
451                 break;
452         default:
453                 return false;
454         }
455
456         if (!xfs_verify_ino(mp, bmap->me_owner))
457                 return false;
458
459         if (!xfs_verify_fileext(mp, bmap->me_startoff, bmap->me_len))
460                 return false;
461
462         return xfs_verify_fsbext(mp, bmap->me_startblock, bmap->me_len);
463 }
464
465 /*
466  * Process a bmap update intent item that was recovered from the log.
467  * We need to update some inode's bmbt.
468  */
469 STATIC int
470 xfs_bui_item_recover(
471         struct xfs_log_item             *lip,
472         struct list_head                *capture_list)
473 {
474         struct xfs_bmbt_irec            irec;
475         struct xfs_bui_log_item         *buip = BUI_ITEM(lip);
476         struct xfs_trans                *tp;
477         struct xfs_inode                *ip = NULL;
478         struct xfs_mount                *mp = lip->li_log->l_mp;
479         struct xfs_map_extent           *bmap;
480         struct xfs_bud_log_item         *budp;
481         xfs_filblks_t                   count;
482         xfs_exntst_t                    state;
483         unsigned int                    bui_type;
484         int                             whichfork;
485         int                             iext_delta;
486         int                             error = 0;
487
488         if (!xfs_bui_validate(mp, buip)) {
489                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
490                                 &buip->bui_format, sizeof(buip->bui_format));
491                 return -EFSCORRUPTED;
492         }
493
494         bmap = &buip->bui_format.bui_extents[0];
495         state = (bmap->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ?
496                         XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
497         whichfork = (bmap->me_flags & XFS_BMAP_EXTENT_ATTR_FORK) ?
498                         XFS_ATTR_FORK : XFS_DATA_FORK;
499         bui_type = bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK;
500
501         error = xlog_recover_iget(mp, bmap->me_owner, &ip);
502         if (error)
503                 return error;
504
505         /* Allocate transaction and do the work. */
506         error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
507                         XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
508         if (error)
509                 goto err_rele;
510
511         budp = xfs_trans_get_bud(tp, buip);
512         xfs_ilock(ip, XFS_ILOCK_EXCL);
513         xfs_trans_ijoin(tp, ip, 0);
514
515         if (bui_type == XFS_BMAP_MAP)
516                 iext_delta = XFS_IEXT_ADD_NOSPLIT_CNT;
517         else
518                 iext_delta = XFS_IEXT_PUNCH_HOLE_CNT;
519
520         error = xfs_iext_count_may_overflow(ip, whichfork, iext_delta);
521         if (error == -EFBIG)
522                 error = xfs_iext_count_upgrade(tp, ip, iext_delta);
523         if (error)
524                 goto err_cancel;
525
526         count = bmap->me_len;
527         error = xfs_trans_log_finish_bmap_update(tp, budp, bui_type, ip,
528                         whichfork, bmap->me_startoff, bmap->me_startblock,
529                         &count, state);
530         if (error == -EFSCORRUPTED)
531                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bmap,
532                                 sizeof(*bmap));
533         if (error)
534                 goto err_cancel;
535
536         if (count > 0) {
537                 ASSERT(bui_type == XFS_BMAP_UNMAP);
538                 irec.br_startblock = bmap->me_startblock;
539                 irec.br_blockcount = count;
540                 irec.br_startoff = bmap->me_startoff;
541                 irec.br_state = state;
542                 xfs_bmap_unmap_extent(tp, ip, &irec);
543         }
544
545         /*
546          * Commit transaction, which frees the transaction and saves the inode
547          * for later replay activities.
548          */
549         error = xfs_defer_ops_capture_and_commit(tp, capture_list);
550         if (error)
551                 goto err_unlock;
552
553         xfs_iunlock(ip, XFS_ILOCK_EXCL);
554         xfs_irele(ip);
555         return 0;
556
557 err_cancel:
558         xfs_trans_cancel(tp);
559 err_unlock:
560         xfs_iunlock(ip, XFS_ILOCK_EXCL);
561 err_rele:
562         xfs_irele(ip);
563         return error;
564 }
565
566 STATIC bool
567 xfs_bui_item_match(
568         struct xfs_log_item     *lip,
569         uint64_t                intent_id)
570 {
571         return BUI_ITEM(lip)->bui_format.bui_id == intent_id;
572 }
573
574 /* Relog an intent item to push the log tail forward. */
575 static struct xfs_log_item *
576 xfs_bui_item_relog(
577         struct xfs_log_item             *intent,
578         struct xfs_trans                *tp)
579 {
580         struct xfs_bud_log_item         *budp;
581         struct xfs_bui_log_item         *buip;
582         struct xfs_map_extent           *extp;
583         unsigned int                    count;
584
585         count = BUI_ITEM(intent)->bui_format.bui_nextents;
586         extp = BUI_ITEM(intent)->bui_format.bui_extents;
587
588         tp->t_flags |= XFS_TRANS_DIRTY;
589         budp = xfs_trans_get_bud(tp, BUI_ITEM(intent));
590         set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
591
592         buip = xfs_bui_init(tp->t_mountp);
593         memcpy(buip->bui_format.bui_extents, extp, count * sizeof(*extp));
594         atomic_set(&buip->bui_next_extent, count);
595         xfs_trans_add_item(tp, &buip->bui_item);
596         set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
597         return &buip->bui_item;
598 }
599
600 static const struct xfs_item_ops xfs_bui_item_ops = {
601         .flags          = XFS_ITEM_INTENT,
602         .iop_size       = xfs_bui_item_size,
603         .iop_format     = xfs_bui_item_format,
604         .iop_unpin      = xfs_bui_item_unpin,
605         .iop_release    = xfs_bui_item_release,
606         .iop_recover    = xfs_bui_item_recover,
607         .iop_match      = xfs_bui_item_match,
608         .iop_relog      = xfs_bui_item_relog,
609 };
610
611 /*
612  * Copy an BUI format buffer from the given buf, and into the destination
613  * BUI format structure.  The BUI/BUD items were designed not to need any
614  * special alignment handling.
615  */
616 static int
617 xfs_bui_copy_format(
618         struct xfs_log_iovec            *buf,
619         struct xfs_bui_log_format       *dst_bui_fmt)
620 {
621         struct xfs_bui_log_format       *src_bui_fmt;
622         uint                            len;
623
624         src_bui_fmt = buf->i_addr;
625         len = xfs_bui_log_format_sizeof(src_bui_fmt->bui_nextents);
626
627         if (buf->i_len == len) {
628                 memcpy(dst_bui_fmt, src_bui_fmt, len);
629                 return 0;
630         }
631         XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
632         return -EFSCORRUPTED;
633 }
634
635 /*
636  * This routine is called to create an in-core extent bmap update
637  * item from the bui format structure which was logged on disk.
638  * It allocates an in-core bui, copies the extents from the format
639  * structure into it, and adds the bui to the AIL with the given
640  * LSN.
641  */
642 STATIC int
643 xlog_recover_bui_commit_pass2(
644         struct xlog                     *log,
645         struct list_head                *buffer_list,
646         struct xlog_recover_item        *item,
647         xfs_lsn_t                       lsn)
648 {
649         int                             error;
650         struct xfs_mount                *mp = log->l_mp;
651         struct xfs_bui_log_item         *buip;
652         struct xfs_bui_log_format       *bui_formatp;
653
654         bui_formatp = item->ri_buf[0].i_addr;
655
656         if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
657                 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
658                 return -EFSCORRUPTED;
659         }
660         buip = xfs_bui_init(mp);
661         error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format);
662         if (error) {
663                 xfs_bui_item_free(buip);
664                 return error;
665         }
666         atomic_set(&buip->bui_next_extent, bui_formatp->bui_nextents);
667         /*
668          * Insert the intent into the AIL directly and drop one reference so
669          * that finishing or canceling the work will drop the other.
670          */
671         xfs_trans_ail_insert(log->l_ailp, &buip->bui_item, lsn);
672         xfs_bui_release(buip);
673         return 0;
674 }
675
676 const struct xlog_recover_item_ops xlog_bui_item_ops = {
677         .item_type              = XFS_LI_BUI,
678         .commit_pass2           = xlog_recover_bui_commit_pass2,
679 };
680
681 /*
682  * This routine is called when an BUD format structure is found in a committed
683  * transaction in the log. Its purpose is to cancel the corresponding BUI if it
684  * was still in the log. To do this it searches the AIL for the BUI with an id
685  * equal to that in the BUD format structure. If we find it we drop the BUD
686  * reference, which removes the BUI from the AIL and frees it.
687  */
688 STATIC int
689 xlog_recover_bud_commit_pass2(
690         struct xlog                     *log,
691         struct list_head                *buffer_list,
692         struct xlog_recover_item        *item,
693         xfs_lsn_t                       lsn)
694 {
695         struct xfs_bud_log_format       *bud_formatp;
696
697         bud_formatp = item->ri_buf[0].i_addr;
698         if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) {
699                 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
700                 return -EFSCORRUPTED;
701         }
702
703         xlog_recover_release_intent(log, XFS_LI_BUI, bud_formatp->bud_bui_id);
704         return 0;
705 }
706
707 const struct xlog_recover_item_ops xlog_bud_item_ops = {
708         .item_type              = XFS_LI_BUD,
709         .commit_pass2           = xlog_recover_bud_commit_pass2,
710 };