From ddb5cce2a51e764621a1fa893360697a61fb438c Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 18 Jan 2023 10:27:47 -0800 Subject: [PATCH 1/2] Add quick utils flush_device helper Add a quick helper that just calls cache flushing ioctls on different kinds of files. Signed-off-by: Zach Brown --- utils/src/dev.c | 42 ++++++++++++++++++++++++++++++++++++++++++ utils/src/dev.h | 1 + 2 files changed, 43 insertions(+) diff --git a/utils/src/dev.c b/utils/src/dev.c index af1e91f6..2a0c9eb6 100644 --- a/utils/src/dev.c +++ b/utils/src/dev.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -103,3 +104,44 @@ char *size_str(u64 nr, unsigned size) return suffixes[i]; } + +/* + * Try to flush the local read cache for a device. This is only a best + * effort as these interfaces don't block waiting to fully purge the + * cache. This is OK because it's used by cached readers that are known + * to be racy anyway. + */ +int flush_device(int fd) +{ + struct stat st; + int ret; + + ret = fstat(fd, &st); + if (ret < 0) { + ret = -errno; + fprintf(stderr, "fstat failed: %s (%d)\n", strerror(errno), errno); + goto out; + } + + if (S_ISREG(st.st_mode)) { + ret = posix_fadvise(fd, 0, st.st_size, POSIX_FADV_DONTNEED); + if (ret < 0) { + ret = -errno; + fprintf(stderr, "POSIX_FADV_DONTNEED failed: %s (%d)\n", + strerror(errno), errno); + goto out; + } + + } else if (S_ISBLK(st.st_mode)) { + ret = ioctl(fd, BLKFLSBUF, 0); + if (ret < 0) { + ret = -errno; + fprintf(stderr, "BLKFLSBUF, failed: %s (%d)\n", strerror(errno), errno); + goto out; + } + } + + ret = 0; +out: + return ret; +} diff --git a/utils/src/dev.h b/utils/src/dev.h index df79fe4c..d483f70b 100644 --- a/utils/src/dev.h +++ b/utils/src/dev.h @@ -14,5 +14,6 @@ int device_size(char *path, int fd, char *use_type, u64 *size_ret); float size_flt(u64 nr, unsigned size); char *size_str(u64 nr, unsigned size); +int flush_device(int fd); #endif From 3363b4fb79afd719b906c74b50abbe3dbe814188 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 18 Jan 2023 10:44:14 -0800 Subject: [PATCH 2/2] Flush device caches in buffered util cmds Add calls to our new device cache flushing helper in commands that use buffered reads. Signed-off-by: Zach Brown --- utils/man/scoutfs.8 | 8 +++----- utils/src/mkfs.c | 50 ++++++++++++++++++++++++++++----------------- utils/src/print.c | 6 ++++++ 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/utils/man/scoutfs.8 b/utils/man/scoutfs.8 index 9cfb454c..a8a517ff 100644 --- a/utils/man/scoutfs.8 +++ b/utils/man/scoutfs.8 @@ -623,11 +623,9 @@ space of the volume making the output much more useful for inspection. .TP .B "META-DEVICE" The path to the metadata device for the filesystem whose metadata will be -printed. Since this command reads via the host's buffer cache, it may not -reflect the current blocks in the filesystem possibly written to the shared -block devices from another host, unless -.B blockdev \--flushbufs -command is used first. +printed. An attempt will be made to flush the host's buffer cache for +this device with the BLKFLSBUF ioctl, or with posix_fadvise() if +the path refers to a regular file. .RE .PD diff --git a/utils/src/mkfs.c b/utils/src/mkfs.c index 49295b0b..962927c9 100644 --- a/utils/src/mkfs.c +++ b/utils/src/mkfs.c @@ -118,6 +118,33 @@ struct mkfs_args { struct scoutfs_quorum_slot slots[SCOUTFS_QUORUM_MAX_SLOTS]; }; +static int open_mkfs_dev(struct mkfs_args *args, char *path, mode_t mode, char *which) +{ + int ret; + int fd = -1; + + fd = open(path, mode); + if (fd < 0) { + ret = -errno; + fprintf(stderr, "failed to open %s dev '%s': %s (%d)\n", + which, path, strerror(errno), errno); + goto out; + } + + ret = flush_device(fd); + if (ret < 0) + goto out; + + if (!args->force) + ret = check_bdev(fd, path, which); + +out: + if (ret < 0 && fd >= 0) + close(fd); + + return ret ?: fd; +} + /* * Make a new file system by writing: * - super blocks @@ -156,32 +183,17 @@ static int do_mkfs(struct mkfs_args *args) gettimeofday(&tv, NULL); pseudo_random_bytes(&fsid, sizeof(fsid)); - meta_fd = open(args->meta_device, O_RDWR | O_EXCL); + meta_fd = open_mkfs_dev(args, args->meta_device, O_RDWR | O_EXCL, "meta"); if (meta_fd < 0) { - ret = -errno; - fprintf(stderr, "failed to open '%s': %s (%d)\n", - args->meta_device, strerror(errno), errno); + ret = meta_fd; goto out; } - if (!args->force) { - ret = check_bdev(meta_fd, args->meta_device, "meta"); - if (ret) - return ret; - } - data_fd = open(args->data_device, O_RDWR | O_EXCL); + data_fd = open_mkfs_dev(args, args->data_device, O_RDWR | O_EXCL, "data"); if (data_fd < 0) { - ret = -errno; - fprintf(stderr, "failed to open '%s': %s (%d)\n", - args->data_device, strerror(errno), errno); + ret = data_fd; goto out; } - if (!args->force) { - ret = check_bdev(data_fd, args->data_device, "data"); - if (ret) - return ret; - } - super = calloc(1, SCOUTFS_BLOCK_SM_SIZE); bt = calloc(1, SCOUTFS_BLOCK_LG_SIZE); diff --git a/utils/src/print.c b/utils/src/print.c index f4975bca..b977da46 100644 --- a/utils/src/print.c +++ b/utils/src/print.c @@ -27,6 +27,7 @@ #include "avl.h" #include "srch.h" #include "leaf_item_hash.h" +#include "dev.h" static void print_block_header(struct scoutfs_block_header *hdr, int size) { @@ -1107,7 +1108,12 @@ static int do_print(struct print_args *args) return ret; } + ret = flush_device(fd); + if (ret < 0) + goto out; + ret = print_volume(fd, args); +out: close(fd); return ret; };