]> git.baikalelectronics.ru Git - kernel.git/commit
btrfs: Speed up btrfs_file_llseek
authorNikolay Borisov <nborisov@suse.com>
Fri, 27 Sep 2019 10:23:16 +0000 (13:23 +0300)
committerDavid Sterba <dsterba@suse.com>
Mon, 18 Nov 2019 11:46:59 +0000 (12:46 +0100)
commit305252cd88eae75a13e8f36fd20fbfb2daecadf5
tree4140bd7e654c040161b9cf0c4040639dddedbbaa
parentf4e66ba720ca505f21a6f9df86f5484ecf44bbf2
btrfs: Speed up btrfs_file_llseek

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: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/file.c