---
 configure.ac  |   3 +-
 src/ntfs-3g.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 156 insertions(+), 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index d1f7e10..9a3d51e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -471,7 +471,8 @@ AC_CHECK_HEADERS([ctype.h fcntl.h libgen.h libintl.h 
limits.h locale.h \
        regex.h endian.h byteswap.h sys/byteorder.h sys/disk.h sys/endian.h \
        sys/param.h sys/ioctl.h sys/mkdev.h sys/mount.h sys/stat.h sys/types.h \
        sys/vfs.h sys/statvfs.h sys/sysmacros.h linux/major.h linux/fd.h \
-       linux/hdreg.h machine/endian.h windows.h syslog.h pwd.h malloc.h])
+       linux/fs.h linux/hdreg.h \
+       machine/endian.h windows.h syslog.h pwd.h malloc.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_HEADER_STDBOOL
diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c
index 94bb138..98be8cd 100644
--- a/src/ntfs-3g.c
+++ b/src/ntfs-3g.c
@@ -82,7 +82,13 @@
 #include <sys/param.h>
 #endif /* defined(__APPLE__) || defined(__DARWIN__), ... */
 
+#ifdef HAVE_LINUX_FS_H
+#include <sys/mount.h>
+#include <linux/fs.h>
+#endif
+
 #include "compat.h"
+#include "bitmap.h"
 #include "attrib.h"
 #include "inode.h"
 #include "volume.h"
@@ -101,6 +107,14 @@
 
 #include "ntfs-3g_common.h"
 
+/* fuse-lite doesn't contain support for ioctl yet.  This can be removed
+ * and all HAVE_IOCTL_IN_FUSE made unconditional below when ioctl support
+ * is added to fuse-lite.
+ */
+#if defined(FUSE_IOCTL_COMPAT) && defined(FUSE_CAP_IOCTL_DIR)
+#  define HAVE_IOCTL_IN_FUSE 1
+#endif
+
 /*
  *     The following permission checking modes are governed by
  *     the HPERMSCONFIG value in param.h
@@ -642,7 +656,8 @@ int ntfs_macfuse_setchgtime(const char *path, const struct 
timespec *tv)
 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
 
 #if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \
-               || (defined(__APPLE__) || defined(__DARWIN__))
+       || defined(HAVE_IOCTL_IN_FUSE) \
+       || (defined(__APPLE__) || defined(__DARWIN__))
 static void *ntfs_init(struct fuse_conn_info *conn)
 {
 #if defined(__APPLE__) || defined(__DARWIN__)
@@ -658,6 +673,9 @@ static void *ntfs_init(struct fuse_conn_info *conn)
                        >= SAFE_CAPACITY_FOR_BIG_WRITES))
                conn->want |= FUSE_CAP_BIG_WRITES;
 #endif
+#ifdef HAVE_IOCTL_IN_FUSE
+       conn->want |= FUSE_CAP_IOCTL_DIR;
+#endif
        return NULL;
 }
 #endif /* defined(FUSE_CAP_DONT_MASK) || (defined(__APPLE__) || 
defined(__DARWIN__)) */
@@ -2445,6 +2463,136 @@ static int ntfs_fuse_fsync(const char *path 
__attribute__((unused)),
        return (ret);
 }
 
