Loading disorderfs.cpp +8 −5 Original line number Diff line number Diff line Loading @@ -68,7 +68,7 @@ namespace { } int wrap (int retval) { return retval == -1 ? -errno : 0; } using Dirents = std::vector<std::string>; using Dirents = std::vector<std::pair<std::string, ino_t>>; // The libc versions of seteuid, etc. set the credentials for all threads. // We need to set credentials for a single thread only, so call the syscalls directly. Loading Loading @@ -270,7 +270,7 @@ int main (int argc, char** argv) // Add some of our own hard-coded FUSE options: fuse_opt_add_arg(&fargs, "-o"); fuse_opt_add_arg(&fargs, "atomic_o_trunc,default_permissions"); // XXX: other mount options? fuse_opt_add_arg(&fargs, "atomic_o_trunc,default_permissions,use_ino"); // XXX: other mount options? if (config.multi_user) { fuse_opt_add_arg(&fargs, "-o"); fuse_opt_add_arg(&fargs, "allow_other"); Loading Loading @@ -429,7 +429,7 @@ int main (int argc, char** argv) struct dirent* dirent_p; int res; while ((res = readdir_r(d, &dirent_storage, &dirent_p)) == 0 && dirent_p) { dirents->emplace_back(dirent_p->d_name); dirents->emplace_back(std::make_pair(dirent_p->d_name, dirent_p->d_ino)); } if (config.sort_dirents) { std::sort(dirents->begin(), dirents->end()); Loading @@ -447,14 +447,17 @@ int main (int argc, char** argv) }; disorderfs_fuse_operations.readdir = [] (const char* path, void* buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info* info) { Dirents& dirents = *get_fuse_data<Dirents*>(info); struct stat st; memset(&st, 0, sizeof(st)); if (config.shuffle_dirents) { std::random_device rd; std::mt19937 g(rd()); std::shuffle(dirents.begin(), dirents.end(), g); } for (const std::string& dirent : dirents) { if (filler(buf, dirent.c_str(), nullptr, 0) != 0) { for (const auto dirent : dirents) { st.st_ino = dirent.second; if (filler(buf, dirent.first.c_str(), &st, 0) != 0) { return -ENOMEM; } } Loading tests/inodes 0 → 100755 +87 −0 Original line number Diff line number Diff line #!/bin/sh . ./common TEMPDIR="$(mktemp -d -t inodes.XXXXXXXXXX)" trap "Unmount 2>/dev/null; rm -rf ${TEMPDIR}" EXIT Setup () { cat >${TEMPDIR}/inodes.cpp <<EOF #include <dirent.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/syscall.h> #include <map> #include <iostream> struct linux_dirent { unsigned long d_ino; off_t d_off; unsigned short d_reclen; char d_name[]; }; #define BUF_SIZE 1024 void perror_and_die (const char* s) { std::perror(s); std::abort(); } int main(int argc, char *argv[]) { int fd, nread, ret = EXIT_SUCCESS; char buf[BUF_SIZE]; struct stat st; const std::string dirname = argc > 1 ? argv[1] : "."; struct linux_dirent *d; std::map<ino_t, std::string> inodes; if ((fd = open(dirname.c_str(), O_RDONLY | O_DIRECTORY)) == -1) perror_and_die("open"); while ((nread = syscall(SYS_getdents, fd, buf, BUF_SIZE)) > 0) { for (int pos = 0; pos < nread; pos += d->d_reclen) { d = (struct linux_dirent *) (buf + pos); std::string filename = dirname + "/" + std::string(d->d_name); if (stat(filename.c_str(), &st) == -1) perror_and_die("stat"); if (d->d_ino != st.st_ino) { std::cerr << filename << ": inode from getdents does not match stat: " << d->d_ino << " != " << st.st_ino << std::endl; ret = EXIT_FAILURE; } if (inodes.find(d->d_ino) == inodes.end()) { inodes[d->d_ino] = filename; } else { std::cerr << filename << ": duplicate inode: " << d->d_ino << " used by " << inodes[d->d_ino] << std::endl; ret = EXIT_FAILURE; } } } if (nread == -1) perror_and_die("open"); exit(ret); } EOF g++ -Wall -o${TEMPDIR}/inodes ${TEMPDIR}/inodes.cpp || Fail "Could not compile testcase" } Setup Mount ${TEMPDIR}/inodes target || Fail "inodes" Unmount Loading
disorderfs.cpp +8 −5 Original line number Diff line number Diff line Loading @@ -68,7 +68,7 @@ namespace { } int wrap (int retval) { return retval == -1 ? -errno : 0; } using Dirents = std::vector<std::string>; using Dirents = std::vector<std::pair<std::string, ino_t>>; // The libc versions of seteuid, etc. set the credentials for all threads. // We need to set credentials for a single thread only, so call the syscalls directly. Loading Loading @@ -270,7 +270,7 @@ int main (int argc, char** argv) // Add some of our own hard-coded FUSE options: fuse_opt_add_arg(&fargs, "-o"); fuse_opt_add_arg(&fargs, "atomic_o_trunc,default_permissions"); // XXX: other mount options? fuse_opt_add_arg(&fargs, "atomic_o_trunc,default_permissions,use_ino"); // XXX: other mount options? if (config.multi_user) { fuse_opt_add_arg(&fargs, "-o"); fuse_opt_add_arg(&fargs, "allow_other"); Loading Loading @@ -429,7 +429,7 @@ int main (int argc, char** argv) struct dirent* dirent_p; int res; while ((res = readdir_r(d, &dirent_storage, &dirent_p)) == 0 && dirent_p) { dirents->emplace_back(dirent_p->d_name); dirents->emplace_back(std::make_pair(dirent_p->d_name, dirent_p->d_ino)); } if (config.sort_dirents) { std::sort(dirents->begin(), dirents->end()); Loading @@ -447,14 +447,17 @@ int main (int argc, char** argv) }; disorderfs_fuse_operations.readdir = [] (const char* path, void* buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info* info) { Dirents& dirents = *get_fuse_data<Dirents*>(info); struct stat st; memset(&st, 0, sizeof(st)); if (config.shuffle_dirents) { std::random_device rd; std::mt19937 g(rd()); std::shuffle(dirents.begin(), dirents.end(), g); } for (const std::string& dirent : dirents) { if (filler(buf, dirent.c_str(), nullptr, 0) != 0) { for (const auto dirent : dirents) { st.st_ino = dirent.second; if (filler(buf, dirent.first.c_str(), &st, 0) != 0) { return -ENOMEM; } } Loading
tests/inodes 0 → 100755 +87 −0 Original line number Diff line number Diff line #!/bin/sh . ./common TEMPDIR="$(mktemp -d -t inodes.XXXXXXXXXX)" trap "Unmount 2>/dev/null; rm -rf ${TEMPDIR}" EXIT Setup () { cat >${TEMPDIR}/inodes.cpp <<EOF #include <dirent.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/syscall.h> #include <map> #include <iostream> struct linux_dirent { unsigned long d_ino; off_t d_off; unsigned short d_reclen; char d_name[]; }; #define BUF_SIZE 1024 void perror_and_die (const char* s) { std::perror(s); std::abort(); } int main(int argc, char *argv[]) { int fd, nread, ret = EXIT_SUCCESS; char buf[BUF_SIZE]; struct stat st; const std::string dirname = argc > 1 ? argv[1] : "."; struct linux_dirent *d; std::map<ino_t, std::string> inodes; if ((fd = open(dirname.c_str(), O_RDONLY | O_DIRECTORY)) == -1) perror_and_die("open"); while ((nread = syscall(SYS_getdents, fd, buf, BUF_SIZE)) > 0) { for (int pos = 0; pos < nread; pos += d->d_reclen) { d = (struct linux_dirent *) (buf + pos); std::string filename = dirname + "/" + std::string(d->d_name); if (stat(filename.c_str(), &st) == -1) perror_and_die("stat"); if (d->d_ino != st.st_ino) { std::cerr << filename << ": inode from getdents does not match stat: " << d->d_ino << " != " << st.st_ino << std::endl; ret = EXIT_FAILURE; } if (inodes.find(d->d_ino) == inodes.end()) { inodes[d->d_ino] = filename; } else { std::cerr << filename << ": duplicate inode: " << d->d_ino << " used by " << inodes[d->d_ino] << std::endl; ret = EXIT_FAILURE; } } } if (nread == -1) perror_and_die("open"); exit(ret); } EOF g++ -Wall -o${TEMPDIR}/inodes ${TEMPDIR}/inodes.cpp || Fail "Could not compile testcase" } Setup Mount ${TEMPDIR}/inodes target || Fail "inodes" Unmount