However deny discard if the partition is not aligned to the underlying
discard block size.
---
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
------------------------------------------------------------------------------
Infragistics Professional
Build stunning WinForms apps today!
Reboot your WinForms applications with our WinForms controls.
Build a bridge from your legacy apps to the future.
http://pubads.g.doubleclick.net/gampad/clk?id=153845071&iu=/4140/ostg.clktrk
_______________________________________________
ntfs-3g-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ntfs-3g-devel