From bf819d3ac2b015139a3571a953e0b361632ebb34 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 5 Oct 2021 14:03:26 +0200 Subject: [PATCH] basic: split out sync() family of calls from fs-util.[ch] into new c/h file No changes in code, just some splitting out. --- src/basic/fileio.c | 6 +- src/basic/fs-util.c | 166 --------------------- src/basic/fs-util.h | 8 -- src/basic/meson.build | 2 + src/basic/sync-util.c | 175 +++++++++++++++++++++++ src/basic/sync-util.h | 11 ++ src/boot/bless-boot.c | 1 + src/boot/bootctl.c | 8 +- src/coredump/coredump.c | 8 +- src/home/homed-manager.c | 1 + src/home/homework-luks.c | 1 + src/import/pull-job.c | 2 +- src/libsystemd/sd-id128/id128-util.c | 7 +- src/libsystemd/sd-journal/journal-file.c | 9 +- src/partition/repart.c | 1 + src/random-seed/random-seed.c | 1 + src/shared/copy.c | 1 + src/shared/install-file.c | 1 + src/shared/machine-id-setup.c | 2 +- src/shutdown/umount.c | 2 +- src/sysusers/sysusers.c | 1 + src/test/test-fs-util.c | 1 + 22 files changed, 216 insertions(+), 199 deletions(-) create mode 100644 src/basic/sync-util.c create mode 100644 src/basic/sync-util.h diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 601e1a61e9..a268a41add 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -25,6 +25,7 @@ #include "socket-util.h" #include "stdio-util.h" #include "string-util.h" +#include "sync-util.h" #include "tmpfile-util.h" /* The maximum size of the file we'll read in one go in read_full_file() (64M). */ @@ -1195,10 +1196,7 @@ int fflush_sync_and_check(FILE *f) { if (fd < 0) return 0; - if (fsync(fd) < 0) - return -errno; - - r = fsync_directory_of_file(fd); + r = fsync_full(fd); if (r < 0) return r; diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 6c3ef972fe..2412df197a 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -1349,172 +1349,6 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) { return 0; } -int fsync_directory_of_file(int fd) { - _cleanup_close_ int dfd = -1; - struct stat st; - int r; - - assert(fd >= 0); - - /* We only reasonably can do this for regular files and directories, or for O_PATH fds, hence check - * for the inode type first */ - if (fstat(fd, &st) < 0) - return -errno; - - if (S_ISDIR(st.st_mode)) { - dfd = openat(fd, "..", O_RDONLY|O_DIRECTORY|O_CLOEXEC, 0); - if (dfd < 0) - return -errno; - - } else if (!S_ISREG(st.st_mode)) { /* Regular files are OK regardless if O_PATH or not, for all other - * types check O_PATH flag */ - int flags; - - flags = fcntl(fd, F_GETFL); - if (flags < 0) - return -errno; - - if (!FLAGS_SET(flags, O_PATH)) /* If O_PATH this refers to the inode in the fs, in which case - * we can sensibly do what is requested. Otherwise this refers - * to a socket, fifo or device node, where the concept of a - * containing directory doesn't make too much sense. */ - return -ENOTTY; - } - - if (dfd < 0) { - _cleanup_free_ char *path = NULL; - - r = fd_get_path(fd, &path); - if (r < 0) { - log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m", - fd, - r == -ENOSYS ? ", ignoring" : ""); - - if (r == -ENOSYS) - /* If /proc is not available, we're most likely running in some - * chroot environment, and syncing the directory is not very - * important in that case. Let's just silently do nothing. */ - return 0; - - return r; - } - - if (!path_is_absolute(path)) - return -EINVAL; - - dfd = open_parent(path, O_CLOEXEC|O_NOFOLLOW, 0); - if (dfd < 0) - return dfd; - } - - if (fsync(dfd) < 0) - return -errno; - - return 0; -} - -int fsync_full(int fd) { - int r, q; - - /* Sync both the file and the directory */ - - r = fsync(fd) < 0 ? -errno : 0; - - q = fsync_directory_of_file(fd); - if (r < 0) /* Return earlier error */ - return r; - if (q == -ENOTTY) /* Ignore if the 'fd' refers to a block device or so which doesn't really have a - * parent dir */ - return 0; - return q; -} - -int fsync_path_at(int at_fd, const char *path) { - _cleanup_close_ int opened_fd = -1; - int fd; - - if (isempty(path)) { - if (at_fd == AT_FDCWD) { - opened_fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC); - if (opened_fd < 0) - return -errno; - - fd = opened_fd; - } else - fd = at_fd; - } else { - opened_fd = openat(at_fd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); - if (opened_fd < 0) - return -errno; - - fd = opened_fd; - } - - if (fsync(fd) < 0) - return -errno; - - return 0; -} - -int fsync_parent_at(int at_fd, const char *path) { - _cleanup_close_ int opened_fd = -1; - - if (isempty(path)) { - if (at_fd != AT_FDCWD) - return fsync_directory_of_file(at_fd); - - opened_fd = open("..", O_RDONLY|O_DIRECTORY|O_CLOEXEC); - if (opened_fd < 0) - return -errno; - - if (fsync(opened_fd) < 0) - return -errno; - - return 0; - } - - opened_fd = openat(at_fd, path, O_PATH|O_CLOEXEC|O_NOFOLLOW); - if (opened_fd < 0) - return -errno; - - return fsync_directory_of_file(opened_fd); -} - -int fsync_path_and_parent_at(int at_fd, const char *path) { - _cleanup_close_ int opened_fd = -1; - - if (isempty(path)) { - if (at_fd != AT_FDCWD) - return fsync_full(at_fd); - - opened_fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC); - } else - opened_fd = openat(at_fd, path, O_RDONLY|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC); - if (opened_fd < 0) - return -errno; - - return fsync_full(opened_fd); -} - -int syncfs_path(int atfd, const char *path) { - _cleanup_close_ int fd = -1; - - if (isempty(path)) { - if (atfd != AT_FDCWD) - return syncfs(atfd) < 0 ? -errno : 0; - - fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC); - } else - fd = openat(atfd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); - if (fd < 0) - return -errno; - - if (syncfs(fd) < 0) - return -errno; - - return 0; -} - int open_parent(const char *path, int flags, mode_t mode) { _cleanup_free_ char *parent = NULL; int fd, r; diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index d612cbe404..7120ecd99d 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -137,14 +137,6 @@ typedef enum UnlinkDeallocateFlags { int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags); -int fsync_directory_of_file(int fd); -int fsync_full(int fd); -int fsync_path_at(int at_fd, const char *path); -int fsync_parent_at(int at_fd, const char *path); -int fsync_path_and_parent_at(int at_fd, const char *path); - -int syncfs_path(int atfd, const char *path); - int open_parent(const char *path, int flags, mode_t mode); int conservative_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); diff --git a/src/basic/meson.build b/src/basic/meson.build index 82f42df929..7b42ac428c 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -215,6 +215,8 @@ basic_sources = files(''' strv.h strxcpyx.c strxcpyx.h + sync-util.c + sync-util.h sysctl-util.c sysctl-util.h syslog-util.c diff --git a/src/basic/sync-util.c b/src/basic/sync-util.c new file mode 100644 index 0000000000..479ff73c63 --- /dev/null +++ b/src/basic/sync-util.c @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include + +#include "fd-util.h" +#include "fs-util.h" +#include "path-util.h" +#include "sync-util.h" + +int fsync_directory_of_file(int fd) { + _cleanup_close_ int dfd = -1; + struct stat st; + int r; + + assert(fd >= 0); + + /* We only reasonably can do this for regular files and directories, or for O_PATH fds, hence check + * for the inode type first */ + if (fstat(fd, &st) < 0) + return -errno; + + if (S_ISDIR(st.st_mode)) { + dfd = openat(fd, "..", O_RDONLY|O_DIRECTORY|O_CLOEXEC, 0); + if (dfd < 0) + return -errno; + + } else if (!S_ISREG(st.st_mode)) { /* Regular files are OK regardless if O_PATH or not, for all other + * types check O_PATH flag */ + int flags; + + flags = fcntl(fd, F_GETFL); + if (flags < 0) + return -errno; + + if (!FLAGS_SET(flags, O_PATH)) /* If O_PATH this refers to the inode in the fs, in which case + * we can sensibly do what is requested. Otherwise this refers + * to a socket, fifo or device node, where the concept of a + * containing directory doesn't make too much sense. */ + return -ENOTTY; + } + + if (dfd < 0) { + _cleanup_free_ char *path = NULL; + + r = fd_get_path(fd, &path); + if (r < 0) { + log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m", + fd, + r == -ENOSYS ? ", ignoring" : ""); + + if (r == -ENOSYS) + /* If /proc is not available, we're most likely running in some + * chroot environment, and syncing the directory is not very + * important in that case. Let's just silently do nothing. */ + return 0; + + return r; + } + + if (!path_is_absolute(path)) + return -EINVAL; + + dfd = open_parent(path, O_CLOEXEC|O_NOFOLLOW, 0); + if (dfd < 0) + return dfd; + } + + if (fsync(dfd) < 0) + return -errno; + + return 0; +} + +int fsync_full(int fd) { + int r, q; + + /* Sync both the file and the directory */ + + r = fsync(fd) < 0 ? -errno : 0; + + q = fsync_directory_of_file(fd); + if (r < 0) /* Return earlier error */ + return r; + if (q == -ENOTTY) /* Ignore if the 'fd' refers to a block device or so which doesn't really have a + * parent dir */ + return 0; + return q; +} + +int fsync_path_at(int at_fd, const char *path) { + _cleanup_close_ int opened_fd = -1; + int fd; + + if (isempty(path)) { + if (at_fd == AT_FDCWD) { + opened_fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC); + if (opened_fd < 0) + return -errno; + + fd = opened_fd; + } else + fd = at_fd; + } else { + opened_fd = openat(at_fd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (opened_fd < 0) + return -errno; + + fd = opened_fd; + } + + if (fsync(fd) < 0) + return -errno; + + return 0; +} + +int fsync_parent_at(int at_fd, const char *path) { + _cleanup_close_ int opened_fd = -1; + + if (isempty(path)) { + if (at_fd != AT_FDCWD) + return fsync_directory_of_file(at_fd); + + opened_fd = open("..", O_RDONLY|O_DIRECTORY|O_CLOEXEC); + if (opened_fd < 0) + return -errno; + + if (fsync(opened_fd) < 0) + return -errno; + + return 0; + } + + opened_fd = openat(at_fd, path, O_PATH|O_CLOEXEC|O_NOFOLLOW); + if (opened_fd < 0) + return -errno; + + return fsync_directory_of_file(opened_fd); +} + +int fsync_path_and_parent_at(int at_fd, const char *path) { + _cleanup_close_ int opened_fd = -1; + + if (isempty(path)) { + if (at_fd != AT_FDCWD) + return fsync_full(at_fd); + + opened_fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC); + } else + opened_fd = openat(at_fd, path, O_RDONLY|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC); + if (opened_fd < 0) + return -errno; + + return fsync_full(opened_fd); +} + +int syncfs_path(int at_fd, const char *path) { + _cleanup_close_ int fd = -1; + + if (isempty(path)) { + if (at_fd != AT_FDCWD) + return syncfs(at_fd) < 0 ? -errno : 0; + + fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC); + } else + fd = openat(at_fd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) + return -errno; + + if (syncfs(fd) < 0) + return -errno; + + return 0; +} diff --git a/src/basic/sync-util.h b/src/basic/sync-util.h new file mode 100644 index 0000000000..e449440a53 --- /dev/null +++ b/src/basic/sync-util.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +int fsync_directory_of_file(int fd); +int fsync_full(int fd); + +int fsync_path_at(int at_fd, const char *path); +int fsync_parent_at(int at_fd, const char *path); +int fsync_path_and_parent_at(int at_fd, const char *path); + +int syncfs_path(int at_fd, const char *path); diff --git a/src/boot/bless-boot.c b/src/boot/bless-boot.c index 7d5a52841e..cb06886727 100644 --- a/src/boot/bless-boot.c +++ b/src/boot/bless-boot.c @@ -14,6 +14,7 @@ #include "parse-util.h" #include "path-util.h" #include "pretty-print.h" +#include "sync-util.h" #include "terminal-util.h" #include "util.h" #include "verbs.h" diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 27b0086406..91b36e91ba 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -38,6 +38,7 @@ #include "stdio-util.h" #include "string-util.h" #include "strv.h" +#include "sync-util.h" #include "terminal-util.h" #include "tmpfile-util.h" #include "umask-util.h" @@ -569,13 +570,12 @@ static int copy_file_with_version_check(const char *from, const char *to, bool f (void) copy_times(fd_from, fd_to, 0); - if (fsync(fd_to) < 0) { + r = fsync_full(fd_to); + if (r < 0) { (void) unlink_noerrno(t); - return log_error_errno(errno, "Failed to copy data from \"%s\" to \"%s\": %m", from, t); + return log_error_errno(r, "Failed to copy data from \"%s\" to \"%s\": %m", from, t); } - (void) fsync_directory_of_file(fd_to); - if (renameat(AT_FDCWD, t, AT_FDCWD, to) < 0) { (void) unlink_noerrno(t); return log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", t, to); diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 444b9ec374..d7eab3d36c 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -48,6 +48,7 @@ #include "string-table.h" #include "string-util.h" #include "strv.h" +#include "sync-util.h" #include "tmpfile-util.h" #include "user-record.h" #include "user-util.h" @@ -261,10 +262,9 @@ static int fix_permissions( (void) fix_acl(fd, uid); (void) fix_xattr(fd, context); - if (fsync(fd) < 0) - return log_error_errno(errno, "Failed to sync coredump %s: %m", coredump_tmpfile_name(filename)); - - (void) fsync_directory_of_file(fd); + r = fsync_full(fd); + if (r < 0) + return log_error_errno(r, "Failed to sync coredump %s: %m", coredump_tmpfile_name(filename)); r = link_tmpfile(fd, filename, target); if (r < 0) diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index 6549e6bd4e..070fd97d69 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -38,6 +38,7 @@ #include "socket-util.h" #include "stat-util.h" #include "strv.h" +#include "sync-util.h" #include "tmpfile-util.h" #include "udev-util.h" #include "user-record-sign.h" diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index 2321a31021..8af9223d57 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -36,6 +36,7 @@ #include "resize-fs.h" #include "stat-util.h" #include "strv.h" +#include "sync-util.h" #include "tmpfile-util.h" /* Round down to the nearest 4K size. Given that newer hardware generally prefers 4K sectors, let's align our diff --git a/src/import/pull-job.c b/src/import/pull-job.c index 4e37dce33f..34b116a8f8 100644 --- a/src/import/pull-job.c +++ b/src/import/pull-job.c @@ -7,7 +7,6 @@ #include "alloc-util.h" #include "fd-util.h" #include "format-util.h" -#include "fs-util.h" #include "gcrypt-util.h" #include "hexdecoct.h" #include "import-util.h" @@ -18,6 +17,7 @@ #include "pull-job.h" #include "string-util.h" #include "strv.h" +#include "sync-util.h" #include "xattr-util.h" void pull_job_close_disk_fd(PullJob *j) { diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c index 2074771a41..19937110b0 100644 --- a/src/libsystemd/sd-id128/id128-util.c +++ b/src/libsystemd/sd-id128/id128-util.c @@ -5,12 +5,12 @@ #include #include "fd-util.h" -#include "fs-util.h" #include "hexdecoct.h" #include "id128-util.h" #include "io-util.h" #include "stdio-util.h" #include "string-util.h" +#include "sync-util.h" char *id128_to_uuid_string(sd_id128_t id, char s[static ID128_UUID_STRING_MAX]) { unsigned n, k = 0; @@ -167,10 +167,7 @@ int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) { return r; if (do_sync) { - if (fsync(fd) < 0) - return -errno; - - r = fsync_directory_of_file(fd); + r = fsync_full(fd); if (r < 0) return r; } diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 9fecc84495..d5ceba2f8f 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -32,6 +32,7 @@ #include "stat-util.h" #include "string-util.h" #include "strv.h" +#include "sync-util.h" #include "xattr-util.h" #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem)) @@ -474,11 +475,9 @@ static int journal_file_refresh_header(JournalFile *f) { r = journal_file_set_online(f); - /* Sync the online state to disk */ - (void) fsync(f->fd); - - /* We likely just created a new file, also sync the directory this file is located in. */ - (void) fsync_directory_of_file(f->fd); + /* Sync the online state to disk; likely just created a new file, also sync the directory this file + * is located in. */ + (void) fsync_full(f->fd); return r; } diff --git a/src/partition/repart.c b/src/partition/repart.c index 564ee4835b..3203b48d8c 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -61,6 +61,7 @@ #include "string-table.h" #include "string-util.h" #include "strv.h" +#include "sync-util.h" #include "terminal-util.h" #include "tpm2-util.h" #include "user-util.h" diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c index e003ca60e3..7724e0365e 100644 --- a/src/random-seed/random-seed.c +++ b/src/random-seed/random-seed.c @@ -25,6 +25,7 @@ #include "parse-util.h" #include "random-util.h" #include "string-util.h" +#include "sync-util.h" #include "util.h" #include "xattr-util.h" diff --git a/src/shared/copy.c b/src/shared/copy.c index f27ce252ee..9053fce333 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -29,6 +29,7 @@ #include "stdio-util.h" #include "string-util.h" #include "strv.h" +#include "sync-util.h" #include "time-util.h" #include "tmpfile-util.h" #include "umask-util.h" diff --git a/src/shared/install-file.c b/src/shared/install-file.c index 664f028ad1..5187d71bec 100644 --- a/src/shared/install-file.c +++ b/src/shared/install-file.c @@ -10,6 +10,7 @@ #include "install-file.h" #include "missing_syscall.h" #include "rm-rf.h" +#include "sync-util.h" int fs_make_very_read_only(int fd) { struct stat st; diff --git a/src/shared/machine-id-setup.c b/src/shared/machine-id-setup.c index d2f989272d..e483675a75 100644 --- a/src/shared/machine-id-setup.c +++ b/src/shared/machine-id-setup.c @@ -9,7 +9,6 @@ #include "alloc-util.h" #include "fd-util.h" -#include "fs-util.h" #include "id128-util.h" #include "io-util.h" #include "log.h" @@ -23,6 +22,7 @@ #include "process-util.h" #include "stat-util.h" #include "string-util.h" +#include "sync-util.h" #include "umask-util.h" #include "util.h" #include "virt.h" diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index c2a26242c0..09fc339ab1 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -23,7 +23,6 @@ #include "device-util.h" #include "escape.h" #include "fd-util.h" -#include "fs-util.h" #include "fstab-util.h" #include "libmount-util.h" #include "mount-setup.h" @@ -34,6 +33,7 @@ #include "signal-util.h" #include "string-util.h" #include "strv.h" +#include "sync-util.h" #include "umount.h" #include "util.h" #include "virt.h" diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 7daebdbe55..c55f7f8b7e 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -29,6 +29,7 @@ #include "specifier.h" #include "string-util.h" #include "strv.h" +#include "sync-util.h" #include "tmpfile-util-label.h" #include "uid-range.h" #include "user-record.h" diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index ac7ee5d3bf..f0cac447c3 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -16,6 +16,7 @@ #include "stdio-util.h" #include "string-util.h" #include "strv.h" +#include "sync-util.h" #include "tests.h" #include "tmpfile-util.h" #include "umask-util.h"