NVSL / linux-nova

NOVA is a log-structured file system designed for byte-addressable non-volatile memories, developed at the University of California, San Diego.
http://nvsl.ucsd.edu/index.php?path=projects/nova
Other
425 stars 118 forks source link

Incorrect inode number emitted from nova_readdir_fast #147

Open iaoing opened 10 months ago

iaoing commented 10 months ago

Issue

The inode number is incorrect when readdir.

Reproduce

The blow C code is used to read the directory and print out the d_ino.

#include <dirent.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>

void print_dirents(DIR * dir){
    struct dirent *entry;
    while ( (entry=readdir(dir)) != NULL ){
        printf("%s, %ld\n", entry->d_name, entry->d_ino);
    }
}

int main(int argc, char **argv){
    if (argc != 2) {
        printf("usgae: execuable [path]\n");
        return 0;
    }

    char *dir_name = argv[1];
    DIR *dir;

    dir = opendir(dir_name);
    print_dirents(dir);
    closedir(dir);

    return 0;
}
sudo insmod nova.ko
sudo mount -t NOVA -o init,dbgmask=255 /dev/pmem0 /mnt/pmem0
sudo mkdir /mnt/pmem/dir
# assuming the executable C code is a.out
./a.out /mnt/pmem0
# the output is:
# ., 1
# .., 33
# dir, 33
# The syslog shows the inode number for the `..` file and the `dir` entry is correct.

Reason

https://github.com/NVSL/linux-nova/blob/976a4d1f3d5282863b23aa834e02012167be6ee2/fs/nova/dir.c#L708-L713 https://github.com/NVSL/linux-nova/blob/976a4d1f3d5282863b23aa834e02012167be6ee2/fs/nova/dir.c#L728-L731

In the above code snippet, the inode number passed to dir_emit is incorrect. It should be prev_entryc->ino rather than ino. This explains why the .. file's inode is 33 and dir's inode is still 33.

Fix

Simply modify the ino as prev_entryc->ino as the below code shows.

 // dir.c#L708-L713
 if (prev_entry && !dir_emit(ctx, prev_entryc->name, 
    prev_entryc->name_len, prev_entryc->ino, 
    IF2DT(le16_to_cpu(prev_child_pi->i_mode)))) { 
    nova_dbgv("Here: pos %llu\n", ctx->pos); 
    return 0; 
 } 

// dir.c#L728-L731
 if (prev_entry && !dir_emit(ctx, prev_entryc->name, 
        prev_entryc->name_len, prev_entryc->ino, 
        IF2DT(le16_to_cpu(prev_child_pi->i_mode)))) 
    return 0;