|
|
edfd2c |
From 9272023b42febae7db1ec828016a980146095a83 Mon Sep 17 00:00:00 2001
|
|
|
edfd2c |
From: Karel Zak <kzak@redhat.com>
|
|
|
edfd2c |
Date: Thu, 2 Feb 2023 13:21:33 +0100
|
|
|
edfd2c |
Subject: fstrim: backport entries de-duplication
|
|
|
edfd2c |
|
|
|
edfd2c |
Upstream: http://github.com/util-linux/util-linux/commit/9dbc073e4c58a56f68da8209df19789131446f5e
|
|
|
edfd2c |
Upstream: http://github.com/util-linux/util-linux/commit/67f974d41d62c8b521fe81e1aac92562366f6a0a
|
|
|
edfd2c |
Upstream: http://github.com/util-linux/util-linux/commit/20af6cee463cd6329b4f06db3282a09be942bd7a
|
|
|
edfd2c |
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2121699
|
|
|
edfd2c |
Signed-off-by: Karel Zak <kzak@redhat.com>
|
|
|
edfd2c |
---
|
|
|
edfd2c |
sys-utils/fstrim.c | 88 ++++++++++++++++++++++++++++++++++++++--------
|
|
|
edfd2c |
1 file changed, 74 insertions(+), 14 deletions(-)
|
|
|
edfd2c |
|
|
|
edfd2c |
diff --git a/sys-utils/fstrim.c b/sys-utils/fstrim.c
|
|
|
edfd2c |
index 70870ef69..6aa523d72 100644
|
|
|
edfd2c |
--- a/sys-utils/fstrim.c
|
|
|
edfd2c |
+++ b/sys-utils/fstrim.c
|
|
|
edfd2c |
@@ -35,6 +35,7 @@
|
|
|
edfd2c |
|
|
|
edfd2c |
#include <sys/ioctl.h>
|
|
|
edfd2c |
#include <sys/stat.h>
|
|
|
edfd2c |
+#include <sys/vfs.h>
|
|
|
edfd2c |
#include <linux/fs.h>
|
|
|
edfd2c |
|
|
|
edfd2c |
#include "nls.h"
|
|
|
edfd2c |
@@ -43,6 +44,7 @@
|
|
|
edfd2c |
#include "closestream.h"
|
|
|
edfd2c |
#include "pathnames.h"
|
|
|
edfd2c |
#include "sysfs.h"
|
|
|
edfd2c |
+#include "statfs_magic.h"
|
|
|
edfd2c |
|
|
|
edfd2c |
#include <libmount.h>
|
|
|
edfd2c |
|
|
|
edfd2c |
@@ -84,6 +86,7 @@ static int fstrim_filesystem(const char *path, struct fstrim_range *rangetpl,
|
|
|
edfd2c |
goto done;
|
|
|
edfd2c |
}
|
|
|
edfd2c |
errno = 0;
|
|
|
edfd2c |
+
|
|
|
edfd2c |
if (ioctl(fd, FITRIM, &range)) {
|
|
|
edfd2c |
rc = errno == EOPNOTSUPP || errno == ENOTTY ? 1 : -errno;
|
|
|
edfd2c |
|
|
|
edfd2c |
@@ -114,7 +117,7 @@ static int has_discard(const char *devname, struct sysfs_cxt *wholedisk)
|
|
|
edfd2c |
struct sysfs_cxt cxt, *parent = NULL;
|
|
|
edfd2c |
uint64_t dg = 0;
|
|
|
edfd2c |
dev_t disk = 0, dev;
|
|
|
edfd2c |
- int rc;
|
|
|
edfd2c |
+ int rc, rdonly = 0;
|
|
|
edfd2c |
|
|
|
edfd2c |
dev = sysfs_devname_to_devno(devname, NULL);
|
|
|
edfd2c |
if (!dev)
|
|
|
edfd2c |
@@ -139,11 +142,46 @@ static int has_discard(const char *devname, struct sysfs_cxt *wholedisk)
|
|
|
edfd2c |
rc = sysfs_init(&cxt, dev, parent);
|
|
|
edfd2c |
if (!rc)
|
|
|
edfd2c |
rc = sysfs_read_u64(&cxt, "queue/discard_granularity", &dg;;
|
|
|
edfd2c |
+ if (!rc)
|
|
|
edfd2c |
+ sysfs_scanf(&cxt, "ro", "%d", &rdonly);
|
|
|
edfd2c |
|
|
|
edfd2c |
sysfs_deinit(&cxt);
|
|
|
edfd2c |
- return rc == 0 && dg > 0;
|
|
|
edfd2c |
+ return rc == 0 && dg > 0 && rdonly == 0;
|
|
|
edfd2c |
}
|
|
|
edfd2c |
|
|
|
edfd2c |
+static int is_unwanted_fs(struct libmnt_fs *fs, const char *tgt)
|
|
|
edfd2c |
+{
|
|
|
edfd2c |
+ struct statfs vfs;
|
|
|
edfd2c |
+ int fd, rc;
|
|
|
edfd2c |
+
|
|
|
edfd2c |
+ if (mnt_fs_is_pseudofs(fs))
|
|
|
edfd2c |
+ return 1;
|
|
|
edfd2c |
+ if (mnt_fs_is_netfs(fs))
|
|
|
edfd2c |
+ return 1;
|
|
|
edfd2c |
+ if (mnt_fs_is_swaparea(fs))
|
|
|
edfd2c |
+ return 1;
|
|
|
edfd2c |
+ if (mnt_fs_match_fstype(fs, "autofs"))
|
|
|
edfd2c |
+ return 1;
|
|
|
edfd2c |
+ if (mnt_fs_match_options(fs, "ro"))
|
|
|
edfd2c |
+ return 1;
|
|
|
edfd2c |
+
|
|
|
edfd2c |
+ fd = open(tgt, O_PATH);
|
|
|
edfd2c |
+ if (fd < 0)
|
|
|
edfd2c |
+ return 1;
|
|
|
edfd2c |
+ rc = fstatfs(fd, &vfs) != 0 || vfs.f_type == STATFS_AUTOFS_MAGIC;
|
|
|
edfd2c |
+ close(fd);
|
|
|
edfd2c |
+ if (rc)
|
|
|
edfd2c |
+ return 1;
|
|
|
edfd2c |
+
|
|
|
edfd2c |
+ /* FITRIM on read-only filesystem can fail, and it can fail */
|
|
|
edfd2c |
+ if (access(tgt, W_OK) != 0) {
|
|
|
edfd2c |
+ if (errno == EROFS)
|
|
|
edfd2c |
+ return 1;
|
|
|
edfd2c |
+ if (errno == EACCES)
|
|
|
edfd2c |
+ return 1;
|
|
|
edfd2c |
+ }
|
|
|
edfd2c |
+ return 0;
|
|
|
edfd2c |
+}
|
|
|
edfd2c |
|
|
|
edfd2c |
static int uniq_fs_target_cmp(
|
|
|
edfd2c |
struct libmnt_table *tb __attribute__((__unused__)),
|
|
|
edfd2c |
@@ -182,30 +220,38 @@ static int fstrim_all(struct fstrim_range *rangetpl, int verbose)
|
|
|
edfd2c |
|
|
|
edfd2c |
mnt_init_debug(0);
|
|
|
edfd2c |
|
|
|
edfd2c |
- itr = mnt_new_iter(MNT_ITER_BACKWARD);
|
|
|
edfd2c |
- if (!itr)
|
|
|
edfd2c |
- err(MNT_EX_FAIL, _("failed to initialize libmount iterator"));
|
|
|
edfd2c |
-
|
|
|
edfd2c |
tab = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO);
|
|
|
edfd2c |
if (!tab)
|
|
|
edfd2c |
err(MNT_EX_FAIL, _("failed to parse %s"), _PATH_PROC_MOUNTINFO);
|
|
|
edfd2c |
|
|
|
edfd2c |
+ if (mnt_table_is_empty(tab)) {
|
|
|
edfd2c |
+ mnt_unref_table(tab);
|
|
|
edfd2c |
+ return MNT_EX_SUCCESS;
|
|
|
edfd2c |
+ }
|
|
|
edfd2c |
+
|
|
|
edfd2c |
/* de-duplicate by mountpoints */
|
|
|
edfd2c |
mnt_table_uniq_fs(tab, 0, uniq_fs_target_cmp);
|
|
|
edfd2c |
|
|
|
edfd2c |
- /* de-duplicate by source */
|
|
|
edfd2c |
- mnt_table_uniq_fs(tab, MNT_UNIQ_FORWARD, uniq_fs_source_cmp);
|
|
|
edfd2c |
+ itr = mnt_new_iter(MNT_ITER_BACKWARD);
|
|
|
edfd2c |
+ if (!itr)
|
|
|
edfd2c |
+ err(MNT_EX_FAIL, _("failed to initialize libmount iterator"));
|
|
|
edfd2c |
|
|
|
edfd2c |
+ /* Remove useless entries and canonicalize the table */
|
|
|
edfd2c |
while (mnt_table_next_fs(tab, itr, &fs) == 0) {
|
|
|
edfd2c |
const char *src = mnt_fs_get_srcpath(fs),
|
|
|
edfd2c |
*tgt = mnt_fs_get_target(fs);
|
|
|
edfd2c |
char *path;
|
|
|
edfd2c |
int rc = 1;
|
|
|
edfd2c |
|
|
|
edfd2c |
- if (!src || !tgt || *src != '/' ||
|
|
|
edfd2c |
- mnt_fs_is_pseudofs(fs) ||
|
|
|
edfd2c |
- mnt_fs_is_netfs(fs))
|
|
|
edfd2c |
+ if (!tgt || is_unwanted_fs(fs, tgt)) {
|
|
|
edfd2c |
+ mnt_table_remove_fs(tab, fs);
|
|
|
edfd2c |
continue;
|
|
|
edfd2c |
+ }
|
|
|
edfd2c |
+
|
|
|
edfd2c |
+ if (!src || *src != '/') {
|
|
|
edfd2c |
+ mnt_table_remove_fs(tab, fs);
|
|
|
edfd2c |
+ continue;
|
|
|
edfd2c |
+ }
|
|
|
edfd2c |
|
|
|
edfd2c |
/* Is it really accessible mountpoint? Not all mountpoints are
|
|
|
edfd2c |
* accessible (maybe over mounted by another filesystem) */
|
|
|
edfd2c |
@@ -213,11 +259,25 @@ static int fstrim_all(struct fstrim_range *rangetpl, int verbose)
|
|
|
edfd2c |
if (path && strcmp(path, tgt) == 0)
|
|
|
edfd2c |
rc = 0;
|
|
|
edfd2c |
free(path);
|
|
|
edfd2c |
- if (rc)
|
|
|
edfd2c |
+ if (rc) {
|
|
|
edfd2c |
+ mnt_table_remove_fs(tab, fs);
|
|
|
edfd2c |
continue; /* overlaying mount */
|
|
|
edfd2c |
+ }
|
|
|
edfd2c |
|
|
|
edfd2c |
- if (!has_discard(src, &wholedisk))
|
|
|
edfd2c |
+ if (!has_discard(src, &wholedisk)) {
|
|
|
edfd2c |
+ mnt_table_remove_fs(tab, fs);
|
|
|
edfd2c |
continue;
|
|
|
edfd2c |
+ }
|
|
|
edfd2c |
+ }
|
|
|
edfd2c |
+
|
|
|
edfd2c |
+ /* de-duplicate by source */
|
|
|
edfd2c |
+ mnt_table_uniq_fs(tab, MNT_UNIQ_FORWARD, uniq_fs_source_cmp);
|
|
|
edfd2c |
+
|
|
|
edfd2c |
+ mnt_reset_iter(itr, MNT_ITER_BACKWARD);
|
|
|
edfd2c |
+
|
|
|
edfd2c |
+ /* Do FITRIM */
|
|
|
edfd2c |
+ while (mnt_table_next_fs(tab, itr, &fs) == 0) {
|
|
|
edfd2c |
+ const char *tgt = mnt_fs_get_target(fs);
|
|
|
edfd2c |
cnt++;
|
|
|
edfd2c |
|
|
|
edfd2c |
/*
|
|
|
edfd2c |
@@ -231,10 +291,10 @@ static int fstrim_all(struct fstrim_range *rangetpl, int verbose)
|
|
|
edfd2c |
if (fstrim_filesystem(tgt, rangetpl, verbose) < 0)
|
|
|
edfd2c |
cnt_err++;
|
|
|
edfd2c |
}
|
|
|
edfd2c |
+ mnt_free_iter(itr);
|
|
|
edfd2c |
|
|
|
edfd2c |
sysfs_deinit(&wholedisk);
|
|
|
edfd2c |
mnt_unref_table(tab);
|
|
|
edfd2c |
- mnt_free_iter(itr);
|
|
|
edfd2c |
|
|
|
edfd2c |
if (cnt && cnt == cnt_err)
|
|
|
edfd2c |
return MNT_EX_FAIL; /* all failed */
|
|
|
edfd2c |
--
|
|
|
edfd2c |
2.39.1
|
|
|
edfd2c |
|