+#ifdef HAVE_IOCTL_IN_FUSE
+
+#if defined(FITRIM) && defined(BLKDISCARD)
+
+/* Issue a TRIM request to the underlying device for the given clusters. */
+static int fstrim_clusters(LCN lcn, s64 length)
+{
+       struct ntfs_device *dev = ctx->vol->dev;
+       uint64_t range[2];
+
+       ntfs_log_debug("fstrim_clusters: %lld length %lld\n",
+               (long long) lcn, (long long) length);
+
+       if (!NDevBlock(dev)) {
+               ntfs_log_debug("fstrim: not supported for non-block-device\n");
+               return -EOPNOTSUPP;
+       }
+
+       range[0] = lcn << ctx->vol->cluster_size_bits;
+       range[1] = length * ctx->vol->cluster_size;
+
+       if (dev->d_ops->ioctl(dev, BLKDISCARD, range) == -1) {
+               ntfs_log_debug("fstrim_one_cluster: ioctl failed: %m\n");
+               return -errno;
+       }
+       return 0;
+}
+
+/* Trim the filesystem.
+ *
+ * Free blocks between 'start' and 'start+len-1' (both byte offsets)
+ * are found and TRIM requests are sent to the block device.  'minlen'
+ * is the minimum continguous free range to discard.
+ */
+static int fstrim(struct fuse_file_info *fi, void *data)
+{
+       struct fstrim_range *range = data;
+       uint64_t start = range->start;
+       uint64_t len = range->len;
+       uint64_t minlen = range->minlen;
+       s64 p, data_size;
+       int ret;
+
+       ntfs_log_debug("fstrim: start=%llu len=%llu minlen=%llu\n",
+               (unsigned long long) start,
+               (unsigned long long) len,
+               (unsigned long long) minlen);
+
+       /* Fail if user tries to use the fstrim -o/-l/-m options.
+        * XXX We could fix these limitations in future.
+        */
+       if (start != 0 || len != (uint64_t)-1) {
+               ntfs_log_debug("fstrim: setting start or length is not 
supported\n");
+               return -EINVAL;
+       }
+       if (minlen > ctx->vol->cluster_size) {
+               ntfs_log_debug("fstrim: minlen > cluster size is not 
supported\n");
+               return -EINVAL;
+       }
+
+       /* Sync the device before doing anything. */
+       ret = ntfs_device_sync(ctx->vol->dev);
+       if (ret)
+               return ret;
+
+       data_size = ctx->vol->lcnbmp_na->data_size;
+
+       /* Read through the bitmap. */
+#define FSTRIM_BUFSIZ 4096
+       for (p = 0; p < data_size; p += FSTRIM_BUFSIZ) {
+               u8 buf[FSTRIM_BUFSIZ];
+               s64 count;
+               s64 br;
+               LCN lcn, end_lcn;
+
+               count = FSTRIM_BUFSIZ;
+               if (count > data_size-p)
+                       count = data_size-p;
+
+               br = ntfs_attr_pread(ctx->vol->lcnbmp_na, p, count, buf);
+               if (br != count) {
+                       if (br >= 0)
+                               return -EIO;
+                       else
+                               return -errno;
+               }
+
+               /* Trim the clusters in large as possible blocks. */
+               for (lcn = 0; lcn < count*8; ++lcn) {
+                       if (!ntfs_bit_get(buf, lcn)) {
+                               /* Cluster 'p*8 + lcn' is not in use,
+                                * find end of this run.
+                                */
+                               end_lcn = lcn+1;
+                               while (end_lcn < count*8 &&
+                                       !ntfs_bit_get(buf, end_lcn))
+                                       end_lcn++;
+                               ret = fstrim_clusters(p*8 + lcn, end_lcn-lcn);
+                               if (ret)
+                                       return ret;
+                               lcn = end_lcn;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+#endif /* FITRIM && BLKDISCARD */
+
+static int ntfs_fuse_ioctl(const char *path __attribute__((unused)),
+                       int cmd, void *arg __attribute__((unused)),
+                       struct fuse_file_info *fi,
+                       unsigned int flags, void *data)
+{
+       if (flags & FUSE_IOCTL_COMPAT)
+               return -ENOSYS;
+
+       switch (cmd) {
+#if defined(FITRIM) && defined(BLKDISCARD)
+       case FITRIM:
+               return fstrim(fi, data);
+#endif
+       }
+
+       return -EINVAL;
+}
+
+#endif /* HAVE_IOCTL_IN_FUSE */
+
 static int ntfs_fuse_bmap(const char *path, size_t blocksize, uint64_t *idx)
 {
        ntfs_inode *ni;
@@ -3396,6 +3544,9 @@ static struct fuse_operations ntfs_3g_ops = {
        .fsyncdir       = ntfs_fuse_fsync,
        .bmap           = ntfs_fuse_bmap,
        .destroy        = ntfs_fuse_destroy2,
+#ifdef HAVE_IOCTL_IN_FUSE
+        .ioctl         = ntfs_fuse_ioctl,
+#endif
 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
        .access         = ntfs_fuse_access,
        .opendir        = ntfs_fuse_opendir,
@@ -3414,7 +3565,8 @@ static struct fuse_operations ntfs_3g_ops = {
        .setchgtime     = ntfs_macfuse_setchgtime,
 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
 #if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \
-               || (defined(__APPLE__) || defined(__DARWIN__))
+       || defined(HAVE_IOCTL_IN_FUSE) \
+       || (defined(__APPLE__) || defined(__DARWIN__))
        .init           = ntfs_init
 #endif
 };
-- 
1.9.0


------------------------------------------------------------------------------
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

Reply via email to