• David Howells's avatar
    afs: Fix EOF corruption · 3f4aa981
    David Howells authored
    When doing a partial writeback, afs_write_back_from_locked_page() may
    generate an FS.StoreData RPC request that writes out part of a file when a
    file has been constructed from pieces by doing seek, write, seek, write,
    ... as is done by ld.
    
    The FS.StoreData RPC is given the current i_size as the file length, but
    the server basically ignores it unless the data length is 0 (in which case
    it's just a truncate operation).  The revised file length returned in the
    result of the RPC may then not reflect what we suggested - and this leads
    to i_size getting moved backwards - which causes issues later.
    
    Fix the client to take account of this by ignoring the returned file size
    unless the data version number jumped unexpectedly - in which case we're
    going to have to clear the pagecache and reload anyway.
    
    This can be observed when doing a kernel build on an AFS mount.  The
    following pair of commands produce the issue:
    
      ld -m elf_x86_64 -z max-page-size=0x200000 --emit-relocs \
          -T arch/x86/realmode/rm/realmode.lds \
          arch/x86/realmode/rm/header.o \
          arch/x86/realmode/rm/trampoline_64.o \
          arch/x86/realmode/rm/stack.o \
          arch/x86/realmode/rm/reboot.o \
          -o arch/x86/realmode/rm/realmode.elf
      arch/x86/tools/relocs --realmode \
          arch/x86/realmode/rm/realmode.elf \
          >arch/x86/realmode/rm/realmode.relocs
    
    This results in the latter giving:
    
    	Cannot read ELF section headers 0/18: Success
    
    as the realmode.elf file got corrupted.
    
    The sequence of events can also be driven with:
    
    	xfs_io -t -f \
    		-c "pwrite -S 0x58 0 0x58" \
    		-c "pwrite -S 0x59 10000 1000" \
    		-c "close" \
    		/afs/example.com/scratch/a
    
    Fixes: 31143d5d ("AFS: implement basic file write support")
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    3f4aa981
inode.c 21.1 KB