Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'xfs-5.10-fixes-7' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Darrick Wong:
"The critical fixes are for a crash that someone reported in the xattr
code on 32-bit arm last week; and a revert of the rmap key comparison
change from last week as it was totally wrong. I need a vacation. :(

Summary:

- Fix various deficiencies in online fsck's metadata checking code

- Fix an integer casting bug in the xattr code on 32-bit systems

- Fix a hang in an inode walk when the inode index is corrupt

- Fix error codes being dropped when initializing per-AG structures

- Fix nowait directio writes that partially succeed but return EAGAIN

- Revert last week's rmap comparison patch because it was wrong"

* tag 'xfs-5.10-fixes-7' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
xfs: revert "xfs: fix rmap key and record comparison functions"
xfs: don't allow NOWAIT DIO across extent boundaries
xfs: return corresponding errcode if xfs_initialize_perag() fail
xfs: ensure inobt record walks always make forward progress
xfs: fix forkoff miscalculation related to XFS_LITINO(mp)
xfs: directory scrub should check the null bestfree entries too
xfs: strengthen rmap record flags checking
xfs: fix the minrecs logic when dealing with inode root child blocks

+125 -42
+7 -1
fs/xfs/libxfs/xfs_attr_leaf.c
··· 515 515 *========================================================================*/ 516 516 517 517 /* 518 - * Query whether the requested number of additional bytes of extended 518 + * Query whether the total requested number of attr fork bytes of extended 519 519 * attribute space will be able to fit inline. 520 520 * 521 521 * Returns zero if not, else the di_forkoff fork offset to be used in the ··· 534 534 int minforkoff; 535 535 int maxforkoff; 536 536 int offset; 537 + 538 + /* 539 + * Check if the new size could fit at all first: 540 + */ 541 + if (bytes > XFS_LITINO(mp)) 542 + return 0; 537 543 538 544 /* rounded down */ 539 545 offset = (XFS_LITINO(mp) - bytes) >> 3;
+8 -8
fs/xfs/libxfs/xfs_rmap_btree.c
··· 243 243 else if (y > x) 244 244 return -1; 245 245 246 - x = be64_to_cpu(kp->rm_offset); 247 - y = xfs_rmap_irec_offset_pack(rec); 246 + x = XFS_RMAP_OFF(be64_to_cpu(kp->rm_offset)); 247 + y = rec->rm_offset; 248 248 if (x > y) 249 249 return 1; 250 250 else if (y > x) ··· 275 275 else if (y > x) 276 276 return -1; 277 277 278 - x = be64_to_cpu(kp1->rm_offset); 279 - y = be64_to_cpu(kp2->rm_offset); 278 + x = XFS_RMAP_OFF(be64_to_cpu(kp1->rm_offset)); 279 + y = XFS_RMAP_OFF(be64_to_cpu(kp2->rm_offset)); 280 280 if (x > y) 281 281 return 1; 282 282 else if (y > x) ··· 390 390 return 1; 391 391 else if (a > b) 392 392 return 0; 393 - a = be64_to_cpu(k1->rmap.rm_offset); 394 - b = be64_to_cpu(k2->rmap.rm_offset); 393 + a = XFS_RMAP_OFF(be64_to_cpu(k1->rmap.rm_offset)); 394 + b = XFS_RMAP_OFF(be64_to_cpu(k2->rmap.rm_offset)); 395 395 if (a <= b) 396 396 return 1; 397 397 return 0; ··· 420 420 return 1; 421 421 else if (a > b) 422 422 return 0; 423 - a = be64_to_cpu(r1->rmap.rm_offset); 424 - b = be64_to_cpu(r2->rmap.rm_offset); 423 + a = XFS_RMAP_OFF(be64_to_cpu(r1->rmap.rm_offset)); 424 + b = XFS_RMAP_OFF(be64_to_cpu(r2->rmap.rm_offset)); 425 425 if (a <= b) 426 426 return 1; 427 427 return 0;
+4 -4
fs/xfs/scrub/bmap.c
··· 218 218 * which doesn't track unwritten state. 219 219 */ 220 220 if (owner != XFS_RMAP_OWN_COW && 221 - irec->br_state == XFS_EXT_UNWRITTEN && 222 - !(rmap.rm_flags & XFS_RMAP_UNWRITTEN)) 221 + !!(irec->br_state == XFS_EXT_UNWRITTEN) != 222 + !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN)) 223 223 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, 224 224 irec->br_startoff); 225 225 226 - if (info->whichfork == XFS_ATTR_FORK && 227 - !(rmap.rm_flags & XFS_RMAP_ATTR_FORK)) 226 + if (!!(info->whichfork == XFS_ATTR_FORK) != 227 + !!(rmap.rm_flags & XFS_RMAP_ATTR_FORK)) 228 228 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, 229 229 irec->br_startoff); 230 230 if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
+28 -19
fs/xfs/scrub/btree.c
··· 452 452 int level, 453 453 struct xfs_btree_block *block) 454 454 { 455 - unsigned int numrecs; 456 - int ok_level; 457 - 458 - numrecs = be16_to_cpu(block->bb_numrecs); 455 + struct xfs_btree_cur *cur = bs->cur; 456 + unsigned int root_level = cur->bc_nlevels - 1; 457 + unsigned int numrecs = be16_to_cpu(block->bb_numrecs); 459 458 460 459 /* More records than minrecs means the block is ok. */ 461 - if (numrecs >= bs->cur->bc_ops->get_minrecs(bs->cur, level)) 460 + if (numrecs >= cur->bc_ops->get_minrecs(cur, level)) 462 461 return; 463 462 464 463 /* 465 - * Certain btree blocks /can/ have fewer than minrecs records. Any 466 - * level greater than or equal to the level of the highest dedicated 467 - * btree block are allowed to violate this constraint. 468 - * 469 - * For a btree rooted in a block, the btree root can have fewer than 470 - * minrecs records. If the btree is rooted in an inode and does not 471 - * store records in the root, the direct children of the root and the 472 - * root itself can have fewer than minrecs records. 464 + * For btrees rooted in the inode, it's possible that the root block 465 + * contents spilled into a regular ondisk block because there wasn't 466 + * enough space in the inode root. The number of records in that 467 + * child block might be less than the standard minrecs, but that's ok 468 + * provided that there's only one direct child of the root. 473 469 */ 474 - ok_level = bs->cur->bc_nlevels - 1; 475 - if (bs->cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) 476 - ok_level--; 477 - if (level >= ok_level) 478 - return; 470 + if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && 471 + level == cur->bc_nlevels - 2) { 472 + struct xfs_btree_block *root_block; 473 + struct xfs_buf *root_bp; 474 + int root_maxrecs; 479 475 480 - xchk_btree_set_corrupt(bs->sc, bs->cur, level); 476 + root_block = xfs_btree_get_block(cur, root_level, &root_bp); 477 + root_maxrecs = cur->bc_ops->get_dmaxrecs(cur, root_level); 478 + if (be16_to_cpu(root_block->bb_numrecs) != 1 || 479 + numrecs <= root_maxrecs) 480 + xchk_btree_set_corrupt(bs->sc, cur, level); 481 + return; 482 + } 483 + 484 + /* 485 + * Otherwise, only the root level is allowed to have fewer than minrecs 486 + * records or keyptrs. 487 + */ 488 + if (level < root_level) 489 + xchk_btree_set_corrupt(bs->sc, cur, level); 481 490 } 482 491 483 492 /*
+17 -4
fs/xfs/scrub/dir.c
··· 558 558 /* Check all the bestfree entries. */ 559 559 for (i = 0; i < bestcount; i++, bestp++) { 560 560 best = be16_to_cpu(*bestp); 561 - if (best == NULLDATAOFF) 562 - continue; 563 561 error = xfs_dir3_data_read(sc->tp, sc->ip, 564 - i * args->geo->fsbcount, 0, &dbp); 562 + xfs_dir2_db_to_da(args->geo, i), 563 + XFS_DABUF_MAP_HOLE_OK, 564 + &dbp); 565 565 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, 566 566 &error)) 567 567 break; 568 - xchk_directory_check_freesp(sc, lblk, dbp, best); 568 + 569 + if (!dbp) { 570 + if (best != NULLDATAOFF) { 571 + xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 572 + lblk); 573 + break; 574 + } 575 + continue; 576 + } 577 + 578 + if (best == NULLDATAOFF) 579 + xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 580 + else 581 + xchk_directory_check_freesp(sc, lblk, dbp, best); 569 582 xfs_trans_brelse(sc->tp, dbp); 570 583 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 571 584 break;
+29
fs/xfs/xfs_iomap.c
··· 706 706 return 0; 707 707 } 708 708 709 + /* 710 + * Check that the imap we are going to return to the caller spans the entire 711 + * range that the caller requested for the IO. 712 + */ 713 + static bool 714 + imap_spans_range( 715 + struct xfs_bmbt_irec *imap, 716 + xfs_fileoff_t offset_fsb, 717 + xfs_fileoff_t end_fsb) 718 + { 719 + if (imap->br_startoff > offset_fsb) 720 + return false; 721 + if (imap->br_startoff + imap->br_blockcount < end_fsb) 722 + return false; 723 + return true; 724 + } 725 + 709 726 static int 710 727 xfs_direct_write_iomap_begin( 711 728 struct inode *inode, ··· 782 765 783 766 if (imap_needs_alloc(inode, flags, &imap, nimaps)) 784 767 goto allocate_blocks; 768 + 769 + /* 770 + * NOWAIT IO needs to span the entire requested IO with a single map so 771 + * that we avoid partial IO failures due to the rest of the IO range not 772 + * covered by this map triggering an EAGAIN condition when it is 773 + * subsequently mapped and aborting the IO. 774 + */ 775 + if ((flags & IOMAP_NOWAIT) && 776 + !imap_spans_range(&imap, offset_fsb, end_fsb)) { 777 + error = -EAGAIN; 778 + goto out_unlock; 779 + } 785 780 786 781 xfs_iunlock(ip, lockmode); 787 782 trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap);
+24 -3
fs/xfs/xfs_iwalk.c
··· 55 55 /* Where do we start the traversal? */ 56 56 xfs_ino_t startino; 57 57 58 + /* What was the last inode number we saw when iterating the inobt? */ 59 + xfs_ino_t lastino; 60 + 58 61 /* Array of inobt records we cache. */ 59 62 struct xfs_inobt_rec_incore *recs; 60 63 ··· 304 301 if (XFS_IS_CORRUPT(mp, *has_more != 1)) 305 302 return -EFSCORRUPTED; 306 303 304 + iwag->lastino = XFS_AGINO_TO_INO(mp, agno, 305 + irec->ir_startino + XFS_INODES_PER_CHUNK - 1); 306 + 307 307 /* 308 308 * If the LE lookup yielded an inobt record before the cursor position, 309 309 * skip it and see if there's another one after it. ··· 353 347 struct xfs_mount *mp = iwag->mp; 354 348 struct xfs_trans *tp = iwag->tp; 355 349 struct xfs_inobt_rec_incore *irec; 356 - xfs_agino_t restart; 350 + xfs_agino_t next_agino; 357 351 int error; 352 + 353 + next_agino = XFS_INO_TO_AGINO(mp, iwag->lastino) + 1; 358 354 359 355 ASSERT(iwag->nr_recs > 0); 360 356 361 357 /* Delete cursor but remember the last record we cached... */ 362 358 xfs_iwalk_del_inobt(tp, curpp, agi_bpp, 0); 363 359 irec = &iwag->recs[iwag->nr_recs - 1]; 364 - restart = irec->ir_startino + XFS_INODES_PER_CHUNK - 1; 360 + ASSERT(next_agino == irec->ir_startino + XFS_INODES_PER_CHUNK); 365 361 366 362 error = xfs_iwalk_ag_recs(iwag); 367 363 if (error) ··· 380 372 if (error) 381 373 return error; 382 374 383 - return xfs_inobt_lookup(*curpp, restart, XFS_LOOKUP_GE, has_more); 375 + return xfs_inobt_lookup(*curpp, next_agino, XFS_LOOKUP_GE, has_more); 384 376 } 385 377 386 378 /* Walk all inodes in a single AG, from @iwag->startino to the end of the AG. */ ··· 404 396 405 397 while (!error && has_more) { 406 398 struct xfs_inobt_rec_incore *irec; 399 + xfs_ino_t rec_fsino; 407 400 408 401 cond_resched(); 409 402 if (xfs_pwork_want_abort(&iwag->pwork)) ··· 415 406 error = xfs_inobt_get_rec(cur, irec, &has_more); 416 407 if (error || !has_more) 417 408 break; 409 + 410 + /* Make sure that we always move forward. */ 411 + rec_fsino = XFS_AGINO_TO_INO(mp, agno, irec->ir_startino); 412 + if (iwag->lastino != NULLFSINO && 413 + XFS_IS_CORRUPT(mp, iwag->lastino >= rec_fsino)) { 414 + error = -EFSCORRUPTED; 415 + goto out; 416 + } 417 + iwag->lastino = rec_fsino + XFS_INODES_PER_CHUNK - 1; 418 418 419 419 /* No allocated inodes in this chunk; skip it. */ 420 420 if (iwag->skip_empty && irec->ir_freecount == irec->ir_count) { ··· 553 535 .trim_start = 1, 554 536 .skip_empty = 1, 555 537 .pwork = XFS_PWORK_SINGLE_THREADED, 538 + .lastino = NULLFSINO, 556 539 }; 557 540 xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, startino); 558 541 int error; ··· 642 623 iwag->data = data; 643 624 iwag->startino = startino; 644 625 iwag->sz_recs = xfs_iwalk_prefetch(inode_records); 626 + iwag->lastino = NULLFSINO; 645 627 xfs_pwork_queue(&pctl, &iwag->pwork); 646 628 startino = XFS_AGINO_TO_INO(mp, agno + 1, 0); 647 629 if (flags & XFS_INOBT_WALK_SAME_AG) ··· 716 696 .startino = startino, 717 697 .sz_recs = xfs_inobt_walk_prefetch(inobt_records), 718 698 .pwork = XFS_PWORK_SINGLE_THREADED, 699 + .lastino = NULLFSINO, 719 700 }; 720 701 xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, startino); 721 702 int error;
+8 -3
fs/xfs/xfs_mount.c
··· 194 194 } 195 195 196 196 pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL); 197 - if (!pag) 197 + if (!pag) { 198 + error = -ENOMEM; 198 199 goto out_unwind_new_pags; 200 + } 199 201 pag->pag_agno = index; 200 202 pag->pag_mount = mp; 201 203 spin_lock_init(&pag->pag_ici_lock); 202 204 INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); 203 - if (xfs_buf_hash_init(pag)) 205 + 206 + error = xfs_buf_hash_init(pag); 207 + if (error) 204 208 goto out_free_pag; 205 209 init_waitqueue_head(&pag->pagb_wait); 206 210 spin_lock_init(&pag->pagb_lock); 207 211 pag->pagb_count = 0; 208 212 pag->pagb_tree = RB_ROOT; 209 213 210 - if (radix_tree_preload(GFP_NOFS)) 214 + error = radix_tree_preload(GFP_NOFS); 215 + if (error) 211 216 goto out_hash_destroy; 212 217 213 218 spin_lock(&mp->m_perag_lock);