1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-23 17:34:00 +03:00

basic: split out sync() family of calls from fs-util.[ch] into new c/h file

No changes in code, just some splitting out.
This commit is contained in:
Lennart Poettering 2021-10-05 14:03:26 +02:00
parent e66ee1d7e6
commit bf819d3ac2
22 changed files with 216 additions and 199 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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

175
src/basic/sync-util.c Normal file
View File

@ -0,0 +1,175 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <fcntl.h>
#include <sys/stat.h>
#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;
}

11
src/basic/sync-util.h Normal file
View File

@ -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);

View File

@ -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"

View File

@ -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);

View File

@ -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)

View File

@ -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"

View File

@ -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

View File

@ -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) {

View File

@ -5,12 +5,12 @@
#include <unistd.h>
#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;
}

View File

@ -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;
}

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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;

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"