• Chao Yu's avatar
    f2fs: fix to convert inline directory correctly · 675f10bd
    Chao Yu authored
    With below serials, we will lose parts of dirents:
    
    1) mount f2fs with inline_dentry option
    2) echo 1 > /sys/fs/f2fs/sdX/dir_level
    3) mkdir dir
    4) touch 180 files named [1-180] in dir
    5) touch 181 in dir
    6) echo 3 > /proc/sys/vm/drop_caches
    7) ll dir
    
    ls: cannot access 2: No such file or directory
    ls: cannot access 4: No such file or directory
    ls: cannot access 5: No such file or directory
    ls: cannot access 6: No such file or directory
    ls: cannot access 8: No such file or directory
    ls: cannot access 9: No such file or directory
    ...
    total 360
    drwxr-xr-x 2 root root 4096 Feb 19 15:12 ./
    drwxr-xr-x 3 root root 4096 Feb 19 15:11 ../
    -rw-r--r-- 1 root root    0 Feb 19 15:12 1
    -rw-r--r-- 1 root root    0 Feb 19 15:12 10
    -rw-r--r-- 1 root root    0 Feb 19 15:12 100
    -????????? ? ?    ?       ?            ? 101
    -????????? ? ?    ?       ?            ? 102
    -????????? ? ?    ?       ?            ? 103
    ...
    
    The reason is: when doing the inline dir conversion, we didn't consider
    that directory has hierarchical hash structure which can be configured
    through sysfs interface 'dir_level'.
    
    By default, dir_level of directory inode is 0, it means we have one bucket
    in hash table located in first level, all dirents will be hashed in this
    bucket, so it has no problem for us to do the duplication simply between
    inline dentry page and converted normal dentry page.
    
    However, if we configured dir_level with the value N (greater than 0), it
    will expand the bucket number of first level hash table by 2^N - 1, it
    hashs dirents into different buckets according their hash value, if we
    still move all dirents to first bucket, it makes incorrent locating for
    inline dirents, the result is, although we can iterate all dirents through
    ->readdir, we can't stat some of them in ->lookup which based on hash
    table searching.
    
    This patch fixes this issue by rehashing dirents into correct position
    when converting inline directory.
    Signed-off-by: default avatarChao Yu <chao2.yu@samsung.com>
    Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
    675f10bd
dir.c 21.7 KB