From 3f0b6fa8121da7928821090f2ef4d65045018bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20=C5=9Alusarz?= Date: Wed, 1 Nov 2017 21:04:20 +0100 Subject: [PATCH 1/6] tests: update "match" to the latest version From NVML repo. --- tests/match | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/tests/match b/tests/match index 94be61652..d2d7df432 100755 --- a/tests/match +++ b/tests/match @@ -46,6 +46,7 @@ # exact matches. the supported tokens are: # # $(N) an integer (i.e. one or more decimal digits) +# $(NC) one or more decimal digits with comma separators # $(FP) a floating point number # $(S) ascii string # $(X) hex number @@ -55,6 +56,8 @@ # $(*) any string # $(DD) output of a "dd" run # $(OPT) line is optional (may be missing, matched if found) +# $(OPX) ends a contiguous list of $(OPT)...$(OPX) lines, at least +# one of which must match # # arguments are: # @@ -65,7 +68,7 @@ # # -d debug -- show lots of debug output # -# -q don't print any output on mismatch (just exit with result code) +# -q don't print log files on mismatch # # -v verbose -- show every line as it is being matched # @@ -164,6 +167,8 @@ sub match { my $line_pat = 0; my $line_out = 0; my $opt = 0; + my $opx = 0; + my $opt_found = 0; my $fstr = snarf($mfile); for (split /^/, $fstr) { @@ -172,7 +177,8 @@ sub match { $line_out++; s/([*+?|{}.\\^\$\[()])/\\$1/g; s/\\\$\\\(FP\\\)/[-+]?\\d*\\.?\\d+([eE][-+]?\\d+)?/g; - s/\\\$\\\(N\\\)/\\d+/g; + s/\\\$\\\(N\\\)/[-+]?\\d+/g; + s/\\\$\\\(NC\\\)/[-+]?\\d+(,[0-9]+)*/g; s/\\\$\\\(\\\*\\\)/\\p{Print}*/g; s/\\\$\\\(S\\\)/\\P{IsC}+/g; s/\\\$\\\(X\\\)/\\p{XPosixXDigit}+/g; @@ -182,6 +188,10 @@ sub match { s/\\\$\\\(DD\\\)/\\d+\\+\\d+ records in\n\\d+\\+\\d+ records out\n\\d+ bytes \\\(\\d+ .B\\\) copied, [.0-9e-]+[^,]*, [.0-9]+ .B.s/g; if (s/\\\$\\\(OPT\\\)//) { $opt = 1; + } elsif (s/\\\$\\\(OPX\\\)//) { + $opx = 1; + } else { + $opt_found = 0; } if ($opt_v) { @@ -199,25 +209,36 @@ sub match { print " => /$_/\n" if $opt_d; print " [$output]\n" if $opt_d; unless ($output =~ s/^$_//) { - if ($opt) { + if ($opt || ($opx && $opt_found)) { printf("%s:%-3d [skipping optional line]\n", $ofile, $line_out) if $opt_v; $line_out--; $opt = 0; } else { if (!$opt_v) { - print "[MATCHING FAILED, COMPLETE FILE ($ofile) BELOW]\n$all_lines\n[EOF]\n"; + if ($opt_q) { + print "[MATCHING FAILED]\n"; + } else { + print "[MATCHING FAILED, COMPLETE FILE ($ofile) BELOW]\n$all_lines\n[EOF]\n"; + } $opt_v = 1; match($mfile, $ofile); } die "$mfile:$line_pat did not match pattern\n"; } + } elsif ($opt) { + $opt_found = 1; } + $opx = 0; } if ($output ne '') { if (!$opt_v) { - print "[MATCHING FAILED, COMPLETE FILE ($ofile) BELOW]\n$all_lines\n[EOF]\n"; + if ($opt_q) { + print "[MATCHING FAILED]\n"; + } else { + print "[MATCHING FAILED, COMPLETE FILE ($ofile) BELOW]\n$all_lines\n[EOF]\n"; + } } # make it a little more print-friendly... From 5d1d40729dd5595af9b1fb0093ecda50de9493ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20=C5=9Alusarz?= Date: Mon, 16 Oct 2017 00:07:26 +0200 Subject: [PATCH 2/6] fuse: make running in foreground and allow_others optional Running in foreground is not always desirable. allow_others option requires more privileges. --- src/pmemfile-fuse/main.c | 82 ++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 19 deletions(-) diff --git a/src/pmemfile-fuse/main.c b/src/pmemfile-fuse/main.c index af1cc8b1b..52a7eef08 100644 --- a/src/pmemfile-fuse/main.c +++ b/src/pmemfile-fuse/main.c @@ -33,10 +33,13 @@ #define _GNU_SOURCE #include "libpmemfile-posix.h" +#include #include #include #include +#include #include +#include #include #include #include @@ -563,17 +566,50 @@ static struct fuse_operations pmemfile_ops = { .flag_nopath = 1, }; +static void +print_usage(FILE *stream, const char *progname) +{ + fprintf(stream, "Usage: %s [-o|-b|-h] POOL DIR\n", progname); +} + int main(int argc, char *argv[]) { - if (argc != 3) - errx(1, "invalid number of arguments"); - char *poolpath = argv[1]; - char *mountpoint = argv[2]; + int opt; + bool allow_other = false; + bool foreground = true; + + while ((opt = getopt(argc, argv, "obh")) >= 0) { + switch (opt) { + case 'o': + case 'O': + allow_other = true; + break; + case 'b': + case 'B': + foreground = false; + break; + case 'h': + case 'H': + print_usage(stdout, argv[0]); + return 0; + default: + print_usage(stderr, argv[0]); + return 2; + } + } + + if (optind + 2 != argc) { + print_usage(stderr, argv[0]); + return 2; + } + + char *poolpath = argv[optind++]; + char *mountpoint = argv[optind++]; PMEMfilepool *pool = pmemfile_pool_open(poolpath); if (!pool) - err(2, "can't open pool"); + err(2, "can't open pool '%s'", poolpath); char resolved_path[PATH_MAX]; if (realpath(poolpath, resolved_path) == NULL) @@ -583,18 +619,26 @@ main(int argc, char *argv[]) if (asprintf(&fsname, "fsname=pmemfile:%s", resolved_path) < 0) err(4, "asprintf"); - char *fuse_args[] = { - argv[0], - "-o", - fsname, - "-o", - "subtype=pmemfile", - "-o", - "allow_other", - "-f", - mountpoint - }; - - return fuse_main(sizeof(fuse_args) / sizeof(fuse_args[0]), fuse_args, - &pmemfile_ops, pool); + char *fuse_args[9]; + + int idx = 0; + fuse_args[idx++] = argv[0]; + fuse_args[idx++] = "-o"; + fuse_args[idx++] = fsname; + fuse_args[idx++] = "-o"; + fuse_args[idx++] = "subtype=pmemfile"; + + if (allow_other) { + fuse_args[idx++] = "-o"; + fuse_args[idx++] = "allow_other"; + } + + if (foreground) + fuse_args[idx++] = "-f"; + + fuse_args[idx++] = mountpoint; + + assert((unsigned)idx <= (sizeof(fuse_args) / sizeof(fuse_args[0]))); + + return fuse_main(idx, fuse_args, &pmemfile_ops, pool); } From bd677d8293b7bf400073c210876a00725f5852a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20=C5=9Alusarz?= Date: Wed, 1 Nov 2017 22:30:08 +0100 Subject: [PATCH 3/6] fuse: fix error handling in read & write --- src/pmemfile-fuse/main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/pmemfile-fuse/main.c b/src/pmemfile-fuse/main.c index 52a7eef08..38617b6ba 100644 --- a/src/pmemfile-fuse/main.c +++ b/src/pmemfile-fuse/main.c @@ -324,7 +324,11 @@ pmemfile_fuse_write(const char *path, const char *buff, size_t size, if (size > INT32_MAX) size = INT32_MAX; - return (int)pmemfile_pwrite(PFP, f, buff, size, off); + int ret = (int)pmemfile_pwrite(PFP, f, buff, size, off); + if (ret < 0) + return -errno; + + return ret; } static int @@ -340,7 +344,11 @@ pmemfile_fuse_read(const char *path, char *buff, size_t size, off_t off, if (size > INT32_MAX) size = INT32_MAX; - return (int)pmemfile_pread(PFP, f, buff, size, off); + int ret = (int)pmemfile_pread(PFP, f, buff, size, off); + if (ret < 0) + return -errno; + + return ret; } static int From a28f3d4d66292b18b26337cdb434d0ea479b14f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20=C5=9Alusarz?= Date: Wed, 1 Nov 2017 22:32:27 +0100 Subject: [PATCH 4/6] fuse: fix readlink readlink hook semantics are different from sys_readlink --- src/pmemfile-fuse/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pmemfile-fuse/main.c b/src/pmemfile-fuse/main.c index 38617b6ba..ce99fe496 100644 --- a/src/pmemfile-fuse/main.c +++ b/src/pmemfile-fuse/main.c @@ -481,8 +481,10 @@ pmemfile_fuse_readlink(const char *path, char *buff, size_t size) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_readlink(pfp, path, buff, size) < 0) + ret = (int)pmemfile_readlink(pfp, path, buff, size - 1); + if (ret < 0) return -errno; + buff[ret] = 0; return 0; } From 37044bfb3f5507422ad600f5541541fc56ef1729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20=C5=9Alusarz?= Date: Wed, 1 Nov 2017 22:47:36 +0100 Subject: [PATCH 5/6] fuse: log failures in debug mode --- src/pmemfile-fuse/main.c | 106 ++++++++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 30 deletions(-) diff --git a/src/pmemfile-fuse/main.c b/src/pmemfile-fuse/main.c index ce99fe496..5485e6831 100644 --- a/src/pmemfile-fuse/main.c +++ b/src/pmemfile-fuse/main.c @@ -57,10 +57,14 @@ update_ctx(PMEMfilepool *pfp) { struct fuse_context *ctx = fuse_get_context(); - if (pmemfile_setreuid(pfp, ctx->uid, ctx->uid) < 0) + if (pmemfile_setreuid(pfp, ctx->uid, ctx->uid) < 0) { + log("pmemfile_setreuid failed: %d\n", errno); return -errno; - if (pmemfile_setregid(pfp, ctx->gid, ctx->gid) < 0) + } + if (pmemfile_setregid(pfp, ctx->gid, ctx->gid) < 0) { + log("pmemfile_setregid failed: %d\n", errno); return -errno; + } pmemfile_umask(pfp, ctx->umask); return 0; @@ -77,8 +81,10 @@ pmemfile_fuse_getattr(const char *path, struct stat *statbuf) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_lstat(pfp, path, statbuf) < 0) + if (pmemfile_lstat(pfp, path, statbuf) < 0) { + log("pmemfile_lstat %s failed: %d\n", path, errno); return -errno; + } return 0; } @@ -95,8 +101,10 @@ pmemfile_fuse_opendir(const char *path, struct fuse_file_info *fi) return ret; PMEMfile *f = pmemfile_open(pfp, path, O_DIRECTORY); - if (f == NULL) + if (f == NULL) { + log("pmemfile_open %s failed: %d\n", path, errno); return -errno; + } fi->fh = (uintptr_t)f; return 0; @@ -129,8 +137,10 @@ pmemfile_fuse_readdir(const char *path, void *buff, fuse_fill_dir_t fill, if (!dir) return -EBADF; - if (pmemfile_lseek(pfp, dir, off, PMEMFILE_SEEK_SET) != off) + if (pmemfile_lseek(pfp, dir, off, PMEMFILE_SEEK_SET) != off) { + log("pmemfile_lseek failed: %d\n", errno); return -errno; + } char dirp[32758]; struct stat statbuf; @@ -181,8 +191,10 @@ pmemfile_fuse_mkdir(const char *path, mode_t mode) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_mkdir(pfp, path, mode) < 0) + if (pmemfile_mkdir(pfp, path, mode) < 0) { + log("pmemfile_mkdir %s failed: %d\n", path, errno); return -errno; + } return 0; } @@ -198,8 +210,10 @@ pmemfile_fuse_rmdir(const char *path) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_rmdir(pfp, path) < 0) + if (pmemfile_rmdir(pfp, path) < 0) { + log("pmemfile_rmdir %s failed: %d\n", path, errno); return -errno; + } return 0; } @@ -214,8 +228,10 @@ pmemfile_fuse_chmod(const char *path, mode_t mode) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_chmod(pfp, path, mode) < 0) + if (pmemfile_chmod(pfp, path, mode) < 0) { + log("pmemfile_chmod %s failed: %d\n", path, errno); return -errno; + } return 0; } @@ -231,8 +247,10 @@ pmemfile_fuse_chown(const char *path, uid_t uid, gid_t gid) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_chown(pfp, path, uid, gid) < 0) + if (pmemfile_chown(pfp, path, uid, gid) < 0) { + log("pmemfile_chown %s failed: %d\n", path, errno); return -errno; + } return 0; } @@ -249,12 +267,13 @@ pmemfile_fuse_create(const char *path, mode_t mode, struct fuse_file_info *fi) return ret; PMEMfile *f = pmemfile_create(pfp, path, mode); - if (f) - fi->fh = (uintptr_t)f; - else - ret = -errno; + if (!f) { + log("pmemfile_create %s failed: %d\n", path, errno); + return -errno; + } + fi->fh = (uintptr_t)f; - return ret; + return 0; } static int @@ -268,8 +287,10 @@ pmemfile_fuse_utimens(const char *path, const struct timespec tv[2]) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_utimensat(pfp, NULL, path, tv, 0) < 0) + if (pmemfile_utimensat(pfp, NULL, path, tv, 0) < 0) { + log("pmemfile_utimens %s failed: %d\n", path, errno); return -errno; + } return 0; } @@ -290,8 +311,10 @@ pmemfile_fuse_open(const char *path, struct fuse_file_info *fi) * (O_LARGEFILE, which userspace on x86_64 defines as 0) */ PMEMfile *f = pmemfile_open(pfp, path, fi->flags & ~0x8000); - if (f == NULL) + if (f == NULL) { + log("pmemfile_open %s failed: %d\n", path, errno); return -errno; + } fi->fh = (uintptr_t)f; return 0; @@ -325,8 +348,10 @@ pmemfile_fuse_write(const char *path, const char *buff, size_t size, size = INT32_MAX; int ret = (int)pmemfile_pwrite(PFP, f, buff, size, off); - if (ret < 0) + if (ret < 0) { + log("pmemfile_pwrite %zd failed: %d\n", size, errno); return -errno; + } return ret; } @@ -345,8 +370,10 @@ pmemfile_fuse_read(const char *path, char *buff, size_t size, off_t off, size = INT32_MAX; int ret = (int)pmemfile_pread(PFP, f, buff, size, off); - if (ret < 0) + if (ret < 0) { + log("pmemfile_pread %zd failed: %d\n", size, errno); return -errno; + } return ret; } @@ -361,8 +388,10 @@ pmemfile_fuse_truncate(const char *path, off_t off) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_truncate(pfp, path, off) < 0) + if (pmemfile_truncate(pfp, path, off) < 0) { + log("pmemfile_truncate %s failed: %d\n", path, errno); return -errno; + } return 0; } @@ -381,8 +410,10 @@ pmemfile_fuse_ftruncate(const char *path, off_t off, struct fuse_file_info *fi) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_ftruncate(pfp, (PMEMfile *)fi->fh, off) < 0) + if (pmemfile_ftruncate(pfp, (PMEMfile *)fi->fh, off) < 0) { + log("pmemfile_ftruncate %s failed: %d\n", path, errno); return -errno; + } return 0; } @@ -398,8 +429,10 @@ pmemfile_fuse_unlink(const char *path) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_unlink(pfp, path) < 0) + if (pmemfile_unlink(pfp, path) < 0) { + log("pmemfile_unlink %s failed: %d\n", path, errno); return -errno; + } return 0; } @@ -415,8 +448,10 @@ pmemfile_fuse_link(const char *path1, const char *path2) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_link(pfp, path1, path2) < 0) + if (pmemfile_link(pfp, path1, path2) < 0) { + log("pmemfile_link %s %s failed: %d\n", path1, path2, errno); return -errno; + } return 0; } @@ -439,7 +474,7 @@ pmemfile_fuse_ioctl(const char *path, int cmd, void *arg, static int pmemfile_fuse_rename(const char *path, const char *dest) { - log("%s\n", path); + log("%s %s\n", path, dest); int ret; PMEMfilepool *pfp = PFP; @@ -447,8 +482,10 @@ pmemfile_fuse_rename(const char *path, const char *dest) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_rename(pfp, path, dest) < 0) + if (pmemfile_rename(pfp, path, dest) < 0) { + log("pmemfile_rename %s %s failed: %d\n", path, dest, errno); return -errno; + } return 0; } @@ -456,7 +493,7 @@ pmemfile_fuse_rename(const char *path, const char *dest) static int pmemfile_fuse_symlink(const char *path, const char *link) { - log("%s\n", path); + log("%s %s\n", path, link); int ret; PMEMfilepool *pfp = PFP; @@ -464,8 +501,10 @@ pmemfile_fuse_symlink(const char *path, const char *link) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_symlink(pfp, path, link) < 0) + if (pmemfile_symlink(pfp, path, link) < 0) { + log("pmemfile_symlink %s %s failed: %d\n", path, link, errno); return -errno; + } return 0; } @@ -482,8 +521,10 @@ pmemfile_fuse_readlink(const char *path, char *buff, size_t size) return ret; ret = (int)pmemfile_readlink(pfp, path, buff, size - 1); - if (ret < 0) + if (ret < 0) { + log("pmemfile_readlink %s failed: %d\n", path, errno); return -errno; + } buff[ret] = 0; return 0; @@ -499,8 +540,10 @@ pmemfile_fuse_mknod(const char *path, mode_t mode, dev_t dev) if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_mknodat(pfp, NULL, path, mode, dev) < 0) + if (pmemfile_mknodat(pfp, NULL, path, mode, dev) < 0) { + log("pmemfile_mknod %s failed: %d\n", path, errno); return -errno; + } return 0; } @@ -511,7 +554,8 @@ pmemfile_fuse_fallocate(const char *path, int mode, off_t offset, off_t size, { log("%s\n", path); - if (!fi->fh) + PMEMfile *f = (PMEMfile *)fi->fh; + if (!f) return -EBADF; int ret; @@ -520,8 +564,10 @@ pmemfile_fuse_fallocate(const char *path, int mode, off_t offset, off_t size, if ((ret = update_ctx(pfp)) < 0) return ret; - if (pmemfile_fallocate(pfp, (PMEMfile *)fi->fh, mode, offset, size) < 0) + if (pmemfile_fallocate(pfp, f, mode, offset, size) < 0) { + log("pmemfile_fallocate %s failed: %d\n", path, errno); return -errno; + } return 0; } From fd1280bc4ba342b4f93182b243237dba0630421c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20=C5=9Alusarz?= Date: Wed, 1 Nov 2017 23:23:03 +0100 Subject: [PATCH 6/6] fuse: fix reads from files created using O_CREAT|O_RDWR "create" hook doesn't have sys_creat semantics. When user passed O_CREAT | O_RDWR as flags to open, we created write-only file handle... --- src/pmemfile-fuse/main.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/pmemfile-fuse/main.c b/src/pmemfile-fuse/main.c index 5485e6831..e63dbb472 100644 --- a/src/pmemfile-fuse/main.c +++ b/src/pmemfile-fuse/main.c @@ -255,6 +255,17 @@ pmemfile_fuse_chown(const char *path, uid_t uid, gid_t gid) return 0; } +static PMEMfile * +pmemfile_open_wrapper(PMEMfilepool *pfp, const char *path, int flags, + pmemfile_mode_t mode) +{ + /* + * &~0x8000, because fuse passes flag pmemfile doesn't understand + * (O_LARGEFILE, which userspace on x86_64 defines as 0) + */ + return pmemfile_open(pfp, path, flags & ~0x8000, mode); +} + static int pmemfile_fuse_create(const char *path, mode_t mode, struct fuse_file_info *fi) { @@ -266,9 +277,9 @@ pmemfile_fuse_create(const char *path, mode_t mode, struct fuse_file_info *fi) if ((ret = update_ctx(pfp)) < 0) return ret; - PMEMfile *f = pmemfile_create(pfp, path, mode); + PMEMfile *f = pmemfile_open_wrapper(pfp, path, fi->flags, mode); if (!f) { - log("pmemfile_create %s failed: %d\n", path, errno); + log("pmemfile_open %s failed: %d\n", path, errno); return -errno; } fi->fh = (uintptr_t)f; @@ -306,11 +317,7 @@ pmemfile_fuse_open(const char *path, struct fuse_file_info *fi) if ((ret = update_ctx(pfp)) < 0) return ret; - /* - * &~0x8000, because fuse passes flag pmemfile doesn't understand - * (O_LARGEFILE, which userspace on x86_64 defines as 0) - */ - PMEMfile *f = pmemfile_open(pfp, path, fi->flags & ~0x8000); + PMEMfile *f = pmemfile_open_wrapper(pfp, path, fi->flags, 0); if (f == NULL) { log("pmemfile_open %s failed: %d\n", path, errno); return -errno;