Commit cb85f4d
ext4: fix race between writepages and enabling EXT4_EXTENTS_FL
If EXT4_EXTENTS_FL is set on an inode while ext4_writepages() is running
on it, the following warning in ext4_add_complete_io() can be hit:
WARNING: CPU: 1 PID: 0 at fs/ext4/page-io.c:234 ext4_put_io_end_defer+0xf0/0x120
Here's a minimal reproducer (not 100% reliable) (root isn't required):
while true; do
sync
done &
while true; do
rm -f file
touch file
chattr -e file
echo X >> file
chattr +e file
done
The problem is that in ext4_writepages(), ext4_should_dioread_nolock()
(which only returns true on extent-based files) is checked once to set
the number of reserved journal credits, and also again later to select
the flags for ext4_map_blocks() and copy the reserved journal handle to
ext4_io_end::handle. But if EXT4_EXTENTS_FL is being concurrently set,
the first check can see dioread_nolock disabled while the later one can
see it enabled, causing the reserved handle to unexpectedly be NULL.
Since changing EXT4_EXTENTS_FL is uncommon, and there may be other races
related to doing so as well, fix this by synchronizing changing
EXT4_EXTENTS_FL with ext4_writepages() via the existing
s_writepages_rwsem (previously called s_journal_flag_rwsem).
This was originally reported by syzbot without a reproducer at
https://syzkaller.appspot.com/bug?extid=2202a584a00fffd19fbf,
but now that dioread_nolock is the default I also started seeing this
when running syzkaller locally.
Link: https://lore.kernel.org/r/[email protected]
Reported-by: [email protected]
Fixes: 6b523df ("ext4: use transaction reservation for extent conversion in ext4_end_io")
Signed-off-by: Eric Biggers <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>
Reviewed-by: Jan Kara <[email protected]>
Cc: [email protected]1 parent bbd5593 commit cb85f4d
2 files changed
+23
-9
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1552 | 1552 | | |
1553 | 1553 | | |
1554 | 1554 | | |
1555 | | - | |
| 1555 | + | |
| 1556 | + | |
| 1557 | + | |
| 1558 | + | |
1556 | 1559 | | |
1557 | 1560 | | |
1558 | 1561 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
407 | 407 | | |
408 | 408 | | |
409 | 409 | | |
| 410 | + | |
410 | 411 | | |
411 | 412 | | |
412 | 413 | | |
| |||
431 | 432 | | |
432 | 433 | | |
433 | 434 | | |
| 435 | + | |
| 436 | + | |
434 | 437 | | |
435 | 438 | | |
436 | 439 | | |
| |||
441 | 444 | | |
442 | 445 | | |
443 | 446 | | |
444 | | - | |
| 447 | + | |
445 | 448 | | |
446 | 449 | | |
447 | 450 | | |
| |||
452 | 455 | | |
453 | 456 | | |
454 | 457 | | |
455 | | - | |
| 458 | + | |
456 | 459 | | |
457 | 460 | | |
458 | 461 | | |
| |||
494 | 497 | | |
495 | 498 | | |
496 | 499 | | |
497 | | - | |
| 500 | + | |
498 | 501 | | |
499 | 502 | | |
500 | 503 | | |
| |||
576 | 579 | | |
577 | 580 | | |
578 | 581 | | |
579 | | - | |
| 582 | + | |
580 | 583 | | |
581 | 584 | | |
582 | | - | |
| 585 | + | |
| 586 | + | |
583 | 587 | | |
584 | 588 | | |
585 | 589 | | |
| |||
589 | 593 | | |
590 | 594 | | |
591 | 595 | | |
592 | | - | |
| 596 | + | |
| 597 | + | |
593 | 598 | | |
594 | 599 | | |
595 | 600 | | |
| |||
613 | 618 | | |
614 | 619 | | |
615 | 620 | | |
| 621 | + | |
| 622 | + | |
616 | 623 | | |
617 | | - | |
618 | | - | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
619 | 628 | | |
620 | 629 | | |
621 | 630 | | |
| |||
650 | 659 | | |
651 | 660 | | |
652 | 661 | | |
| 662 | + | |
| 663 | + | |
653 | 664 | | |
654 | 665 | | |
0 commit comments