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