• Filipe Manana's avatar
    btrfs: use log root when iterating over index keys when logging directory · 5d3e4f1d
    Filipe Manana authored
    When logging dir dentries of a directory, we iterate over the subvolume
    tree to find dir index keys on leaves modified in the current transaction.
    This however is heavy on locking, since btrfs_search_forward() may often
    keep locks on extent buffers for quite a while when walking the tree to
    find a suitable leaf modified in the current transaction and with a key
    not smaller than then the provided minimum key. That means it will block
    other tasks trying to access the subvolume tree, which may be common fs
    operations like creating, renaming, linking, unlinking, reflinking files,
    etc.
    
    A better solution is to iterate the log tree, since it's much smaller than
    a subvolume tree and just use plain btrfs_search_slot() (or the wrapper
    btrfs_for_each_slot()) and only contains dir index keys added in the
    current transaction.
    
    The following bonnie++ test on a non-debug kernel (with Debian's default
    kernel config) on a 20G null block device, was used to measure the impact:
    
       $ cat test.sh
       #!/bin/bash
    
       DEV=/dev/nullb0
       MNT=/mnt/nullb0
    
       NR_DIRECTORIES=20
       NR_FILES=20480  # must be a multiple of 1024
       DATASET_SIZE=$(( (8 * 1024 * 1024 * 1024) / 1048576 )) # 8 GiB as megabytes
       DIRECTORY_SIZE=$(( DATASET_SIZE / NR_FILES ))
       NR_FILES=$(( NR_FILES / 1024 ))
    
       umount $DEV &> /dev/null
       mkfs.btrfs -f $DEV
       mount $DEV $MNT
    
       bonnie++ -u root -d $MNT \
           -n $NR_FILES:$DIRECTORY_SIZE:$DIRECTORY_SIZE:$NR_DIRECTORIES \
           -r 0 -s $DATASET_SIZE -b
    
       umount $MNT
    
    Before patchset:
    
       Version 2.00a       ------Sequential Output------ --Sequential Input- --Random-
                           -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
       Name:Size etc        /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
       debian0          8G  376k  99  1.1g  98  939m  92 1527k  99  3.2g  99  9060 256
       Latency             24920us     207us     680ms    5594us     171us    2891us
       Version 2.00a       ------Sequential Create------ --------Random Create--------
       debian0             -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
                     files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                     20/20 20480  96 +++++ +++ 20480  95 20480  99 +++++ +++ 20480  97
       Latency              8708us     137us    5128us    6743us      60us   19712us
    
    After patchset:
    
       Version 2.00a       ------Sequential Output------ --Sequential Input- --Random-
                           -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
       Name:Size etc        /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
       debian0          8G  384k  99  1.2g  99  971m  91 1533k  99  3.3g  99  9180 309
       Latency             24930us     125us     661ms    5587us      46us    2020us
       Version 2.00a       ------Sequential Create------ --------Random Create--------
       debian0             -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
                     files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                     20/20 20480  90 +++++ +++ 20480  99 20480  99 +++++ +++ 20480  97
       Latency              7030us      61us    1246us    4942us      56us   16855us
    
    The patchset consists of this patch plus a previous one that has the
    following subject:
    
       "btrfs: avoid iterating over all indexes when logging directory"
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    5d3e4f1d
tree-log.c 210 KB