Skip to content
  • David Howells's avatar
    afs: Make afs_write_begin() avoid writing to a page that's being stored · 5a039c32
    David Howells authored
    
    
    Make afs_write_begin() wait for a page that's marked PG_writeback because:
    
     (1) We need to avoid interference with the data being stored so that the
         data on the server ends up in a defined state.
    
     (2) page->private is used to track the window of dirty data within a page,
         but it's also used by the storage code to track what's being written,
         being cleared by the completion notification.  Ownership can't be
         relinquished by the storage code until completion because it a store
         fails, the data must be remarked dirty.
    
    Tracing shows something like the following (edited):
    
     x86_64-linux-gn-15940 [1] afs_page_dirty: vn=ffff8800bef33800 9c75 begin 0-125
        kworker/u8:3-114   [2] afs_page_dirty: vn=ffff8800bef33800 9c75 store+ 0-125
     x86_64-linux-gn-15940 [1] afs_page_dirty: vn=ffff8800bef33800 9c75 begin 0-2052
        kworker/u8:3-114   [2] afs_page_dirty: vn=ffff8800bef33800 9c75 clear 0-2052
        kworker/u8:3-114   [2] afs_page_dirty: vn=ffff8800bef33800 9c75 store 0-0
        kworker/u8:3-114   [2] afs_page_dirty: vn=ffff8800bef33800 9c75 WARN 0-0
    
    The clear (completion) corresponding to the store+ (store continuation from
    a previous page) happens between the second begin (afs_write_begin) and the
    store corresponding to that.  This results in the second store not seeing
    any data to write back, leading to the following warning:
    
    WARNING: CPU: 2 PID: 114 at ../fs/afs/write.c:403 afs_write_back_from_locked_page+0x19d/0x76c [kafs]
    Modules linked in: kafs(E)
    CPU: 2 PID: 114 Comm: kworker/u8:3 Tainted: G            E   4.14.0-fscache+ #242
    Hardware name: ASUS All Series/H97-PLUS, BIOS 2306 10/09/2014
    Workqueue: writeback wb_workfn (flush-afs-2)
    task: ffff8800cad72600 task.stack: ffff8800cad44000
    RIP: 0010:afs_write_back_from_locked_page+0x19d/0x76c [kafs]
    RSP: 0018:ffff8800cad47aa0 EFLAGS: 00010246
    RAX: 0000000000000001 RBX: ffff8800bef33a20 RCX: 0000000000000000
    RDX: 000000000000000f RSI: ffffffff81c5d0e0 RDI: ffff8800cad72e78
    RBP: ffff8800d31ea1e8 R08: ffff8800c1358000 R09: ffff8800ca00e400
    R10: ffff8800cad47a38 R11: ffff8800c5d9e400 R12: 0000000000000000
    R13: ffffea0002d9df00 R14: ffffffffa0023c1c R15: 0000000000007fdf
    FS:  0000000000000000(0000) GS:ffff8800ca700000(0000) knlGS:0000000000000000
    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: 00007f85ac6c4000 CR3: 0000000001c10001 CR4: 00000000001606e0
    Call Trace:
     ? clear_page_dirty_for_io+0x23a/0x267
     afs_writepages_region+0x1be/0x286 [kafs]
     afs_writepages+0x60/0x127 [kafs]
     do_writepages+0x36/0x70
     __writeback_single_inode+0x12f/0x635
     writeback_sb_inodes+0x2cc/0x452
     __writeback_inodes_wb+0x68/0x9f
     wb_writeback+0x208/0x470
     ? wb_workfn+0x22b/0x565
     wb_workfn+0x22b/0x565
     ? worker_thread+0x230/0x2ac
     process_one_work+0x2cc/0x517
     ? worker_thread+0x230/0x2ac
     worker_thread+0x1d4/0x2ac
     ? rescuer_thread+0x29b/0x29b
     kthread+0x15d/0x165
     ? kthread_create_on_node+0x3f/0x3f
     ? call_usermodehelper_exec_async+0x118/0x11f
     ret_from_fork+0x24/0x30
    
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    5a039c32