mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-12 08:58:20 +03:00
tmpfiles: Try to take a BSD lock on files as well
Similar to what we do for directories, just before we remove a file, let's try to take a BSD lock on it. If that fails, skip removing the file.
This commit is contained in:
parent
5ccf06074a
commit
65e179a1e7
@ -111,14 +111,13 @@ strategies to avoid these issues:
|
||||
towards unexpected program termination as there are never files on disk that
|
||||
need to be explicitly deleted.
|
||||
|
||||
3. 🥇 Operate below a sub-directory of `/tmp/` and `/var/tmp/` you created, and
|
||||
take a BSD file lock ([`flock(dir_fd,
|
||||
LOCK_SH)`](https://man7.org/linux/man-pages/man2/flock.2.html)) on that
|
||||
sub-directory. This is particularly interesting when operating on more than
|
||||
a single file, or on file nodes that are not plain regular files, for
|
||||
example when extracting a tarball to a temporary directory. The ageing
|
||||
algorithm will skip all directories (and everything below them) that are
|
||||
locked through a BSD file lock. As BSD file locks are automatically released
|
||||
3. 🥇 Take an exclusive or shared BSD file lock ([`flock()`](
|
||||
https://man7.org/linux/man-pages/man2/flock.2.html)) on files and directories
|
||||
you don't want to be removed. This is particularly interesting when operating
|
||||
on more than a single file, or on file nodes that are not plain regular files,
|
||||
for example when extracting a tarball to a temporary directory. The ageing
|
||||
algorithm will skip all directories (and everything below them) and files that
|
||||
are locked through a BSD file lock. As BSD file locks are automatically released
|
||||
when the file descriptor they are taken on is closed, and all file
|
||||
descriptors opened by a process are implicitly closed when it exits, this is
|
||||
a robust mechanism that ensures all temporary files are subject to ageing
|
||||
@ -127,9 +126,7 @@ strategies to avoid these issues:
|
||||
modification/access times, as extracted files are otherwise immediately
|
||||
candidates for deletion by the ageing algorithm. The
|
||||
[`flock`](https://man7.org/linux/man-pages/man1/flock.1.html) tool of the
|
||||
`util-linux` packages makes this concept available to shell scripts. Note
|
||||
that `systemd-tmpfiles` only checks for BSD file locks on directories, locks
|
||||
on other types of file nodes (including regular files) are not considered.
|
||||
`util-linux` packages makes this concept available to shell scripts.
|
||||
|
||||
4. Keep the access time of all temporary files created current. In regular
|
||||
intervals, use `utimensat()` or a related call to update the access time
|
||||
|
@ -131,7 +131,9 @@
|
||||
directories marked with <varname>D</varname> or
|
||||
<varname>R</varname>, and files or directories themselves
|
||||
marked with <varname>r</varname> or <varname>R</varname> are
|
||||
removed.</para></listitem>
|
||||
removed unless an exclusive or shared BSD lock is taken on them (see <citerefentry
|
||||
project='man-pages'><refentrytitle>flock</refentrytitle><manvolnum>2</manvolnum></citerefentry>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -647,13 +647,13 @@ w- /proc/sys/vm/swappiness - - - - 10</programlisting></para>
|
||||
# an hour ago in "/tmp/foo/bar", are subject to time-based cleanup.
|
||||
d /tmp/foo/bar - - - - bmA:1h -</programlisting></para>
|
||||
|
||||
<para>Note that while the aging algorithm is run a 'shared' BSD file lock (see <citerefentry
|
||||
<para>Note that while the aging algorithm is run an exclusive BSD file lock (see <citerefentry
|
||||
project='man-pages'><refentrytitle>flock</refentrytitle><manvolnum>2</manvolnum></citerefentry>) is
|
||||
taken on each directory the algorithm descends into (and each directory below that, and so on). If the
|
||||
aging algorithm finds a lock is already taken on some directory, it (and everything below it) is
|
||||
skipped. Applications may use this to temporarily exclude certain directory subtrees from the aging
|
||||
algorithm: the applications can take a BSD file lock themselves, and as long as they keep it aging of
|
||||
the directory and everything below it is disabled.</para>
|
||||
taken on each directory/file the algorithm decides to remove. If the aging algorithm finds a lock (
|
||||
shared or exclusive) is already taken on some directory/file, it (and everything below it) is skipped.
|
||||
Applications may use this to temporarily exclude certain directory subtrees from the aging algorithm:
|
||||
the applications can take a BSD file lock themselves, and as long as they keep it aging of the
|
||||
directory/file and everything below it is disabled.</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
|
@ -754,6 +754,8 @@ static int dir_cleanup(
|
||||
r = log_warning_errno(errno, "Failed to remove directory \"%s\", ignoring: %m", sub_path);
|
||||
|
||||
} else {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
/* Skip files for which the sticky bit is set. These are semantics we define, and are
|
||||
* unknown elsewhere. See XDG_RUNTIME_DIR specification for details. */
|
||||
if (sx.stx_mode & S_ISVTX) {
|
||||
@ -794,6 +796,14 @@ static int dir_cleanup(
|
||||
cutoff_nsec, sub_path, age_by_file, false))
|
||||
continue;
|
||||
|
||||
fd = xopenat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME, 0);
|
||||
if (fd < 0 && fd != -ENOENT)
|
||||
log_warning_errno(fd, "Opening file \"%s\" failed, ignoring: %m", sub_path);
|
||||
if (fd >= 0 && flock(fd, LOCK_EX|LOCK_NB) < 0 && errno == EAGAIN) {
|
||||
log_debug_errno(errno, "Couldn't acquire shared BSD lock on file \"%s\", skipping: %m", p);
|
||||
continue;
|
||||
}
|
||||
|
||||
log_debug("Removing \"%s\".", sub_path);
|
||||
if (unlinkat(dirfd(d), de->d_name, 0) < 0)
|
||||
if (errno != ENOENT)
|
||||
|
Loading…
x
Reference in New Issue
Block a user