/* * nfsbug.c * exercises a bug in Linux 2.4/2.5 client NFS * If the parent directory of an unlinked-but-open file goes away, * kernel reports "inode mismatch". * * nfsbug */ #include #include #include #include #include #include #include int main(int argc, char *argv[]) { char path[2048]; char file[2048]; int fd; int v = 1, r; struct dirent *d; DIR *dir; if (argc != 2) exit(1); /* create a dir "t" under */ sprintf(path, "%s/%s", argv[1], "t"); if (mkdir(path, 0777) < 0) exit(1); /* create a file "foo" under /t */ sprintf(file, "%s/%s", path, "foo"); if ((fd = open(file, O_CREAT, 0666)) < 0) exit(1); /* * ok, we're now holding the file open, do an rm -rf. * We have to readdir() because unlinking over NFS does a rename * (otherwise we could just unlink it and then do rmdir). * The readdir() returns foo, then the renamed file (which, when unlinked, * really gets unlinked, not renamed). */ if ((dir = opendir(path)) == NULL) exit(1); while (d = readdir(dir)) { if (!strcmp(".", d->d_name) || !strcmp("..", d->d_name)) continue; sprintf(file, "%s/%s", path, d->d_name); r = unlink(file); if (v && r == 0) printf("unlinked %s\n", file); else if (v && r < 0) printf("failed to unlink %s\n", file); } if (rmdir(path) < 0) printf("failed to rmdir %s\n", path); else printf("rmdir-ed %s\n", path); /* exit, which tries to unlink the .nfs file again */ printf("exit: "); fgets((char *)&r, 2, stdin); exit(0); }