tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

rename open file loose unsync data


I tracked down a PUFFS bug with rename: if I rename a file that has
unsync data, it get lost and replaced by zeroes. I use page cache. The
test case below exhibit the bug.

Here is my analysis of the problem so far: the kernel is nice enough to
call puffs_vnop_fsync before puffs_vnop_rename, therefore the data
should be sync to the file and I should not see that bug. However,
adding a few printf() in the kernel shows me that puffs_vnop_fsync
calls flushvncache/VOP_PUTPAGES/genfs_putpages/genfs_do_putpages, where
pmap_clear_modify() returns needs_clean=0, and therefore the call to
GOP_WRITE is not done, leaving data unsync.

Oddly, if I explicitely add a fsync(2) before rename(2) in my test case,
the bug disapear. I can see that genfs_do_putpages() gets a
needs_clean=1 from pmap_clear_modify()  in that case. I still have to
understand why it makes a difference when explictely calling fsync(2).

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
#include <sysexits.h>

        int fd1, fd2;
        char buf[] = "abcdefgh";
        char buf2[] = "xxxxxxxx";


        if ((fd1 = open("tmp", O_CREAT|O_RDWR, 0644)) == -1)
                err(EX_OSERR, "cannot open tmp");

        if (write(fd1, buf, sizeof(buf)) != sizeof(buf))
                err(EX_OSERR, "write failed");

        if (rename("tmp", "tmp2") == -1)
                err(EX_OSERR, "rename failed");

        /* No bug if fd1 is closed or fsync'ed before rename */

        if ((fd2 = open("tmp2", O_RDONLY, 0)) == -1)
                err(EX_OSERR, "cannot open tmp2");

        if (read(fd2, buf2, sizeof(buf2)) != sizeof(buf2))
                err(EX_OSERR, "read failed");


        printf("buf  = \"%s\"\nbuf2 = \"%s\"\n", buf, buf2);

        return 0;

Emmanuel Dreyfus

Home | Main Index | Thread Index | Old Index