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
ntfs-3g-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ntfs-3g-devel

Reply via email to