parent
03ba43f400
commit
b3c10803a2
@ -0,0 +1,217 @@
|
|||||||
|
From c26a519da1ed182e7cfd67e7a353932dda53d811 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= <jpandre@users.sourceforge.net>
|
||||||
|
Date: Mon, 4 Aug 2014 17:39:50 +0200
|
||||||
|
Subject: [PATCH] Fixed fstrim(8) applied to partitions
|
||||||
|
|
||||||
|
The new way goes via /sys/dev/block/MAJOR:MINOR to map partitions to
|
||||||
|
devices and get discard parameters of the parent device. It also ensures
|
||||||
|
that the partition is aligned to the discard block size.
|
||||||
|
|
||||||
|
Contributed by Richard W.M. Jones
|
||||||
|
---
|
||||||
|
libntfs-3g/ioctl.c | 140 ++++++++++++++++++++++++++---------------------------
|
||||||
|
1 file changed, 68 insertions(+), 72 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libntfs-3g/ioctl.c b/libntfs-3g/ioctl.c
|
||||||
|
index bbbceb9..eb7c8e7 100644
|
||||||
|
--- a/libntfs-3g/ioctl.c
|
||||||
|
+++ b/libntfs-3g/ioctl.c
|
||||||
|
@@ -66,8 +66,6 @@
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-#include <dirent.h>
|
||||||
|
-
|
||||||
|
#include "compat.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "bitmap.h"
|
||||||
|
@@ -135,17 +133,14 @@ static int read_u64(const char *path, u64 *n)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find discard limits for current backing device.
|
||||||
|
- * XXX Kernel makes this a pain in the neck.
|
||||||
|
*/
|
||||||
|
-static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity,
|
||||||
|
+static int fstrim_limits(ntfs_volume *vol,
|
||||||
|
+ u64 *discard_alignment,
|
||||||
|
+ u64 *discard_granularity,
|
||||||
|
u64 *discard_max_bytes)
|
||||||
|
{
|
||||||
|
struct stat statbuf;
|
||||||
|
- DIR *dir;
|
||||||
|
- struct dirent *d;
|
||||||
|
- char path[80];
|
||||||
|
- char line[64];
|
||||||
|
- char dev[64];
|
||||||
|
+ char path1[80], path2[80];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Stat the backing device. Caller has ensured it is a block device. */
|
||||||
|
@@ -155,82 +150,78 @@ static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity,
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* Now look for a /sys/block/<dev>/dev file which contains
|
||||||
|
- * "major:minor\n".
|
||||||
|
+ /* For whole devices,
|
||||||
|
+ * /sys/dev/block/MAJOR:MINOR/discard_alignment
|
||||||
|
+ * /sys/dev/block/MAJOR:MINOR/queue/discard_granularity
|
||||||
|
+ * /sys/dev/block/MAJOR:MINOR/queue/discard_max_bytes
|
||||||
|
+ * will exist.
|
||||||
|
+ * For partitions, we also need to check the parent device:
|
||||||
|
+ * /sys/dev/block/MAJOR:MINOR/../queue/discard_granularity
|
||||||
|
+ * /sys/dev/block/MAJOR:MINOR/../queue/discard_max_bytes
|
||||||
|
*/
|
||||||
|
- snprintf(dev, sizeof dev, "%d:%d\n",
|
||||||
|
+ snprintf(path1, sizeof path1, "/sys/dev/block/%d:%d",
|
||||||
|
major(statbuf.st_rdev), minor(statbuf.st_rdev));
|
||||||
|
|
||||||
|
- dir = opendir("/sys/block");
|
||||||
|
- if (dir == NULL) {
|
||||||
|
- ntfs_log_debug("fstrim_limits: could not open /sys/block\n");
|
||||||
|
- return -errno;
|
||||||
|
+ snprintf(path2, sizeof path2, "%s/discard_alignment", path1);
|
||||||
|
+ ret = read_u64(path2, discard_alignment);
|
||||||
|
+ if (ret) {
|
||||||
|
+ if (ret != -ENOENT)
|
||||||
|
+ return ret;
|
||||||
|
+ else
|
||||||
|
+ /* We would expect this file to exist on all
|
||||||
|
+ * modern kernels. But for the sake of very
|
||||||
|
+ * old kernels:
|
||||||
|
+ */
|
||||||
|
+ goto not_found;
|
||||||
|
}
|
||||||
|
- for (;;) {
|
||||||
|
- errno = 0;
|
||||||
|
- d = readdir(dir);
|
||||||
|
- if (!d) break;
|
||||||
|
|
||||||
|
- snprintf(path, sizeof path, "/sys/block/%s/dev", d->d_name);
|
||||||
|
- ret = read_line(path, line, sizeof line);
|
||||||
|
- if (ret)
|
||||||
|
- continue;
|
||||||
|
- if (strcmp(line, dev) == 0)
|
||||||
|
- goto found;
|
||||||
|
+ snprintf(path2, sizeof path2, "%s/queue/discard_granularity", path1);
|
||||||
|
+ ret = read_u64(path2, discard_granularity);
|
||||||
|
+ if (ret) {
|
||||||
|
+ if (ret != -ENOENT)
|
||||||
|
+ return ret;
|
||||||
|
+ else {
|
||||||
|
+ snprintf(path2, sizeof path2,
|
||||||
|
+ "%s/../queue/discard_granularity", path1);
|
||||||
|
+ ret = read_u64(path2, discard_granularity);
|
||||||
|
+ if (ret) {
|
||||||
|
+ if (ret != -ENOENT)
|
||||||
|
+ return ret;
|
||||||
|
+ else
|
||||||
|
+ goto not_found;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* Check readdir didn't fail. */
|
||||||
|
- if (errno != 0) {
|
||||||
|
- ret = -errno;
|
||||||
|
- ntfs_log_debug("fstrim_limits: readdir failed\n");
|
||||||
|
- goto out;
|
||||||
|
+ snprintf(path2, sizeof path2, "%s/queue/discard_max_bytes", path1);
|
||||||
|
+ ret = read_u64(path2, discard_max_bytes);
|
||||||
|
+ if (ret) {
|
||||||
|
+ if (ret != -ENOENT)
|
||||||
|
+ return ret;
|
||||||
|
+ else {
|
||||||
|
+ snprintf(path2, sizeof path2,
|
||||||
|
+ "%s/../queue/discard_max_bytes", path1);
|
||||||
|
+ ret = read_u64(path2, discard_max_bytes);
|
||||||
|
+ if (ret) {
|
||||||
|
+ if (ret != -ENOENT)
|
||||||
|
+ return ret;
|
||||||
|
+ else
|
||||||
|
+ goto not_found;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+not_found:
|
||||||
|
/* If we reach here then we didn't find the device. This is
|
||||||
|
* not an error, but set discard_max_bytes = 0 to indicate
|
||||||
|
* that discard is not available.
|
||||||
|
*/
|
||||||
|
+ *discard_alignment = 0;
|
||||||
|
*discard_granularity = 0;
|
||||||
|
*discard_max_bytes = 0;
|
||||||
|
- ntfs_log_debug("fstrim_limits: /sys/block entry corresponding to device %s not found\n",
|
||||||
|
- vol->dev->d_name);
|
||||||
|
- ret = 0;
|
||||||
|
- goto out;
|
||||||
|
-
|
||||||
|
-found:
|
||||||
|
- /* Found the device at /sys/block/ + d->d_name */
|
||||||
|
- snprintf (path, sizeof path,
|
||||||
|
- "/sys/block/%s/queue/discard_granularity",
|
||||||
|
- d->d_name);
|
||||||
|
- ret = read_u64(path, discard_granularity);
|
||||||
|
- if (ret) {
|
||||||
|
- ntfs_log_debug("fstrim_limits: could not read %s\n", path);
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- snprintf (path, sizeof path,
|
||||||
|
- "/sys/block/%s/queue/discard_max_bytes",
|
||||||
|
- d->d_name);
|
||||||
|
- ret = read_u64(path, discard_max_bytes);
|
||||||
|
- if (ret) {
|
||||||
|
- ntfs_log_debug("fstrim_limits: could not read %s\n", path);
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- ntfs_log_debug("fstrim_limits: device %s discard granularity = %llu max_bytes = %llu\n",
|
||||||
|
- d->d_name,
|
||||||
|
- (unsigned long long) *discard_granularity,
|
||||||
|
- (unsigned long long) *discard_max_bytes);
|
||||||
|
-
|
||||||
|
- ret = 0;
|
||||||
|
-out:
|
||||||
|
- if (closedir (dir) == -1) {
|
||||||
|
- ret = -errno;
|
||||||
|
- ntfs_log_debug("fstrim_limits: closedir failed\n");
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return ret;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FSTRIM_BUFSIZ 4096
|
||||||
|
@@ -247,7 +238,7 @@ static int fstrim(ntfs_volume *vol, void *data)
|
||||||
|
u64 start = range->start;
|
||||||
|
u64 len = range->len;
|
||||||
|
u64 minlen = range->minlen;
|
||||||
|
- u64 discard_granularity, discard_max_bytes;
|
||||||
|
+ u64 discard_alignment, discard_granularity, discard_max_bytes;
|
||||||
|
u8 *buf = NULL;
|
||||||
|
LCN start_buf;
|
||||||
|
int ret;
|
||||||
|
@@ -279,9 +270,14 @@ static int fstrim(ntfs_volume *vol, void *data)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = fstrim_limits(vol, &discard_granularity, &discard_max_bytes);
|
||||||
|
+ ret = fstrim_limits(vol, &discard_alignment,
|
||||||
|
+ &discard_granularity, &discard_max_bytes);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
+ if (discard_alignment != 0) {
|
||||||
|
+ ntfs_log_debug("fstrim: backing device is not aligned for discards\n");
|
||||||
|
+ return -EOPNOTSUPP;
|
||||||
|
+ }
|
||||||
|
if (discard_granularity > vol->cluster_size) {
|
||||||
|
ntfs_log_debug("fstrim: discard granularity of backing device is larger than cluster size\n");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
--
|
||||||
|
1.9.3
|
||||||
|
|
Loading…
Reference in new issue