hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/xfs/xfs_bmap_item.c
....@@ -9,34 +9,38 @@
99 #include "xfs_log_format.h"
1010 #include "xfs_trans_resv.h"
1111 #include "xfs_bit.h"
12
+#include "xfs_shared.h"
1213 #include "xfs_mount.h"
1314 #include "xfs_defer.h"
1415 #include "xfs_inode.h"
1516 #include "xfs_trans.h"
1617 #include "xfs_trans_priv.h"
17
-#include "xfs_buf_item.h"
1818 #include "xfs_bmap_item.h"
1919 #include "xfs_log.h"
2020 #include "xfs_bmap.h"
2121 #include "xfs_icache.h"
22
-#include "xfs_trace.h"
2322 #include "xfs_bmap_btree.h"
2423 #include "xfs_trans_space.h"
25
-
24
+#include "xfs_error.h"
25
+#include "xfs_log_priv.h"
26
+#include "xfs_log_recover.h"
27
+#include "xfs_quota.h"
2628
2729 kmem_zone_t *xfs_bui_zone;
2830 kmem_zone_t *xfs_bud_zone;
31
+
32
+static const struct xfs_item_ops xfs_bui_item_ops;
2933
3034 static inline struct xfs_bui_log_item *BUI_ITEM(struct xfs_log_item *lip)
3135 {
3236 return container_of(lip, struct xfs_bui_log_item, bui_item);
3337 }
3438
35
-void
39
+STATIC void
3640 xfs_bui_item_free(
3741 struct xfs_bui_log_item *buip)
3842 {
39
- kmem_zone_free(xfs_bui_zone, buip);
43
+ kmem_cache_free(xfs_bui_zone, buip);
4044 }
4145
4246 /*
....@@ -46,13 +50,13 @@
4650 * committed vs unpin operations in bulk insert operations. Hence the reference
4751 * count to ensure only the last caller frees the BUI.
4852 */
49
-void
53
+STATIC void
5054 xfs_bui_release(
5155 struct xfs_bui_log_item *buip)
5256 {
5357 ASSERT(atomic_read(&buip->bui_refcount) > 0);
5458 if (atomic_dec_and_test(&buip->bui_refcount)) {
55
- xfs_trans_ail_remove(&buip->bui_item, SHUTDOWN_LOG_IO_ERROR);
59
+ xfs_trans_ail_delete(&buip->bui_item, SHUTDOWN_LOG_IO_ERROR);
5660 xfs_bui_item_free(buip);
5761 }
5862 }
....@@ -96,15 +100,6 @@
96100 }
97101
98102 /*
99
- * Pinning has no meaning for an bui item, so just return.
100
- */
101
-STATIC void
102
-xfs_bui_item_pin(
103
- struct xfs_log_item *lip)
104
-{
105
-}
106
-
107
-/*
108103 * The unpin operation is the last place an BUI is manipulated in the log. It is
109104 * either inserted in the AIL or aborted in the event of a log I/O error. In
110105 * either case, the BUI transaction has been successfully committed to make it
....@@ -123,84 +118,28 @@
123118 }
124119
125120 /*
126
- * BUI items have no locking or pushing. However, since BUIs are pulled from
127
- * the AIL when their corresponding BUDs are committed to disk, their situation
128
- * is very similar to being pinned. Return XFS_ITEM_PINNED so that the caller
129
- * will eventually flush the log. This should help in getting the BUI out of
130
- * the AIL.
131
- */
132
-STATIC uint
133
-xfs_bui_item_push(
134
- struct xfs_log_item *lip,
135
- struct list_head *buffer_list)
136
-{
137
- return XFS_ITEM_PINNED;
138
-}
139
-
140
-/*
141121 * The BUI has been either committed or aborted if the transaction has been
142122 * cancelled. If the transaction was cancelled, an BUD isn't going to be
143123 * constructed and thus we free the BUI here directly.
144124 */
145125 STATIC void
146
-xfs_bui_item_unlock(
126
+xfs_bui_item_release(
147127 struct xfs_log_item *lip)
148128 {
149
- if (test_bit(XFS_LI_ABORTED, &lip->li_flags))
150
- xfs_bui_release(BUI_ITEM(lip));
129
+ xfs_bui_release(BUI_ITEM(lip));
151130 }
152
-
153
-/*
154
- * The BUI is logged only once and cannot be moved in the log, so simply return
155
- * the lsn at which it's been logged.
156
- */
157
-STATIC xfs_lsn_t
158
-xfs_bui_item_committed(
159
- struct xfs_log_item *lip,
160
- xfs_lsn_t lsn)
161
-{
162
- return lsn;
163
-}
164
-
165
-/*
166
- * The BUI dependency tracking op doesn't do squat. It can't because
167
- * it doesn't know where the free extent is coming from. The dependency
168
- * tracking has to be handled by the "enclosing" metadata object. For
169
- * example, for inodes, the inode is locked throughout the extent freeing
170
- * so the dependency should be recorded there.
171
- */
172
-STATIC void
173
-xfs_bui_item_committing(
174
- struct xfs_log_item *lip,
175
- xfs_lsn_t lsn)
176
-{
177
-}
178
-
179
-/*
180
- * This is the ops vector shared by all bui log items.
181
- */
182
-static const struct xfs_item_ops xfs_bui_item_ops = {
183
- .iop_size = xfs_bui_item_size,
184
- .iop_format = xfs_bui_item_format,
185
- .iop_pin = xfs_bui_item_pin,
186
- .iop_unpin = xfs_bui_item_unpin,
187
- .iop_unlock = xfs_bui_item_unlock,
188
- .iop_committed = xfs_bui_item_committed,
189
- .iop_push = xfs_bui_item_push,
190
- .iop_committing = xfs_bui_item_committing,
191
-};
192131
193132 /*
194133 * Allocate and initialize an bui item with the given number of extents.
195134 */
196
-struct xfs_bui_log_item *
135
+STATIC struct xfs_bui_log_item *
197136 xfs_bui_init(
198137 struct xfs_mount *mp)
199138
200139 {
201140 struct xfs_bui_log_item *buip;
202141
203
- buip = kmem_zone_zalloc(xfs_bui_zone, KM_SLEEP);
142
+ buip = kmem_cache_zalloc(xfs_bui_zone, GFP_KERNEL | __GFP_NOFAIL);
204143
205144 xfs_log_item_init(mp, &buip->bui_item, XFS_LI_BUI, &xfs_bui_item_ops);
206145 buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS;
....@@ -249,159 +188,262 @@
249188 }
250189
251190 /*
252
- * Pinning has no meaning for an bud item, so just return.
253
- */
254
-STATIC void
255
-xfs_bud_item_pin(
256
- struct xfs_log_item *lip)
257
-{
258
-}
259
-
260
-/*
261
- * Since pinning has no meaning for an bud item, unpinning does
262
- * not either.
263
- */
264
-STATIC void
265
-xfs_bud_item_unpin(
266
- struct xfs_log_item *lip,
267
- int remove)
268
-{
269
-}
270
-
271
-/*
272
- * There isn't much you can do to push on an bud item. It is simply stuck
273
- * waiting for the log to be flushed to disk.
274
- */
275
-STATIC uint
276
-xfs_bud_item_push(
277
- struct xfs_log_item *lip,
278
- struct list_head *buffer_list)
279
-{
280
- return XFS_ITEM_PINNED;
281
-}
282
-
283
-/*
284191 * The BUD is either committed or aborted if the transaction is cancelled. If
285192 * the transaction is cancelled, drop our reference to the BUI and free the
286193 * BUD.
287194 */
288195 STATIC void
289
-xfs_bud_item_unlock(
196
+xfs_bud_item_release(
290197 struct xfs_log_item *lip)
291198 {
292199 struct xfs_bud_log_item *budp = BUD_ITEM(lip);
293200
294
- if (test_bit(XFS_LI_ABORTED, &lip->li_flags)) {
295
- xfs_bui_release(budp->bud_buip);
296
- kmem_zone_free(xfs_bud_zone, budp);
297
- }
298
-}
299
-
300
-/*
301
- * When the bud item is committed to disk, all we need to do is delete our
302
- * reference to our partner bui item and then free ourselves. Since we're
303
- * freeing ourselves we must return -1 to keep the transaction code from
304
- * further referencing this item.
305
- */
306
-STATIC xfs_lsn_t
307
-xfs_bud_item_committed(
308
- struct xfs_log_item *lip,
309
- xfs_lsn_t lsn)
310
-{
311
- struct xfs_bud_log_item *budp = BUD_ITEM(lip);
312
-
313
- /*
314
- * Drop the BUI reference regardless of whether the BUD has been
315
- * aborted. Once the BUD transaction is constructed, it is the sole
316
- * responsibility of the BUD to release the BUI (even if the BUI is
317
- * aborted due to log I/O error).
318
- */
319201 xfs_bui_release(budp->bud_buip);
320
- kmem_zone_free(xfs_bud_zone, budp);
321
-
322
- return (xfs_lsn_t)-1;
202
+ kmem_cache_free(xfs_bud_zone, budp);
323203 }
324204
325
-/*
326
- * The BUD dependency tracking op doesn't do squat. It can't because
327
- * it doesn't know where the free extent is coming from. The dependency
328
- * tracking has to be handled by the "enclosing" metadata object. For
329
- * example, for inodes, the inode is locked throughout the extent freeing
330
- * so the dependency should be recorded there.
331
- */
332
-STATIC void
333
-xfs_bud_item_committing(
334
- struct xfs_log_item *lip,
335
- xfs_lsn_t lsn)
336
-{
337
-}
338
-
339
-/*
340
- * This is the ops vector shared by all bud log items.
341
- */
342205 static const struct xfs_item_ops xfs_bud_item_ops = {
206
+ .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED,
343207 .iop_size = xfs_bud_item_size,
344208 .iop_format = xfs_bud_item_format,
345
- .iop_pin = xfs_bud_item_pin,
346
- .iop_unpin = xfs_bud_item_unpin,
347
- .iop_unlock = xfs_bud_item_unlock,
348
- .iop_committed = xfs_bud_item_committed,
349
- .iop_push = xfs_bud_item_push,
350
- .iop_committing = xfs_bud_item_committing,
209
+ .iop_release = xfs_bud_item_release,
351210 };
352211
353
-/*
354
- * Allocate and initialize an bud item with the given number of extents.
355
- */
356
-struct xfs_bud_log_item *
357
-xfs_bud_init(
358
- struct xfs_mount *mp,
212
+static struct xfs_bud_log_item *
213
+xfs_trans_get_bud(
214
+ struct xfs_trans *tp,
359215 struct xfs_bui_log_item *buip)
360
-
361216 {
362
- struct xfs_bud_log_item *budp;
217
+ struct xfs_bud_log_item *budp;
363218
364
- budp = kmem_zone_zalloc(xfs_bud_zone, KM_SLEEP);
365
- xfs_log_item_init(mp, &budp->bud_item, XFS_LI_BUD, &xfs_bud_item_ops);
219
+ budp = kmem_cache_zalloc(xfs_bud_zone, GFP_KERNEL | __GFP_NOFAIL);
220
+ xfs_log_item_init(tp->t_mountp, &budp->bud_item, XFS_LI_BUD,
221
+ &xfs_bud_item_ops);
366222 budp->bud_buip = buip;
367223 budp->bud_format.bud_bui_id = buip->bui_format.bui_id;
368224
225
+ xfs_trans_add_item(tp, &budp->bud_item);
369226 return budp;
370227 }
228
+
229
+/*
230
+ * Finish an bmap update and log it to the BUD. Note that the
231
+ * transaction is marked dirty regardless of whether the bmap update
232
+ * succeeds or fails to support the BUI/BUD lifecycle rules.
233
+ */
234
+static int
235
+xfs_trans_log_finish_bmap_update(
236
+ struct xfs_trans *tp,
237
+ struct xfs_bud_log_item *budp,
238
+ enum xfs_bmap_intent_type type,
239
+ struct xfs_inode *ip,
240
+ int whichfork,
241
+ xfs_fileoff_t startoff,
242
+ xfs_fsblock_t startblock,
243
+ xfs_filblks_t *blockcount,
244
+ xfs_exntst_t state)
245
+{
246
+ int error;
247
+
248
+ error = xfs_bmap_finish_one(tp, ip, type, whichfork, startoff,
249
+ startblock, blockcount, state);
250
+
251
+ /*
252
+ * Mark the transaction dirty, even on error. This ensures the
253
+ * transaction is aborted, which:
254
+ *
255
+ * 1.) releases the BUI and frees the BUD
256
+ * 2.) shuts down the filesystem
257
+ */
258
+ tp->t_flags |= XFS_TRANS_DIRTY;
259
+ set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
260
+
261
+ return error;
262
+}
263
+
264
+/* Sort bmap intents by inode. */
265
+static int
266
+xfs_bmap_update_diff_items(
267
+ void *priv,
268
+ struct list_head *a,
269
+ struct list_head *b)
270
+{
271
+ struct xfs_bmap_intent *ba;
272
+ struct xfs_bmap_intent *bb;
273
+
274
+ ba = container_of(a, struct xfs_bmap_intent, bi_list);
275
+ bb = container_of(b, struct xfs_bmap_intent, bi_list);
276
+ return ba->bi_owner->i_ino - bb->bi_owner->i_ino;
277
+}
278
+
279
+/* Set the map extent flags for this mapping. */
280
+static void
281
+xfs_trans_set_bmap_flags(
282
+ struct xfs_map_extent *bmap,
283
+ enum xfs_bmap_intent_type type,
284
+ int whichfork,
285
+ xfs_exntst_t state)
286
+{
287
+ bmap->me_flags = 0;
288
+ switch (type) {
289
+ case XFS_BMAP_MAP:
290
+ case XFS_BMAP_UNMAP:
291
+ bmap->me_flags = type;
292
+ break;
293
+ default:
294
+ ASSERT(0);
295
+ }
296
+ if (state == XFS_EXT_UNWRITTEN)
297
+ bmap->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN;
298
+ if (whichfork == XFS_ATTR_FORK)
299
+ bmap->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK;
300
+}
301
+
302
+/* Log bmap updates in the intent item. */
303
+STATIC void
304
+xfs_bmap_update_log_item(
305
+ struct xfs_trans *tp,
306
+ struct xfs_bui_log_item *buip,
307
+ struct xfs_bmap_intent *bmap)
308
+{
309
+ uint next_extent;
310
+ struct xfs_map_extent *map;
311
+
312
+ tp->t_flags |= XFS_TRANS_DIRTY;
313
+ set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
314
+
315
+ /*
316
+ * atomic_inc_return gives us the value after the increment;
317
+ * we want to use it as an array index so we need to subtract 1 from
318
+ * it.
319
+ */
320
+ next_extent = atomic_inc_return(&buip->bui_next_extent) - 1;
321
+ ASSERT(next_extent < buip->bui_format.bui_nextents);
322
+ map = &buip->bui_format.bui_extents[next_extent];
323
+ map->me_owner = bmap->bi_owner->i_ino;
324
+ map->me_startblock = bmap->bi_bmap.br_startblock;
325
+ map->me_startoff = bmap->bi_bmap.br_startoff;
326
+ map->me_len = bmap->bi_bmap.br_blockcount;
327
+ xfs_trans_set_bmap_flags(map, bmap->bi_type, bmap->bi_whichfork,
328
+ bmap->bi_bmap.br_state);
329
+}
330
+
331
+static struct xfs_log_item *
332
+xfs_bmap_update_create_intent(
333
+ struct xfs_trans *tp,
334
+ struct list_head *items,
335
+ unsigned int count,
336
+ bool sort)
337
+{
338
+ struct xfs_mount *mp = tp->t_mountp;
339
+ struct xfs_bui_log_item *buip = xfs_bui_init(mp);
340
+ struct xfs_bmap_intent *bmap;
341
+
342
+ ASSERT(count == XFS_BUI_MAX_FAST_EXTENTS);
343
+
344
+ xfs_trans_add_item(tp, &buip->bui_item);
345
+ if (sort)
346
+ list_sort(mp, items, xfs_bmap_update_diff_items);
347
+ list_for_each_entry(bmap, items, bi_list)
348
+ xfs_bmap_update_log_item(tp, buip, bmap);
349
+ return &buip->bui_item;
350
+}
351
+
352
+/* Get an BUD so we can process all the deferred rmap updates. */
353
+static struct xfs_log_item *
354
+xfs_bmap_update_create_done(
355
+ struct xfs_trans *tp,
356
+ struct xfs_log_item *intent,
357
+ unsigned int count)
358
+{
359
+ return &xfs_trans_get_bud(tp, BUI_ITEM(intent))->bud_item;
360
+}
361
+
362
+/* Process a deferred rmap update. */
363
+STATIC int
364
+xfs_bmap_update_finish_item(
365
+ struct xfs_trans *tp,
366
+ struct xfs_log_item *done,
367
+ struct list_head *item,
368
+ struct xfs_btree_cur **state)
369
+{
370
+ struct xfs_bmap_intent *bmap;
371
+ xfs_filblks_t count;
372
+ int error;
373
+
374
+ bmap = container_of(item, struct xfs_bmap_intent, bi_list);
375
+ count = bmap->bi_bmap.br_blockcount;
376
+ error = xfs_trans_log_finish_bmap_update(tp, BUD_ITEM(done),
377
+ bmap->bi_type,
378
+ bmap->bi_owner, bmap->bi_whichfork,
379
+ bmap->bi_bmap.br_startoff,
380
+ bmap->bi_bmap.br_startblock,
381
+ &count,
382
+ bmap->bi_bmap.br_state);
383
+ if (!error && count > 0) {
384
+ ASSERT(bmap->bi_type == XFS_BMAP_UNMAP);
385
+ bmap->bi_bmap.br_blockcount = count;
386
+ return -EAGAIN;
387
+ }
388
+ kmem_free(bmap);
389
+ return error;
390
+}
391
+
392
+/* Abort all pending BUIs. */
393
+STATIC void
394
+xfs_bmap_update_abort_intent(
395
+ struct xfs_log_item *intent)
396
+{
397
+ xfs_bui_release(BUI_ITEM(intent));
398
+}
399
+
400
+/* Cancel a deferred rmap update. */
401
+STATIC void
402
+xfs_bmap_update_cancel_item(
403
+ struct list_head *item)
404
+{
405
+ struct xfs_bmap_intent *bmap;
406
+
407
+ bmap = container_of(item, struct xfs_bmap_intent, bi_list);
408
+ kmem_free(bmap);
409
+}
410
+
411
+const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
412
+ .max_items = XFS_BUI_MAX_FAST_EXTENTS,
413
+ .create_intent = xfs_bmap_update_create_intent,
414
+ .abort_intent = xfs_bmap_update_abort_intent,
415
+ .create_done = xfs_bmap_update_create_done,
416
+ .finish_item = xfs_bmap_update_finish_item,
417
+ .cancel_item = xfs_bmap_update_cancel_item,
418
+};
371419
372420 /*
373421 * Process a bmap update intent item that was recovered from the log.
374422 * We need to update some inode's bmbt.
375423 */
376
-int
377
-xfs_bui_recover(
378
- struct xfs_trans *parent_tp,
379
- struct xfs_bui_log_item *buip)
424
+STATIC int
425
+xfs_bui_item_recover(
426
+ struct xfs_log_item *lip,
427
+ struct list_head *capture_list)
380428 {
381
- int error = 0;
382
- unsigned int bui_type;
429
+ struct xfs_bmbt_irec irec;
430
+ struct xfs_bui_log_item *buip = BUI_ITEM(lip);
431
+ struct xfs_trans *tp;
432
+ struct xfs_inode *ip = NULL;
433
+ struct xfs_mount *mp = lip->li_mountp;
383434 struct xfs_map_extent *bmap;
435
+ struct xfs_bud_log_item *budp;
384436 xfs_fsblock_t startblock_fsb;
385437 xfs_fsblock_t inode_fsb;
386438 xfs_filblks_t count;
387
- bool op_ok;
388
- struct xfs_bud_log_item *budp;
389
- enum xfs_bmap_intent_type type;
390
- int whichfork;
391439 xfs_exntst_t state;
392
- struct xfs_trans *tp;
393
- struct xfs_inode *ip = NULL;
394
- struct xfs_bmbt_irec irec;
395
- struct xfs_mount *mp = parent_tp->t_mountp;
396
-
397
- ASSERT(!test_bit(XFS_BUI_RECOVERED, &buip->bui_flags));
440
+ unsigned int bui_type;
441
+ int whichfork;
442
+ int error = 0;
398443
399444 /* Only one mapping operation per BUI... */
400
- if (buip->bui_format.bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
401
- set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
402
- xfs_bui_release(buip);
403
- return -EIO;
404
- }
445
+ if (buip->bui_format.bui_nextents != XFS_BUI_MAX_FAST_EXTENTS)
446
+ return -EFSCORRUPTED;
405447
406448 /*
407449 * First check the validity of the extent described by the
....@@ -412,52 +454,6 @@
412454 XFS_FSB_TO_DADDR(mp, bmap->me_startblock));
413455 inode_fsb = XFS_BB_TO_FSB(mp, XFS_FSB_TO_DADDR(mp,
414456 XFS_INO_TO_FSB(mp, bmap->me_owner)));
415
- switch (bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) {
416
- case XFS_BMAP_MAP:
417
- case XFS_BMAP_UNMAP:
418
- op_ok = true;
419
- break;
420
- default:
421
- op_ok = false;
422
- break;
423
- }
424
- if (!op_ok || startblock_fsb == 0 ||
425
- bmap->me_len == 0 ||
426
- inode_fsb == 0 ||
427
- startblock_fsb >= mp->m_sb.sb_dblocks ||
428
- bmap->me_len >= mp->m_sb.sb_agblocks ||
429
- inode_fsb >= mp->m_sb.sb_dblocks ||
430
- (bmap->me_flags & ~XFS_BMAP_EXTENT_FLAGS)) {
431
- /*
432
- * This will pull the BUI from the AIL and
433
- * free the memory associated with it.
434
- */
435
- set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
436
- xfs_bui_release(buip);
437
- return -EIO;
438
- }
439
-
440
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
441
- XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
442
- if (error)
443
- return error;
444
- /*
445
- * Recovery stashes all deferred ops during intent processing and
446
- * finishes them on completion. Transfer current dfops state to this
447
- * transaction and transfer the result back before we return.
448
- */
449
- xfs_defer_move(tp, parent_tp);
450
- budp = xfs_trans_get_bud(tp, buip);
451
-
452
- /* Grab the inode. */
453
- error = xfs_iget(mp, tp, bmap->me_owner, 0, XFS_ILOCK_EXCL, &ip);
454
- if (error)
455
- goto err_inode;
456
-
457
- if (VFS_I(ip)->i_nlink == 0)
458
- xfs_iflags_set(ip, XFS_IRECOVERY);
459
-
460
- /* Process deferred bmap item. */
461457 state = (bmap->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ?
462458 XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
463459 whichfork = (bmap->me_flags & XFS_BMAP_EXTENT_ATTR_FORK) ?
....@@ -466,45 +462,219 @@
466462 switch (bui_type) {
467463 case XFS_BMAP_MAP:
468464 case XFS_BMAP_UNMAP:
469
- type = bui_type;
470465 break;
471466 default:
472
- error = -EFSCORRUPTED;
473
- goto err_inode;
467
+ return -EFSCORRUPTED;
474468 }
469
+ if (startblock_fsb == 0 ||
470
+ bmap->me_len == 0 ||
471
+ inode_fsb == 0 ||
472
+ startblock_fsb >= mp->m_sb.sb_dblocks ||
473
+ bmap->me_len >= mp->m_sb.sb_agblocks ||
474
+ inode_fsb >= mp->m_sb.sb_dblocks ||
475
+ (bmap->me_flags & ~XFS_BMAP_EXTENT_FLAGS))
476
+ return -EFSCORRUPTED;
477
+
478
+ /* Grab the inode. */
479
+ error = xfs_iget(mp, NULL, bmap->me_owner, 0, 0, &ip);
480
+ if (error)
481
+ return error;
482
+
483
+ error = xfs_qm_dqattach(ip);
484
+ if (error)
485
+ goto err_rele;
486
+
487
+ if (VFS_I(ip)->i_nlink == 0)
488
+ xfs_iflags_set(ip, XFS_IRECOVERY);
489
+
490
+ /* Allocate transaction and do the work. */
491
+ error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
492
+ XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
493
+ if (error)
494
+ goto err_rele;
495
+
496
+ budp = xfs_trans_get_bud(tp, buip);
497
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
475498 xfs_trans_ijoin(tp, ip, 0);
476499
477500 count = bmap->me_len;
478
- error = xfs_trans_log_finish_bmap_update(tp, budp, type, ip, whichfork,
479
- bmap->me_startoff, bmap->me_startblock, &count, state);
501
+ error = xfs_trans_log_finish_bmap_update(tp, budp, bui_type, ip,
502
+ whichfork, bmap->me_startoff, bmap->me_startblock,
503
+ &count, state);
480504 if (error)
481
- goto err_inode;
505
+ goto err_cancel;
482506
483507 if (count > 0) {
484
- ASSERT(type == XFS_BMAP_UNMAP);
508
+ ASSERT(bui_type == XFS_BMAP_UNMAP);
485509 irec.br_startblock = bmap->me_startblock;
486510 irec.br_blockcount = count;
487511 irec.br_startoff = bmap->me_startoff;
488512 irec.br_state = state;
489
- error = xfs_bmap_unmap_extent(tp, ip, &irec);
490
- if (error)
491
- goto err_inode;
513
+ xfs_bmap_unmap_extent(tp, ip, &irec);
492514 }
493515
494
- set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
495
- xfs_defer_move(parent_tp, tp);
496
- error = xfs_trans_commit(tp);
516
+ /*
517
+ * Commit transaction, which frees the transaction and saves the inode
518
+ * for later replay activities.
519
+ */
520
+ error = xfs_defer_ops_capture_and_commit(tp, ip, capture_list);
521
+ if (error)
522
+ goto err_unlock;
523
+
497524 xfs_iunlock(ip, XFS_ILOCK_EXCL);
498525 xfs_irele(ip);
526
+ return 0;
499527
500
- return error;
501
-
502
-err_inode:
503
- xfs_defer_move(parent_tp, tp);
528
+err_cancel:
504529 xfs_trans_cancel(tp);
505
- if (ip) {
506
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
507
- xfs_irele(ip);
508
- }
530
+err_unlock:
531
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
532
+err_rele:
533
+ xfs_irele(ip);
509534 return error;
510535 }
536
+
537
+STATIC bool
538
+xfs_bui_item_match(
539
+ struct xfs_log_item *lip,
540
+ uint64_t intent_id)
541
+{
542
+ return BUI_ITEM(lip)->bui_format.bui_id == intent_id;
543
+}
544
+
545
+/* Relog an intent item to push the log tail forward. */
546
+static struct xfs_log_item *
547
+xfs_bui_item_relog(
548
+ struct xfs_log_item *intent,
549
+ struct xfs_trans *tp)
550
+{
551
+ struct xfs_bud_log_item *budp;
552
+ struct xfs_bui_log_item *buip;
553
+ struct xfs_map_extent *extp;
554
+ unsigned int count;
555
+
556
+ count = BUI_ITEM(intent)->bui_format.bui_nextents;
557
+ extp = BUI_ITEM(intent)->bui_format.bui_extents;
558
+
559
+ tp->t_flags |= XFS_TRANS_DIRTY;
560
+ budp = xfs_trans_get_bud(tp, BUI_ITEM(intent));
561
+ set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
562
+
563
+ buip = xfs_bui_init(tp->t_mountp);
564
+ memcpy(buip->bui_format.bui_extents, extp, count * sizeof(*extp));
565
+ atomic_set(&buip->bui_next_extent, count);
566
+ xfs_trans_add_item(tp, &buip->bui_item);
567
+ set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
568
+ return &buip->bui_item;
569
+}
570
+
571
+static const struct xfs_item_ops xfs_bui_item_ops = {
572
+ .iop_size = xfs_bui_item_size,
573
+ .iop_format = xfs_bui_item_format,
574
+ .iop_unpin = xfs_bui_item_unpin,
575
+ .iop_release = xfs_bui_item_release,
576
+ .iop_recover = xfs_bui_item_recover,
577
+ .iop_match = xfs_bui_item_match,
578
+ .iop_relog = xfs_bui_item_relog,
579
+};
580
+
581
+/*
582
+ * Copy an BUI format buffer from the given buf, and into the destination
583
+ * BUI format structure. The BUI/BUD items were designed not to need any
584
+ * special alignment handling.
585
+ */
586
+static int
587
+xfs_bui_copy_format(
588
+ struct xfs_log_iovec *buf,
589
+ struct xfs_bui_log_format *dst_bui_fmt)
590
+{
591
+ struct xfs_bui_log_format *src_bui_fmt;
592
+ uint len;
593
+
594
+ src_bui_fmt = buf->i_addr;
595
+ len = xfs_bui_log_format_sizeof(src_bui_fmt->bui_nextents);
596
+
597
+ if (buf->i_len == len) {
598
+ memcpy(dst_bui_fmt, src_bui_fmt, len);
599
+ return 0;
600
+ }
601
+ XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
602
+ return -EFSCORRUPTED;
603
+}
604
+
605
+/*
606
+ * This routine is called to create an in-core extent bmap update
607
+ * item from the bui format structure which was logged on disk.
608
+ * It allocates an in-core bui, copies the extents from the format
609
+ * structure into it, and adds the bui to the AIL with the given
610
+ * LSN.
611
+ */
612
+STATIC int
613
+xlog_recover_bui_commit_pass2(
614
+ struct xlog *log,
615
+ struct list_head *buffer_list,
616
+ struct xlog_recover_item *item,
617
+ xfs_lsn_t lsn)
618
+{
619
+ int error;
620
+ struct xfs_mount *mp = log->l_mp;
621
+ struct xfs_bui_log_item *buip;
622
+ struct xfs_bui_log_format *bui_formatp;
623
+
624
+ bui_formatp = item->ri_buf[0].i_addr;
625
+
626
+ if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
627
+ XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
628
+ return -EFSCORRUPTED;
629
+ }
630
+ buip = xfs_bui_init(mp);
631
+ error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format);
632
+ if (error) {
633
+ xfs_bui_item_free(buip);
634
+ return error;
635
+ }
636
+ atomic_set(&buip->bui_next_extent, bui_formatp->bui_nextents);
637
+ /*
638
+ * Insert the intent into the AIL directly and drop one reference so
639
+ * that finishing or canceling the work will drop the other.
640
+ */
641
+ xfs_trans_ail_insert(log->l_ailp, &buip->bui_item, lsn);
642
+ xfs_bui_release(buip);
643
+ return 0;
644
+}
645
+
646
+const struct xlog_recover_item_ops xlog_bui_item_ops = {
647
+ .item_type = XFS_LI_BUI,
648
+ .commit_pass2 = xlog_recover_bui_commit_pass2,
649
+};
650
+
651
+/*
652
+ * This routine is called when an BUD format structure is found in a committed
653
+ * transaction in the log. Its purpose is to cancel the corresponding BUI if it
654
+ * was still in the log. To do this it searches the AIL for the BUI with an id
655
+ * equal to that in the BUD format structure. If we find it we drop the BUD
656
+ * reference, which removes the BUI from the AIL and frees it.
657
+ */
658
+STATIC int
659
+xlog_recover_bud_commit_pass2(
660
+ struct xlog *log,
661
+ struct list_head *buffer_list,
662
+ struct xlog_recover_item *item,
663
+ xfs_lsn_t lsn)
664
+{
665
+ struct xfs_bud_log_format *bud_formatp;
666
+
667
+ bud_formatp = item->ri_buf[0].i_addr;
668
+ if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) {
669
+ XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
670
+ return -EFSCORRUPTED;
671
+ }
672
+
673
+ xlog_recover_release_intent(log, XFS_LI_BUI, bud_formatp->bud_bui_id);
674
+ return 0;
675
+}
676
+
677
+const struct xlog_recover_item_ops xlog_bud_item_ops = {
678
+ .item_type = XFS_LI_BUD,
679
+ .commit_pass2 = xlog_recover_bud_commit_pass2,
680
+};