xfstests/xfs/080 fix
Let's say there are 2 extents: one unwritten and the other written.
rwtest.file:
EXT: FILE-OFFSET BLOCK-RANGE AG AG-OFFSET TOTAL FLAGS
0: [0..15]: 160..175 0 (160..175) 16 10000
1: [16..63]: 176..223 0 (176..223) 48 00000
Then we do a direct io write to these 2 extends.
root@block:/mnt/test# xfs_io
xfs_io> open -d rwtest.file
xfs_io> pwrite -b 32768 0 32768
EXT 0 should be converted to written extent.
rwtest.file:
EXT: FILE-OFFSET BLOCK-RANGE AG AG-OFFSET TOTAL FLAGS
0: [0..63]: 160..223 0 (160..223) 64 00000
There was a bug that caused dio->bi_privte set to NULL, so below code path
was not executed, so the extent not converted from unwritten to written.
[ 72.328096] Call Trace:
[ 72.328786] [<ffffffff8169c2f3>] dump_stack+0x4f/0x7b
[ 72.330002] [<ffffffff8127140f>] xfs_bmapi_convert_unwritten+0x73/0x176
[ 72.331565] [<ffffffff8126cd9d>] ? xfs_bmap_search_extents+0x60/0xd6
[ 72.333059] [<ffffffff812c96f1>] ? kmem_zone_alloc+0x6e/0xba
[ 72.334412] [<ffffffff8127a233>] xfs_bmapi_write+0x2a0/0x7ee
[ 72.335777] [<ffffffff812b9455>] xfs_iomap_write_unwritten+0x205/0x413
[ 72.337300] [<ffffffff8129d7e2>] xfs_end_io+0x50/0x75
[ 72.338495] [<ffffffff8129dab9>] xfs_end_io_direct_write+0x176/0x26c
[ 72.339952] [<ffffffff810d20a4>] ? delayacct_end+0x55/0x5e
[ 72.341238] [<ffffffff8118759d>] dio_complete+0x7c/0x134
[ 72.342488] [<ffffffff811882a7>] __blockdev_direct_IO+0x633/0x666
[ 72.343908] [<ffffffff8129fdbb>] ? xfs_get_blocks+0x13/0x13
[ 72.345263] [<ffffffff8129d890>] xfs_vm_direct_IO+0x89/0x90
[ 72.346598] [<ffffffff8129d943>] ? xfs_setfilesize_trans_alloc+0xac/0xac
[ 72.348185] [<ffffffff8169ae5e>] xfs_file_dio_aio_write+0x2e0/0x449
[ 72.349652] [<ffffffff813e1028>] ? __clear_user+0x36/0x5b
[ 72.350950] [<ffffffff812af9c6>] xfs_file_write_iter+0x75/0x105
[ 72.352369] [<ffffffff81151524>] __vfs_write+0x97/0xc0
[ 72.353607] [<ffffffff81151b1f>] vfs_write+0xb5/0x16f
[ 72.354832] [<ffffffff811522c3>] SyS_write+0x4a/0x94
[ 72.356060] [<ffffffff816a4b17>] system_call_fastpath+0x12/0x6f
The bug is the local "map_bh" in get_blocks().
For XFS:
map_bh->b_private saves "ioend"(see xfs_map_direct()).
We need to pass map_bh->b_private to next call of get_blocks().
Fixed it by moving "map_bh" to dio_alloc_bios(),
then it's passed down to dio_send_bio() -> get_blocks().
1 file changed