---
 configure.ac  |   3 +-
 src/ntfs-3g.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 145 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..d0b2ee7 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
+#define _SYS_MOUNT_H 1 /* extremely ugly hack XXX */
+#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,125 @@ 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 cluster. */
+static int fstrim_one_cluster(LCN lcn)
+{
+       struct ntfs_device *dev = ctx->vol->dev;
+       uint64_t range[2];
+
+       //ntfs_log_debug("fstrim_one_cluster: %lld\n", (long long) lcn);
+
+       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] = 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;
+       LCN lcn;
+       s64 bufsize;
+       u8 *buf;
+       s64 br;
+       int ret = 0;
+
+       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;
+
+       /* Read the bitmap into memory.  XXX Potentially huge? */
+       bufsize = ctx->vol->lcnbmp_na->data_size;
+       buf = ntfs_malloc(bufsize);
+       if (!buf)
+               return -ENOMEM;
+       br = ntfs_attr_pread(ctx->vol->lcnbmp_na, 0, bufsize, buf);
+       if (br != bufsize) {
+               if (br >= 0)
+                       ret = -EIO;
+               else
+                       ret = -errno;
+               goto free_buf;
+       }
+
+       /* Find out which clusters are unused. */
+       for (lcn = 0; lcn < ctx->vol->lcnbmp_na->data_size * 8; lcn++) {
+               if (lcn >= ctx->vol->nr_clusters)
+                       break;
+               if (!ntfs_bit_get(buf, lcn)) { /* cluster not in use */
+                       ret = fstrim_one_cluster(lcn);
+                       if (ret)
+                               goto free_buf;
+               }
+       }
+
+free_buf:
+       free(buf);
+       return ret;
+}
+
+#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 +3533,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 +3554,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


------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
ntfs-3g-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ntfs-3g-devel

Reply via email to