701 lines · 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_trans.h"16#include "xfs_trans_priv.h"17#include "xfs_rmap_item.h"18#include "xfs_log.h"19#include "xfs_rmap.h"20#include "xfs_error.h"21#include "xfs_log_priv.h"22#include "xfs_log_recover.h"23#include "xfs_ag.h"24#include "xfs_btree.h"25#include "xfs_trace.h"26 27struct kmem_cache *xfs_rui_cache;28struct kmem_cache *xfs_rud_cache;29 30static const struct xfs_item_ops xfs_rui_item_ops;31 32static inline struct xfs_rui_log_item *RUI_ITEM(struct xfs_log_item *lip)33{34 return container_of(lip, struct xfs_rui_log_item, rui_item);35}36 37STATIC void38xfs_rui_item_free(39 struct xfs_rui_log_item *ruip)40{41 kvfree(ruip->rui_item.li_lv_shadow);42 if (ruip->rui_format.rui_nextents > XFS_RUI_MAX_FAST_EXTENTS)43 kfree(ruip);44 else45 kmem_cache_free(xfs_rui_cache, ruip);46}47 48/*49 * Freeing the RUI requires that we remove it from the AIL if it has already50 * been placed there. However, the RUI may not yet have been placed in the AIL51 * when called by xfs_rui_release() from RUD processing due to the ordering of52 * committed vs unpin operations in bulk insert operations. Hence the reference53 * count to ensure only the last caller frees the RUI.54 */55STATIC void56xfs_rui_release(57 struct xfs_rui_log_item *ruip)58{59 ASSERT(atomic_read(&ruip->rui_refcount) > 0);60 if (!atomic_dec_and_test(&ruip->rui_refcount))61 return;62 63 xfs_trans_ail_delete(&ruip->rui_item, 0);64 xfs_rui_item_free(ruip);65}66 67STATIC void68xfs_rui_item_size(69 struct xfs_log_item *lip,70 int *nvecs,71 int *nbytes)72{73 struct xfs_rui_log_item *ruip = RUI_ITEM(lip);74 75 *nvecs += 1;76 *nbytes += xfs_rui_log_format_sizeof(ruip->rui_format.rui_nextents);77}78 79/*80 * This is called to fill in the vector of log iovecs for the81 * given rui log item. We use only 1 iovec, and we point that82 * at the rui_log_format structure embedded in the rui item.83 * It is at this point that we assert that all of the extent84 * slots in the rui item have been filled.85 */86STATIC void87xfs_rui_item_format(88 struct xfs_log_item *lip,89 struct xfs_log_vec *lv)90{91 struct xfs_rui_log_item *ruip = RUI_ITEM(lip);92 struct xfs_log_iovec *vecp = NULL;93 94 ASSERT(atomic_read(&ruip->rui_next_extent) ==95 ruip->rui_format.rui_nextents);96 97 ruip->rui_format.rui_type = XFS_LI_RUI;98 ruip->rui_format.rui_size = 1;99 100 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUI_FORMAT, &ruip->rui_format,101 xfs_rui_log_format_sizeof(ruip->rui_format.rui_nextents));102}103 104/*105 * The unpin operation is the last place an RUI is manipulated in the log. It is106 * either inserted in the AIL or aborted in the event of a log I/O error. In107 * either case, the RUI transaction has been successfully committed to make it108 * this far. Therefore, we expect whoever committed the RUI to either construct109 * and commit the RUD or drop the RUD's reference in the event of error. Simply110 * drop the log's RUI reference now that the log is done with it.111 */112STATIC void113xfs_rui_item_unpin(114 struct xfs_log_item *lip,115 int remove)116{117 struct xfs_rui_log_item *ruip = RUI_ITEM(lip);118 119 xfs_rui_release(ruip);120}121 122/*123 * The RUI has been either committed or aborted if the transaction has been124 * cancelled. If the transaction was cancelled, an RUD isn't going to be125 * constructed and thus we free the RUI here directly.126 */127STATIC void128xfs_rui_item_release(129 struct xfs_log_item *lip)130{131 xfs_rui_release(RUI_ITEM(lip));132}133 134/*135 * Allocate and initialize an rui item with the given number of extents.136 */137STATIC struct xfs_rui_log_item *138xfs_rui_init(139 struct xfs_mount *mp,140 uint nextents)141 142{143 struct xfs_rui_log_item *ruip;144 145 ASSERT(nextents > 0);146 if (nextents > XFS_RUI_MAX_FAST_EXTENTS)147 ruip = kzalloc(xfs_rui_log_item_sizeof(nextents),148 GFP_KERNEL | __GFP_NOFAIL);149 else150 ruip = kmem_cache_zalloc(xfs_rui_cache,151 GFP_KERNEL | __GFP_NOFAIL);152 153 xfs_log_item_init(mp, &ruip->rui_item, XFS_LI_RUI, &xfs_rui_item_ops);154 ruip->rui_format.rui_nextents = nextents;155 ruip->rui_format.rui_id = (uintptr_t)(void *)ruip;156 atomic_set(&ruip->rui_next_extent, 0);157 atomic_set(&ruip->rui_refcount, 2);158 159 return ruip;160}161 162static inline struct xfs_rud_log_item *RUD_ITEM(struct xfs_log_item *lip)163{164 return container_of(lip, struct xfs_rud_log_item, rud_item);165}166 167STATIC void168xfs_rud_item_size(169 struct xfs_log_item *lip,170 int *nvecs,171 int *nbytes)172{173 *nvecs += 1;174 *nbytes += sizeof(struct xfs_rud_log_format);175}176 177/*178 * This is called to fill in the vector of log iovecs for the179 * given rud log item. We use only 1 iovec, and we point that180 * at the rud_log_format structure embedded in the rud item.181 * It is at this point that we assert that all of the extent182 * slots in the rud item have been filled.183 */184STATIC void185xfs_rud_item_format(186 struct xfs_log_item *lip,187 struct xfs_log_vec *lv)188{189 struct xfs_rud_log_item *rudp = RUD_ITEM(lip);190 struct xfs_log_iovec *vecp = NULL;191 192 rudp->rud_format.rud_type = XFS_LI_RUD;193 rudp->rud_format.rud_size = 1;194 195 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUD_FORMAT, &rudp->rud_format,196 sizeof(struct xfs_rud_log_format));197}198 199/*200 * The RUD is either committed or aborted if the transaction is cancelled. If201 * the transaction is cancelled, drop our reference to the RUI and free the202 * RUD.203 */204STATIC void205xfs_rud_item_release(206 struct xfs_log_item *lip)207{208 struct xfs_rud_log_item *rudp = RUD_ITEM(lip);209 210 xfs_rui_release(rudp->rud_ruip);211 kvfree(rudp->rud_item.li_lv_shadow);212 kmem_cache_free(xfs_rud_cache, rudp);213}214 215static struct xfs_log_item *216xfs_rud_item_intent(217 struct xfs_log_item *lip)218{219 return &RUD_ITEM(lip)->rud_ruip->rui_item;220}221 222static const struct xfs_item_ops xfs_rud_item_ops = {223 .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED |224 XFS_ITEM_INTENT_DONE,225 .iop_size = xfs_rud_item_size,226 .iop_format = xfs_rud_item_format,227 .iop_release = xfs_rud_item_release,228 .iop_intent = xfs_rud_item_intent,229};230 231static inline struct xfs_rmap_intent *ri_entry(const struct list_head *e)232{233 return list_entry(e, struct xfs_rmap_intent, ri_list);234}235 236/* Sort rmap intents by AG. */237static int238xfs_rmap_update_diff_items(239 void *priv,240 const struct list_head *a,241 const struct list_head *b)242{243 struct xfs_rmap_intent *ra = ri_entry(a);244 struct xfs_rmap_intent *rb = ri_entry(b);245 246 return ra->ri_pag->pag_agno - rb->ri_pag->pag_agno;247}248 249/* Log rmap updates in the intent item. */250STATIC void251xfs_rmap_update_log_item(252 struct xfs_trans *tp,253 struct xfs_rui_log_item *ruip,254 struct xfs_rmap_intent *ri)255{256 uint next_extent;257 struct xfs_map_extent *map;258 259 /*260 * atomic_inc_return gives us the value after the increment;261 * we want to use it as an array index so we need to subtract 1 from262 * it.263 */264 next_extent = atomic_inc_return(&ruip->rui_next_extent) - 1;265 ASSERT(next_extent < ruip->rui_format.rui_nextents);266 map = &ruip->rui_format.rui_extents[next_extent];267 map->me_owner = ri->ri_owner;268 map->me_startblock = ri->ri_bmap.br_startblock;269 map->me_startoff = ri->ri_bmap.br_startoff;270 map->me_len = ri->ri_bmap.br_blockcount;271 272 map->me_flags = 0;273 if (ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN)274 map->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN;275 if (ri->ri_whichfork == XFS_ATTR_FORK)276 map->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK;277 switch (ri->ri_type) {278 case XFS_RMAP_MAP:279 map->me_flags |= XFS_RMAP_EXTENT_MAP;280 break;281 case XFS_RMAP_MAP_SHARED:282 map->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED;283 break;284 case XFS_RMAP_UNMAP:285 map->me_flags |= XFS_RMAP_EXTENT_UNMAP;286 break;287 case XFS_RMAP_UNMAP_SHARED:288 map->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED;289 break;290 case XFS_RMAP_CONVERT:291 map->me_flags |= XFS_RMAP_EXTENT_CONVERT;292 break;293 case XFS_RMAP_CONVERT_SHARED:294 map->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED;295 break;296 case XFS_RMAP_ALLOC:297 map->me_flags |= XFS_RMAP_EXTENT_ALLOC;298 break;299 case XFS_RMAP_FREE:300 map->me_flags |= XFS_RMAP_EXTENT_FREE;301 break;302 default:303 ASSERT(0);304 }305}306 307static struct xfs_log_item *308xfs_rmap_update_create_intent(309 struct xfs_trans *tp,310 struct list_head *items,311 unsigned int count,312 bool sort)313{314 struct xfs_mount *mp = tp->t_mountp;315 struct xfs_rui_log_item *ruip = xfs_rui_init(mp, count);316 struct xfs_rmap_intent *ri;317 318 ASSERT(count > 0);319 320 if (sort)321 list_sort(mp, items, xfs_rmap_update_diff_items);322 list_for_each_entry(ri, items, ri_list)323 xfs_rmap_update_log_item(tp, ruip, ri);324 return &ruip->rui_item;325}326 327/* Get an RUD so we can process all the deferred rmap updates. */328static struct xfs_log_item *329xfs_rmap_update_create_done(330 struct xfs_trans *tp,331 struct xfs_log_item *intent,332 unsigned int count)333{334 struct xfs_rui_log_item *ruip = RUI_ITEM(intent);335 struct xfs_rud_log_item *rudp;336 337 rudp = kmem_cache_zalloc(xfs_rud_cache, GFP_KERNEL | __GFP_NOFAIL);338 xfs_log_item_init(tp->t_mountp, &rudp->rud_item, XFS_LI_RUD,339 &xfs_rud_item_ops);340 rudp->rud_ruip = ruip;341 rudp->rud_format.rud_rui_id = ruip->rui_format.rui_id;342 343 return &rudp->rud_item;344}345 346/* Add this deferred RUI to the transaction. */347void348xfs_rmap_defer_add(349 struct xfs_trans *tp,350 struct xfs_rmap_intent *ri)351{352 struct xfs_mount *mp = tp->t_mountp;353 354 trace_xfs_rmap_defer(mp, ri);355 356 ri->ri_pag = xfs_perag_intent_get(mp, ri->ri_bmap.br_startblock);357 xfs_defer_add(tp, &ri->ri_list, &xfs_rmap_update_defer_type);358}359 360/* Cancel a deferred rmap update. */361STATIC void362xfs_rmap_update_cancel_item(363 struct list_head *item)364{365 struct xfs_rmap_intent *ri = ri_entry(item);366 367 xfs_perag_intent_put(ri->ri_pag);368 kmem_cache_free(xfs_rmap_intent_cache, ri);369}370 371/* Process a deferred rmap update. */372STATIC int373xfs_rmap_update_finish_item(374 struct xfs_trans *tp,375 struct xfs_log_item *done,376 struct list_head *item,377 struct xfs_btree_cur **state)378{379 struct xfs_rmap_intent *ri = ri_entry(item);380 int error;381 382 error = xfs_rmap_finish_one(tp, ri, state);383 384 xfs_rmap_update_cancel_item(item);385 return error;386}387 388/* Clean up after calling xfs_rmap_finish_one. */389STATIC void390xfs_rmap_finish_one_cleanup(391 struct xfs_trans *tp,392 struct xfs_btree_cur *rcur,393 int error)394{395 struct xfs_buf *agbp = NULL;396 397 if (rcur == NULL)398 return;399 agbp = rcur->bc_ag.agbp;400 xfs_btree_del_cursor(rcur, error);401 if (error && agbp)402 xfs_trans_brelse(tp, agbp);403}404 405/* Abort all pending RUIs. */406STATIC void407xfs_rmap_update_abort_intent(408 struct xfs_log_item *intent)409{410 xfs_rui_release(RUI_ITEM(intent));411}412 413/* Is this recovered RUI ok? */414static inline bool415xfs_rui_validate_map(416 struct xfs_mount *mp,417 struct xfs_map_extent *map)418{419 if (!xfs_has_rmapbt(mp))420 return false;421 422 if (map->me_flags & ~XFS_RMAP_EXTENT_FLAGS)423 return false;424 425 switch (map->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {426 case XFS_RMAP_EXTENT_MAP:427 case XFS_RMAP_EXTENT_MAP_SHARED:428 case XFS_RMAP_EXTENT_UNMAP:429 case XFS_RMAP_EXTENT_UNMAP_SHARED:430 case XFS_RMAP_EXTENT_CONVERT:431 case XFS_RMAP_EXTENT_CONVERT_SHARED:432 case XFS_RMAP_EXTENT_ALLOC:433 case XFS_RMAP_EXTENT_FREE:434 break;435 default:436 return false;437 }438 439 if (!XFS_RMAP_NON_INODE_OWNER(map->me_owner) &&440 !xfs_verify_ino(mp, map->me_owner))441 return false;442 443 if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len))444 return false;445 446 return xfs_verify_fsbext(mp, map->me_startblock, map->me_len);447}448 449static inline void450xfs_rui_recover_work(451 struct xfs_mount *mp,452 struct xfs_defer_pending *dfp,453 const struct xfs_map_extent *map)454{455 struct xfs_rmap_intent *ri;456 457 ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_KERNEL | __GFP_NOFAIL);458 459 switch (map->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {460 case XFS_RMAP_EXTENT_MAP:461 ri->ri_type = XFS_RMAP_MAP;462 break;463 case XFS_RMAP_EXTENT_MAP_SHARED:464 ri->ri_type = XFS_RMAP_MAP_SHARED;465 break;466 case XFS_RMAP_EXTENT_UNMAP:467 ri->ri_type = XFS_RMAP_UNMAP;468 break;469 case XFS_RMAP_EXTENT_UNMAP_SHARED:470 ri->ri_type = XFS_RMAP_UNMAP_SHARED;471 break;472 case XFS_RMAP_EXTENT_CONVERT:473 ri->ri_type = XFS_RMAP_CONVERT;474 break;475 case XFS_RMAP_EXTENT_CONVERT_SHARED:476 ri->ri_type = XFS_RMAP_CONVERT_SHARED;477 break;478 case XFS_RMAP_EXTENT_ALLOC:479 ri->ri_type = XFS_RMAP_ALLOC;480 break;481 case XFS_RMAP_EXTENT_FREE:482 ri->ri_type = XFS_RMAP_FREE;483 break;484 default:485 ASSERT(0);486 return;487 }488 489 ri->ri_owner = map->me_owner;490 ri->ri_whichfork = (map->me_flags & XFS_RMAP_EXTENT_ATTR_FORK) ?491 XFS_ATTR_FORK : XFS_DATA_FORK;492 ri->ri_bmap.br_startblock = map->me_startblock;493 ri->ri_bmap.br_startoff = map->me_startoff;494 ri->ri_bmap.br_blockcount = map->me_len;495 ri->ri_bmap.br_state = (map->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ?496 XFS_EXT_UNWRITTEN : XFS_EXT_NORM;497 ri->ri_pag = xfs_perag_intent_get(mp, map->me_startblock);498 499 xfs_defer_add_item(dfp, &ri->ri_list);500}501 502/*503 * Process an rmap update intent item that was recovered from the log.504 * We need to update the rmapbt.505 */506STATIC int507xfs_rmap_recover_work(508 struct xfs_defer_pending *dfp,509 struct list_head *capture_list)510{511 struct xfs_trans_res resv;512 struct xfs_log_item *lip = dfp->dfp_intent;513 struct xfs_rui_log_item *ruip = RUI_ITEM(lip);514 struct xfs_trans *tp;515 struct xfs_mount *mp = lip->li_log->l_mp;516 int i;517 int error = 0;518 519 /*520 * First check the validity of the extents described by the521 * RUI. If any are bad, then assume that all are bad and522 * just toss the RUI.523 */524 for (i = 0; i < ruip->rui_format.rui_nextents; i++) {525 if (!xfs_rui_validate_map(mp,526 &ruip->rui_format.rui_extents[i])) {527 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,528 &ruip->rui_format,529 sizeof(ruip->rui_format));530 return -EFSCORRUPTED;531 }532 533 xfs_rui_recover_work(mp, dfp, &ruip->rui_format.rui_extents[i]);534 }535 536 resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);537 error = xfs_trans_alloc(mp, &resv, mp->m_rmap_maxlevels, 0,538 XFS_TRANS_RESERVE, &tp);539 if (error)540 return error;541 542 error = xlog_recover_finish_intent(tp, dfp);543 if (error == -EFSCORRUPTED)544 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,545 &ruip->rui_format,546 sizeof(ruip->rui_format));547 if (error)548 goto abort_error;549 550 return xfs_defer_ops_capture_and_commit(tp, capture_list);551 552abort_error:553 xfs_trans_cancel(tp);554 return error;555}556 557/* Relog an intent item to push the log tail forward. */558static struct xfs_log_item *559xfs_rmap_relog_intent(560 struct xfs_trans *tp,561 struct xfs_log_item *intent,562 struct xfs_log_item *done_item)563{564 struct xfs_rui_log_item *ruip;565 struct xfs_map_extent *map;566 unsigned int count;567 568 count = RUI_ITEM(intent)->rui_format.rui_nextents;569 map = RUI_ITEM(intent)->rui_format.rui_extents;570 571 ruip = xfs_rui_init(tp->t_mountp, count);572 memcpy(ruip->rui_format.rui_extents, map, count * sizeof(*map));573 atomic_set(&ruip->rui_next_extent, count);574 575 return &ruip->rui_item;576}577 578const struct xfs_defer_op_type xfs_rmap_update_defer_type = {579 .name = "rmap",580 .max_items = XFS_RUI_MAX_FAST_EXTENTS,581 .create_intent = xfs_rmap_update_create_intent,582 .abort_intent = xfs_rmap_update_abort_intent,583 .create_done = xfs_rmap_update_create_done,584 .finish_item = xfs_rmap_update_finish_item,585 .finish_cleanup = xfs_rmap_finish_one_cleanup,586 .cancel_item = xfs_rmap_update_cancel_item,587 .recover_work = xfs_rmap_recover_work,588 .relog_intent = xfs_rmap_relog_intent,589};590 591STATIC bool592xfs_rui_item_match(593 struct xfs_log_item *lip,594 uint64_t intent_id)595{596 return RUI_ITEM(lip)->rui_format.rui_id == intent_id;597}598 599static const struct xfs_item_ops xfs_rui_item_ops = {600 .flags = XFS_ITEM_INTENT,601 .iop_size = xfs_rui_item_size,602 .iop_format = xfs_rui_item_format,603 .iop_unpin = xfs_rui_item_unpin,604 .iop_release = xfs_rui_item_release,605 .iop_match = xfs_rui_item_match,606};607 608static inline void609xfs_rui_copy_format(610 struct xfs_rui_log_format *dst,611 const struct xfs_rui_log_format *src)612{613 unsigned int i;614 615 memcpy(dst, src, offsetof(struct xfs_rui_log_format, rui_extents));616 617 for (i = 0; i < src->rui_nextents; i++)618 memcpy(&dst->rui_extents[i], &src->rui_extents[i],619 sizeof(struct xfs_map_extent));620}621 622/*623 * This routine is called to create an in-core extent rmap update624 * item from the rui format structure which was logged on disk.625 * It allocates an in-core rui, copies the extents from the format626 * structure into it, and adds the rui to the AIL with the given627 * LSN.628 */629STATIC int630xlog_recover_rui_commit_pass2(631 struct xlog *log,632 struct list_head *buffer_list,633 struct xlog_recover_item *item,634 xfs_lsn_t lsn)635{636 struct xfs_mount *mp = log->l_mp;637 struct xfs_rui_log_item *ruip;638 struct xfs_rui_log_format *rui_formatp;639 size_t len;640 641 rui_formatp = item->ri_buf[0].i_addr;642 643 if (item->ri_buf[0].i_len < xfs_rui_log_format_sizeof(0)) {644 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,645 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);646 return -EFSCORRUPTED;647 }648 649 len = xfs_rui_log_format_sizeof(rui_formatp->rui_nextents);650 if (item->ri_buf[0].i_len != len) {651 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,652 item->ri_buf[0].i_addr, item->ri_buf[0].i_len);653 return -EFSCORRUPTED;654 }655 656 ruip = xfs_rui_init(mp, rui_formatp->rui_nextents);657 xfs_rui_copy_format(&ruip->rui_format, rui_formatp);658 atomic_set(&ruip->rui_next_extent, rui_formatp->rui_nextents);659 660 xlog_recover_intent_item(log, &ruip->rui_item, lsn,661 &xfs_rmap_update_defer_type);662 return 0;663}664 665const struct xlog_recover_item_ops xlog_rui_item_ops = {666 .item_type = XFS_LI_RUI,667 .commit_pass2 = xlog_recover_rui_commit_pass2,668};669 670/*671 * This routine is called when an RUD format structure is found in a committed672 * transaction in the log. Its purpose is to cancel the corresponding RUI if it673 * was still in the log. To do this it searches the AIL for the RUI with an id674 * equal to that in the RUD format structure. If we find it we drop the RUD675 * reference, which removes the RUI from the AIL and frees it.676 */677STATIC int678xlog_recover_rud_commit_pass2(679 struct xlog *log,680 struct list_head *buffer_list,681 struct xlog_recover_item *item,682 xfs_lsn_t lsn)683{684 struct xfs_rud_log_format *rud_formatp;685 686 rud_formatp = item->ri_buf[0].i_addr;687 if (item->ri_buf[0].i_len != sizeof(struct xfs_rud_log_format)) {688 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,689 rud_formatp, item->ri_buf[0].i_len);690 return -EFSCORRUPTED;691 }692 693 xlog_recover_release_intent(log, XFS_LI_RUI, rud_formatp->rud_rui_id);694 return 0;695}696 697const struct xlog_recover_item_ops xlog_rud_item_ops = {698 .item_type = XFS_LI_RUD,699 .commit_pass2 = xlog_recover_rud_commit_pass2,700};701