• Nikolay Borisov's avatar
    btrfs: Speed up btrfs_file_llseek · d79b7c26
    Nikolay Borisov authored
    Modifying the file position is done on a per-file basis. This renders
    holding the inode lock for writing useless and makes the performance of
    concurrent llseek's abysmal.
    
    Fix this by holding the inode for read. This provides protection against
    concurrent truncates and find_desired_extent already includes proper
    extent locking for the range which ensures proper locking against
    concurrent writes. SEEK_CUR and SEEK_END can be done lockessly.
    
    The former is synchronized by file::f_lock spinlock. SEEK_END is not
    synchronized but atomic, but that's OK since there is not guarantee that
    SEEK_END will always be at the end of the file in the face of tail
    modifications.
    
    This change brings ~82% performance improvement when doing a lot of
    parallel fseeks. The workload essentially does:
    
        for (d=0; d<num_seek_read; d++)
          {
    	/* offset %= 16777216; */
    	fseek (f, 256 * d % 16777216, SEEK_SET);
    	fread (buffer, 64, 1, f);
          }
    
    Without patch:
    
    num workprocesses = 16
    num fseek/fread = 8000000
    step = 256
    fork 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    
    real	0m41.412s
    user	0m28.777s
    sys	2m16.510s
    
    With patch:
    
    num workprocesses = 16
    num fseek/fread = 8000000
    step = 256
    fork 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    
    real	0m11.479s
    user	0m27.629s
    sys	0m21.040s
    Signed-off-by: default avatarNikolay Borisov <nborisov@suse.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    d79b7c26
file.c 92.3 KB