···258258 xfs_agblock_t wantbno, /* target starting block */259259 xfs_extlen_t wantlen, /* target length */260260 xfs_extlen_t alignment, /* target alignment */261261- char userdata, /* are we allocating data? */261261+ int datatype, /* are we allocating data? */262262 xfs_agblock_t freebno, /* freespace's starting block */263263 xfs_extlen_t freelen, /* freespace's length */264264 xfs_agblock_t *newbnop) /* result: best start block from free */···269269 xfs_extlen_t newlen1=0; /* length with newbno1 */270270 xfs_extlen_t newlen2=0; /* length with newbno2 */271271 xfs_agblock_t wantend; /* end of target extent */272272+ bool userdata = xfs_alloc_is_userdata(datatype);272273273274 ASSERT(freelen >= wantlen);274275 freeend = freebno + freelen;···925924926925 sdiff = xfs_alloc_compute_diff(args->agbno, args->len,927926 args->alignment,928928- args->userdata, *sbnoa,927927+ args->datatype, *sbnoa,929928 *slena, &new);930929931930 /*···11091108 if (args->len < blen)11101109 continue;11111110 ltdiff = xfs_alloc_compute_diff(args->agbno, args->len,11121112- args->alignment, args->userdata, ltbnoa,11111111+ args->alignment, args->datatype, ltbnoa,11131112 ltlena, <new);11141113 if (ltnew != NULLAGBLOCK &&11151114 (args->len > blen || ltdiff < bdiff)) {···12621261 args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);12631262 xfs_alloc_fix_len(args);12641263 ltdiff = xfs_alloc_compute_diff(args->agbno, args->len,12651265- args->alignment, args->userdata, ltbnoa,12641264+ args->alignment, args->datatype, ltbnoa,12661265 ltlena, <new);1267126612681267 error = xfs_alloc_find_best_extent(args,···12791278 args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen);12801279 xfs_alloc_fix_len(args);12811280 gtdiff = xfs_alloc_compute_diff(args->agbno, args->len,12821282- args->alignment, args->userdata, gtbnoa,12811281+ args->alignment, args->datatype, gtbnoa,12831282 gtlena, >new);1284128312851284 error = xfs_alloc_find_best_extent(args,···13391338 }13401339 rlen = args->len;13411340 (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment,13421342- args->userdata, ltbnoa, ltlena, <new);13411341+ args->datatype, ltbnoa, ltlena, <new);13431342 ASSERT(ltnew >= ltbno);13441343 ASSERT(ltnew + rlen <= ltbnoa + ltlena);13451344 ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));···16181617 goto error0;16191618 if (fbno != NULLAGBLOCK) {16201619 xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1,16211621- args->userdata);16201620+ xfs_alloc_allow_busy_reuse(args->datatype));1622162116231623- if (args->userdata) {16221622+ if (xfs_alloc_is_userdata(args->datatype)) {16241623 xfs_buf_t *bp;1625162416261625 bp = xfs_btree_get_bufs(args->mp, args->tp,···21002099 * somewhere else if we are not being asked to try harder at this21012100 * point21022101 */21032103- if (pag->pagf_metadata && args->userdata &&21022102+ if (pag->pagf_metadata && xfs_alloc_is_userdata(args->datatype) &&21042103 (flags & XFS_ALLOC_FLAG_TRYLOCK)) {21052104 ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));21062105 goto out_agbp_relse;···26762675 * Try near allocation first, then anywhere-in-ag after26772676 * the first a.g. fails.26782677 */26792679- if ((args->userdata & XFS_ALLOC_INITIAL_USER_DATA) &&26782678+ if ((args->datatype & XFS_ALLOC_INITIAL_USER_DATA) &&26802679 (mp->m_flags & XFS_MOUNT_32BITINODES)) {26812680 args->fsbno = XFS_AGB_TO_FSB(mp,26822681 ((mp->m_agfrotor / rotorstep) %···28092808#endif2810280928112810 /* Zero the extent if we were asked to do so */28122812- if (args->userdata & XFS_ALLOC_USERDATA_ZERO) {28112811+ if (args->datatype & XFS_ALLOC_USERDATA_ZERO) {28132812 error = xfs_zero_extent(args->ip, args->fsbno, args->len);28142813 if (error)28152814 goto error0;
+15-2
fs/xfs/libxfs/xfs_alloc.h
···8585 xfs_extlen_t len; /* output: actual size of extent */8686 xfs_alloctype_t type; /* allocation type XFS_ALLOCTYPE_... */8787 xfs_alloctype_t otype; /* original allocation type */8888+ int datatype; /* mask defining data type treatment */8889 char wasdel; /* set if allocation was prev delayed */8990 char wasfromfl; /* set if allocation is from freelist */9090- char userdata; /* mask defining userdata treatment */9191 xfs_fsblock_t firstblock; /* io first block allocated */9292 struct xfs_owner_info oinfo; /* owner of blocks being allocated */9393 enum xfs_ag_resv_type resv; /* block reservation to use */9494} xfs_alloc_arg_t;95959696/*9797- * Defines for userdata9797+ * Defines for datatype9898 */9999#define XFS_ALLOC_USERDATA (1 << 0)/* allocation is for user data*/100100#define XFS_ALLOC_INITIAL_USER_DATA (1 << 1)/* special case start of file */101101#define XFS_ALLOC_USERDATA_ZERO (1 << 2)/* zero extent on allocation */102102+#define XFS_ALLOC_NOBUSY (1 << 3)/* Busy extents not allowed */103103+104104+static inline bool105105+xfs_alloc_is_userdata(int datatype)106106+{107107+ return (datatype & ~XFS_ALLOC_NOBUSY) != 0;108108+}109109+110110+static inline bool111111+xfs_alloc_allow_busy_reuse(int datatype)112112+{113113+ return (datatype & XFS_ALLOC_NOBUSY) == 0;114114+}102115103116/* freespace limit calculations */104117#define XFS_ALLOC_AGFL_RESERVE 4
+26-15
fs/xfs/libxfs/xfs_bmap.c
···3348334833493349 mp = ap->ip->i_mount;33503350 nullfb = *ap->firstblock == NULLFSBLOCK;33513351- rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;33513351+ rt = XFS_IS_REALTIME_INODE(ap->ip) &&33523352+ xfs_alloc_is_userdata(ap->datatype);33523353 fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);33533354 /*33543355 * If allocating at eof, and there's a previous real block,···36253624{36263625 xfs_mount_t *mp; /* mount point structure */36273626 xfs_alloctype_t atype = 0; /* type for allocation routines */36283628- xfs_extlen_t align; /* minimum allocation alignment */36273627+ xfs_extlen_t align = 0; /* minimum allocation alignment */36293628 xfs_agnumber_t fb_agno; /* ag number of ap->firstblock */36303629 xfs_agnumber_t ag;36313630 xfs_alloc_arg_t args;···36483647 else if (mp->m_dalign)36493648 stripe_align = mp->m_dalign;3650364936513651- align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;36503650+ if (xfs_alloc_is_userdata(ap->datatype))36513651+ align = xfs_get_extsz_hint(ap->ip);36523652 if (unlikely(align)) {36533653 error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,36543654 align, 0, ap->eof, 0, ap->conv,···36623660 nullfb = *ap->firstblock == NULLFSBLOCK;36633661 fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);36643662 if (nullfb) {36653665- if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {36633663+ if (xfs_alloc_is_userdata(ap->datatype) &&36643664+ xfs_inode_is_filestream(ap->ip)) {36663665 ag = xfs_filestream_lookup_ag(ap->ip);36673666 ag = (ag != NULLAGNUMBER) ? ag : 0;36683667 ap->blkno = XFS_AGB_TO_FSB(mp, ag, 0);···37033700 * enough for the request. If one isn't found, then adjust37043701 * the minimum allocation size to the largest space found.37053702 */37063706- if (ap->userdata && xfs_inode_is_filestream(ap->ip))37033703+ if (xfs_alloc_is_userdata(ap->datatype) &&37043704+ xfs_inode_is_filestream(ap->ip))37073705 error = xfs_bmap_btalloc_filestreams(ap, &args, &blen);37083706 else37093707 error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);···37883784 args.minleft = ap->minleft;37893785 args.wasdel = ap->wasdel;37903786 args.resv = XFS_AG_RESV_NONE;37913791- args.userdata = ap->userdata;37923792- if (ap->userdata & XFS_ALLOC_USERDATA_ZERO)37873787+ args.datatype = ap->datatype;37883788+ if (ap->datatype & XFS_ALLOC_USERDATA_ZERO)37933789 args.ip = ap->ip;3794379037953791 error = xfs_alloc_vextent(&args);···38833879xfs_bmap_alloc(38843880 struct xfs_bmalloca *ap) /* bmap alloc argument struct */38853881{38863886- if (XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata)38823882+ if (XFS_IS_REALTIME_INODE(ap->ip) &&38833883+ xfs_alloc_is_userdata(ap->datatype))38873884 return xfs_bmap_rtalloc(ap);38883885 return xfs_bmap_btalloc(ap);38893886}···42094204 }4210420542114206 /*42124212- * Indicate if this is the first user data in the file, or just any42134213- * user data. And if it is userdata, indicate whether it needs to42144214- * be initialised to zero during allocation.42074207+ * Set the data type being allocated. For the data fork, the first data42084208+ * in the file is treated differently to all other allocations. For the42094209+ * attribute fork, we only need to ensure the allocated range is not on42104210+ * the busy list.42154211 */42164212 if (!(bma->flags & XFS_BMAPI_METADATA)) {42174217- bma->userdata = (bma->offset == 0) ?42184218- XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA;42134213+ bma->datatype = XFS_ALLOC_NOBUSY;42144214+ if (whichfork == XFS_DATA_FORK) {42154215+ if (bma->offset == 0)42164216+ bma->datatype |= XFS_ALLOC_INITIAL_USER_DATA;42174217+ else42184218+ bma->datatype |= XFS_ALLOC_USERDATA;42194219+ }42194220 if (bma->flags & XFS_BMAPI_ZERO)42204220- bma->userdata |= XFS_ALLOC_USERDATA_ZERO;42214221+ bma->datatype |= XFS_ALLOC_USERDATA_ZERO;42214222 }4222422342234224 bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1;···44934482 bma.tp = tp;44944483 bma.ip = ip;44954484 bma.total = total;44964496- bma.userdata = 0;44854485+ bma.datatype = 0;44974486 bma.dfops = dfops;44984487 bma.firstblock = firstblock;44994488
+1-1
fs/xfs/libxfs/xfs_bmap.h
···5454 bool wasdel; /* replacing a delayed allocation */5555 bool aeof; /* allocated space at eof */5656 bool conv; /* overwriting unwritten extents */5757- char userdata;/* userdata mask */5757+ int datatype;/* data type being allocated */5858 int flags;5959};6060
+1-1
fs/xfs/xfs_bmap_util.c
···182182 XFS_TRANS_DQ_RTBCOUNT, (long) ralen);183183184184 /* Zero the extent if we were asked to do so */185185- if (ap->userdata & XFS_ALLOC_USERDATA_ZERO) {185185+ if (ap->datatype & XFS_ALLOC_USERDATA_ZERO) {186186 error = xfs_zero_extent(ap->ip, ap->blkno, ap->length);187187 if (error)188188 return error;
+1-1
fs/xfs/xfs_extent_busy.c
···384384 * If this is a metadata allocation, try to reuse the busy385385 * extent instead of trimming the allocation.386386 */387387- if (!args->userdata &&387387+ if (!xfs_alloc_is_userdata(args->datatype) &&388388 !(busyp->flags & XFS_EXTENT_BUSY_DISCARDED)) {389389 if (!xfs_extent_busy_update_extent(args->mp, args->pag,390390 busyp, fbno, flen,
···4444#include "xfs_error.h"4545#include "xfs_dir2.h"4646#include "xfs_rmap_item.h"4747+#include "xfs_buf_item.h"47484849#define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1)4950···382381 SHUTDOWN_META_IO_ERROR);383382 }384383 }384384+385385+ /*386386+ * On v5 supers, a bli could be attached to update the metadata LSN.387387+ * Clean it up.388388+ */389389+ if (bp->b_fspriv)390390+ xfs_buf_item_relse(bp);391391+ ASSERT(bp->b_fspriv == NULL);392392+385393 bp->b_iodone = NULL;386394 xfs_buf_ioend(bp);387395}···23702360xlog_recover_validate_buf_type(23712361 struct xfs_mount *mp,23722362 struct xfs_buf *bp,23732373- xfs_buf_log_format_t *buf_f)23632363+ xfs_buf_log_format_t *buf_f,23642364+ xfs_lsn_t current_lsn)23742365{23752366 struct xfs_da_blkinfo *info = bp->b_addr;23762367 __uint32_t magic32;23772368 __uint16_t magic16;23782369 __uint16_t magicda;23702370+ char *warnmsg = NULL;2379237123802372 /*23812373 * We can only do post recovery validation on items on CRC enabled···24162404 bp->b_ops = &xfs_rmapbt_buf_ops;24172405 break;24182406 default:24192419- xfs_warn(mp, "Bad btree block magic!");24202420- ASSERT(0);24072407+ warnmsg = "Bad btree block magic!";24212408 break;24222409 }24232410 break;24242411 case XFS_BLFT_AGF_BUF:24252412 if (magic32 != XFS_AGF_MAGIC) {24262426- xfs_warn(mp, "Bad AGF block magic!");24272427- ASSERT(0);24132413+ warnmsg = "Bad AGF block magic!";24282414 break;24292415 }24302416 bp->b_ops = &xfs_agf_buf_ops;24312417 break;24322418 case XFS_BLFT_AGFL_BUF:24332419 if (magic32 != XFS_AGFL_MAGIC) {24342434- xfs_warn(mp, "Bad AGFL block magic!");24352435- ASSERT(0);24202420+ warnmsg = "Bad AGFL block magic!";24362421 break;24372422 }24382423 bp->b_ops = &xfs_agfl_buf_ops;24392424 break;24402425 case XFS_BLFT_AGI_BUF:24412426 if (magic32 != XFS_AGI_MAGIC) {24422442- xfs_warn(mp, "Bad AGI block magic!");24432443- ASSERT(0);24272427+ warnmsg = "Bad AGI block magic!";24442428 break;24452429 }24462430 bp->b_ops = &xfs_agi_buf_ops;···24462438 case XFS_BLFT_GDQUOT_BUF:24472439#ifdef CONFIG_XFS_QUOTA24482440 if (magic16 != XFS_DQUOT_MAGIC) {24492449- xfs_warn(mp, "Bad DQUOT block magic!");24502450- ASSERT(0);24412441+ warnmsg = "Bad DQUOT block magic!";24512442 break;24522443 }24532444 bp->b_ops = &xfs_dquot_buf_ops;···24582451 break;24592452 case XFS_BLFT_DINO_BUF:24602453 if (magic16 != XFS_DINODE_MAGIC) {24612461- xfs_warn(mp, "Bad INODE block magic!");24622462- ASSERT(0);24542454+ warnmsg = "Bad INODE block magic!";24632455 break;24642456 }24652457 bp->b_ops = &xfs_inode_buf_ops;24662458 break;24672459 case XFS_BLFT_SYMLINK_BUF:24682460 if (magic32 != XFS_SYMLINK_MAGIC) {24692469- xfs_warn(mp, "Bad symlink block magic!");24702470- ASSERT(0);24612461+ warnmsg = "Bad symlink block magic!";24712462 break;24722463 }24732464 bp->b_ops = &xfs_symlink_buf_ops;···24732468 case XFS_BLFT_DIR_BLOCK_BUF:24742469 if (magic32 != XFS_DIR2_BLOCK_MAGIC &&24752470 magic32 != XFS_DIR3_BLOCK_MAGIC) {24762476- xfs_warn(mp, "Bad dir block magic!");24772477- ASSERT(0);24712471+ warnmsg = "Bad dir block magic!";24782472 break;24792473 }24802474 bp->b_ops = &xfs_dir3_block_buf_ops;···24812477 case XFS_BLFT_DIR_DATA_BUF:24822478 if (magic32 != XFS_DIR2_DATA_MAGIC &&24832479 magic32 != XFS_DIR3_DATA_MAGIC) {24842484- xfs_warn(mp, "Bad dir data magic!");24852485- ASSERT(0);24802480+ warnmsg = "Bad dir data magic!";24862481 break;24872482 }24882483 bp->b_ops = &xfs_dir3_data_buf_ops;···24892486 case XFS_BLFT_DIR_FREE_BUF:24902487 if (magic32 != XFS_DIR2_FREE_MAGIC &&24912488 magic32 != XFS_DIR3_FREE_MAGIC) {24922492- xfs_warn(mp, "Bad dir3 free magic!");24932493- ASSERT(0);24892489+ warnmsg = "Bad dir3 free magic!";24942490 break;24952491 }24962492 bp->b_ops = &xfs_dir3_free_buf_ops;···24972495 case XFS_BLFT_DIR_LEAF1_BUF:24982496 if (magicda != XFS_DIR2_LEAF1_MAGIC &&24992497 magicda != XFS_DIR3_LEAF1_MAGIC) {25002500- xfs_warn(mp, "Bad dir leaf1 magic!");25012501- ASSERT(0);24982498+ warnmsg = "Bad dir leaf1 magic!";25022499 break;25032500 }25042501 bp->b_ops = &xfs_dir3_leaf1_buf_ops;···25052504 case XFS_BLFT_DIR_LEAFN_BUF:25062505 if (magicda != XFS_DIR2_LEAFN_MAGIC &&25072506 magicda != XFS_DIR3_LEAFN_MAGIC) {25082508- xfs_warn(mp, "Bad dir leafn magic!");25092509- ASSERT(0);25072507+ warnmsg = "Bad dir leafn magic!";25102508 break;25112509 }25122510 bp->b_ops = &xfs_dir3_leafn_buf_ops;···25132513 case XFS_BLFT_DA_NODE_BUF:25142514 if (magicda != XFS_DA_NODE_MAGIC &&25152515 magicda != XFS_DA3_NODE_MAGIC) {25162516- xfs_warn(mp, "Bad da node magic!");25172517- ASSERT(0);25162516+ warnmsg = "Bad da node magic!";25182517 break;25192518 }25202519 bp->b_ops = &xfs_da3_node_buf_ops;···25212522 case XFS_BLFT_ATTR_LEAF_BUF:25222523 if (magicda != XFS_ATTR_LEAF_MAGIC &&25232524 magicda != XFS_ATTR3_LEAF_MAGIC) {25242524- xfs_warn(mp, "Bad attr leaf magic!");25252525- ASSERT(0);25252525+ warnmsg = "Bad attr leaf magic!";25262526 break;25272527 }25282528 bp->b_ops = &xfs_attr3_leaf_buf_ops;25292529 break;25302530 case XFS_BLFT_ATTR_RMT_BUF:25312531 if (magic32 != XFS_ATTR3_RMT_MAGIC) {25322532- xfs_warn(mp, "Bad attr remote magic!");25332533- ASSERT(0);25322532+ warnmsg = "Bad attr remote magic!";25342533 break;25352534 }25362535 bp->b_ops = &xfs_attr3_rmt_buf_ops;25372536 break;25382537 case XFS_BLFT_SB_BUF:25392538 if (magic32 != XFS_SB_MAGIC) {25402540- xfs_warn(mp, "Bad SB block magic!");25412541- ASSERT(0);25392539+ warnmsg = "Bad SB block magic!";25422540 break;25432541 }25442542 bp->b_ops = &xfs_sb_buf_ops;···25522556 xfs_blft_from_flags(buf_f));25532557 break;25542558 }25592559+25602560+ /*25612561+ * Nothing else to do in the case of a NULL current LSN as this means25622562+ * the buffer is more recent than the change in the log and will be25632563+ * skipped.25642564+ */25652565+ if (current_lsn == NULLCOMMITLSN)25662566+ return;25672567+25682568+ if (warnmsg) {25692569+ xfs_warn(mp, warnmsg);25702570+ ASSERT(0);25712571+ }25722572+25732573+ /*25742574+ * We must update the metadata LSN of the buffer as it is written out to25752575+ * ensure that older transactions never replay over this one and corrupt25762576+ * the buffer. This can occur if log recovery is interrupted at some25772577+ * point after the current transaction completes, at which point a25782578+ * subsequent mount starts recovery from the beginning.25792579+ *25802580+ * Write verifiers update the metadata LSN from log items attached to25812581+ * the buffer. Therefore, initialize a bli purely to carry the LSN to25822582+ * the verifier. We'll clean it up in our ->iodone() callback.25832583+ */25842584+ if (bp->b_ops) {25852585+ struct xfs_buf_log_item *bip;25862586+25872587+ ASSERT(!bp->b_iodone || bp->b_iodone == xlog_recover_iodone);25882588+ bp->b_iodone = xlog_recover_iodone;25892589+ xfs_buf_item_init(bp, mp);25902590+ bip = bp->b_fspriv;25912591+ bip->bli_item.li_lsn = current_lsn;25922592+ }25552593}2556259425572595/*···25992569 struct xfs_mount *mp,26002570 xlog_recover_item_t *item,26012571 struct xfs_buf *bp,26022602- xfs_buf_log_format_t *buf_f)25722572+ xfs_buf_log_format_t *buf_f,25732573+ xfs_lsn_t current_lsn)26032574{26042575 int i;26052576 int bit;···26732642 /* Shouldn't be any more regions */26742643 ASSERT(i == item->ri_total);2675264426762676- xlog_recover_validate_buf_type(mp, bp, buf_f);26452645+ xlog_recover_validate_buf_type(mp, bp, buf_f, current_lsn);26772646}2678264726792648/*···27162685 if (log->l_quotaoffs_flag & type)27172686 return false;2718268727192719- xlog_recover_do_reg_buffer(mp, item, bp, buf_f);26882688+ xlog_recover_do_reg_buffer(mp, item, bp, buf_f, NULLCOMMITLSN);27202689 return true;27212690}27222691···28042773 */28052774 lsn = xlog_recover_get_buf_lsn(mp, bp);28062775 if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) {28072807- xlog_recover_validate_buf_type(mp, bp, buf_f);27762776+ trace_xfs_log_recover_buf_skip(log, buf_f);27772777+ xlog_recover_validate_buf_type(mp, bp, buf_f, NULLCOMMITLSN);28082778 goto out_release;28092779 }28102780···28212789 if (!dirty)28222790 goto out_release;28232791 } else {28242824- xlog_recover_do_reg_buffer(mp, item, bp, buf_f);27922792+ xlog_recover_do_reg_buffer(mp, item, bp, buf_f, current_lsn);28252793 }2826279428272795 /*···38783846xlog_recover_commit_trans(38793847 struct xlog *log,38803848 struct xlog_recover *trans,38813881- int pass)38493849+ int pass,38503850+ struct list_head *buffer_list)38823851{38833852 int error = 0;38843884- int error2;38853853 int items_queued = 0;38863854 struct xlog_recover_item *item;38873855 struct xlog_recover_item *next;38883888- LIST_HEAD (buffer_list);38893856 LIST_HEAD (ra_list);38903857 LIST_HEAD (done_list);38913858···39073876 items_queued++;39083877 if (items_queued >= XLOG_RECOVER_COMMIT_QUEUE_MAX) {39093878 error = xlog_recover_items_pass2(log, trans,39103910- &buffer_list, &ra_list);38793879+ buffer_list, &ra_list);39113880 list_splice_tail_init(&ra_list, &done_list);39123881 items_queued = 0;39133882 }···39253894 if (!list_empty(&ra_list)) {39263895 if (!error)39273896 error = xlog_recover_items_pass2(log, trans,39283928- &buffer_list, &ra_list);38973897+ buffer_list, &ra_list);39293898 list_splice_tail_init(&ra_list, &done_list);39303899 }3931390039323901 if (!list_empty(&done_list))39333902 list_splice_init(&done_list, &trans->r_itemq);3934390339353935- error2 = xfs_buf_delwri_submit(&buffer_list);39363936- return error ? error : error2;39043904+ return error;39373905}3938390639393907STATIC void···41154085 char *dp,41164086 unsigned int len,41174087 unsigned int flags,41184118- int pass)40884088+ int pass,40894089+ struct list_head *buffer_list)41194090{41204091 int error = 0;41214092 bool freeit = false;···41404109 error = xlog_recover_add_to_cont_trans(log, trans, dp, len);41414110 break;41424111 case XLOG_COMMIT_TRANS:41434143- error = xlog_recover_commit_trans(log, trans, pass);41124112+ error = xlog_recover_commit_trans(log, trans, pass,41134113+ buffer_list);41444114 /* success or fail, we are now done with this transaction. */41454115 freeit = true;41464116 break;···42234191 struct xlog_op_header *ohead,42244192 char *dp,42254193 char *end,42264226- int pass)41944194+ int pass,41954195+ struct list_head *buffer_list)42274196{42284197 struct xlog_recover *trans;42294198 unsigned int len;41994199+ int error;4230420042314201 /* Do we understand who wrote this op? */42324202 if (ohead->oh_clientid != XFS_TRANSACTION &&···42554221 return 0;42564222 }4257422342244224+ /*42254225+ * The recovered buffer queue is drained only once we know that all42264226+ * recovery items for the current LSN have been processed. This is42274227+ * required because:42284228+ *42294229+ * - Buffer write submission updates the metadata LSN of the buffer.42304230+ * - Log recovery skips items with a metadata LSN >= the current LSN of42314231+ * the recovery item.42324232+ * - Separate recovery items against the same metadata buffer can share42334233+ * a current LSN. I.e., consider that the LSN of a recovery item is42344234+ * defined as the starting LSN of the first record in which its42354235+ * transaction appears, that a record can hold multiple transactions,42364236+ * and/or that a transaction can span multiple records.42374237+ *42384238+ * In other words, we are allowed to submit a buffer from log recovery42394239+ * once per current LSN. Otherwise, we may incorrectly skip recovery42404240+ * items and cause corruption.42414241+ *42424242+ * We don't know up front whether buffers are updated multiple times per42434243+ * LSN. Therefore, track the current LSN of each commit log record as it42444244+ * is processed and drain the queue when it changes. Use commit records42454245+ * because they are ordered correctly by the logging code.42464246+ */42474247+ if (log->l_recovery_lsn != trans->r_lsn &&42484248+ ohead->oh_flags & XLOG_COMMIT_TRANS) {42494249+ error = xfs_buf_delwri_submit(buffer_list);42504250+ if (error)42514251+ return error;42524252+ log->l_recovery_lsn = trans->r_lsn;42534253+ }42544254+42584255 return xlog_recovery_process_trans(log, trans, dp, len,42594259- ohead->oh_flags, pass);42564256+ ohead->oh_flags, pass, buffer_list);42604257}4261425842624259/*···43054240 struct hlist_head rhash[],43064241 struct xlog_rec_header *rhead,43074242 char *dp,43084308- int pass)42434243+ int pass,42444244+ struct list_head *buffer_list)43094245{43104246 struct xlog_op_header *ohead;43114247 char *end;···43204254 if (xlog_header_check_recover(log->l_mp, rhead))43214255 return -EIO;4322425642574257+ trace_xfs_log_recover_record(log, rhead, pass);43234258 while ((dp < end) && num_logops) {4324425943254260 ohead = (struct xlog_op_header *)dp;···4329426243304263 /* errors will abort recovery */43314264 error = xlog_recover_process_ophdr(log, rhash, rhead, ohead,43324332- dp, end, pass);42654265+ dp, end, pass, buffer_list);43334266 if (error)43344267 return error;43354268···47524685 struct hlist_head rhash[],47534686 struct xlog_rec_header *rhead,47544687 char *dp,47554755- int pass)46884688+ int pass,46894689+ struct list_head *buffer_list)47564690{47574691 int error;47584692 __le32 crc;···48004732 if (error)48014733 return error;4802473448034803- return xlog_recover_process_data(log, rhash, rhead, dp, pass);47354735+ return xlog_recover_process_data(log, rhash, rhead, dp, pass,47364736+ buffer_list);48044737}4805473848064739STATIC int···48624793 char *offset;48634794 xfs_buf_t *hbp, *dbp;48644795 int error = 0, h_size, h_len;47964796+ int error2 = 0;48654797 int bblks, split_bblks;48664798 int hblks, split_hblks, wrapped_hblks;48674799 struct hlist_head rhash[XLOG_RHASH_SIZE];48004800+ LIST_HEAD (buffer_list);4868480148694802 ASSERT(head_blk != tail_blk);48704803 rhead_blk = 0;···50524981 }5053498250544983 error = xlog_recover_process(log, rhash, rhead, offset,50555055- pass);49844984+ pass, &buffer_list);50564985 if (error)50574986 goto bread_err2;50584987···50835012 if (error)50845013 goto bread_err2;5085501450865086- error = xlog_recover_process(log, rhash, rhead, offset, pass);50155015+ error = xlog_recover_process(log, rhash, rhead, offset, pass,50165016+ &buffer_list);50875017 if (error)50885018 goto bread_err2;50895019···50975025 bread_err1:50985026 xlog_put_bp(hbp);5099502750285028+ /*50295029+ * Submit buffers that have been added from the last record processed,50305030+ * regardless of error status.50315031+ */50325032+ if (!list_empty(&buffer_list))50335033+ error2 = xfs_buf_delwri_submit(&buffer_list);50345034+51005035 if (error && first_bad)51015036 *first_bad = rhead_blk;5102503751035103- return error;50385038+ return error ? error : error2;51045039}5105504051065041/*
+14
fs/xfs/xfs_mount.c
···934934 }935935936936 /*937937+ * Now the log is fully replayed, we can transition to full read-only938938+ * mode for read-only mounts. This will sync all the metadata and clean939939+ * the log so that the recovery we just performed does not have to be940940+ * replayed again on the next mount.941941+ *942942+ * We use the same quiesce mechanism as the rw->ro remount, as they are943943+ * semantically identical operations.944944+ */945945+ if ((mp->m_flags & (XFS_MOUNT_RDONLY|XFS_MOUNT_NORECOVERY)) ==946946+ XFS_MOUNT_RDONLY) {947947+ xfs_quiesce_attr(mp);948948+ }949949+950950+ /*937951 * Complete the quota initialisation, post-log-replay component.938952 */939953 if (quotamount) {
+1-1
fs/xfs/xfs_super.c
···11371137 * Note: xfs_log_quiesce() stops background log work - the callers must ensure11381138 * it is started again when appropriate.11391139 */11401140-static void11401140+void11411141xfs_quiesce_attr(11421142 struct xfs_mount *mp)11431143{