Gentoo Archives: gentoo-commits

From: "Patrick McLean (chutzpah)" <chutzpah@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in sys-fs/ntfs3g/files: ntfs3g-2014.2.15-dont-put-things-in-root.patch ntfs3g-2014.2.15-update-fuse-lite-to-support-ioctls.patch ntfs3g-2014.2.15-fix-fstrim-applied-to-partitons.patch ntfs3g-2014.2.15-implement-fstrim.patch
Date: Thu, 29 Jan 2015 08:20:11
Message-Id: 20150129082005.B2C8C108EB@oystercatcher.gentoo.org
1 chutzpah 15/01/29 08:20:05
2
3 Added: ntfs3g-2014.2.15-dont-put-things-in-root.patch
4 ntfs3g-2014.2.15-update-fuse-lite-to-support-ioctls.patch
5 ntfs3g-2014.2.15-fix-fstrim-applied-to-partitons.patch
6 ntfs3g-2014.2.15-implement-fstrim.patch
7 Log:
8 Revision bump, add upstream patches to support fstrim. Make sure everything is in /usr/{s,}bin rather than making some symlinks in /{s,}bin. Set LD to make sure to use the bfd linker, even when the system linker is set to gold (bug #450024)
9
10 (Portage version: 2.2.15/cvs/Linux x86_64, signed Manifest commit with key 0xE3F69979BB4B8928DA78E3D17CBF44EF)
11
12 Revision Changes Path
13 1.1 sys-fs/ntfs3g/files/ntfs3g-2014.2.15-dont-put-things-in-root.patch
14
15 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-fs/ntfs3g/files/ntfs3g-2014.2.15-dont-put-things-in-root.patch?rev=1.1&view=markup
16 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-fs/ntfs3g/files/ntfs3g-2014.2.15-dont-put-things-in-root.patch?rev=1.1&content-type=text/plain
17
18 Index: ntfs3g-2014.2.15-dont-put-things-in-root.patch
19 ===================================================================
20 diff -ur ntfs-3g_ntfsprogs-2014.2.15.orig/ntfsprogs/Makefile.am ntfs-3g_ntfsprogs-2014.2.15/ntfsprogs/Makefile.am
21 --- ntfs-3g_ntfsprogs-2014.2.15.orig/ntfsprogs/Makefile.am 2015-01-29 00:12:51.786936314 -0800
22 +++ ntfs-3g_ntfsprogs-2014.2.15/ntfsprogs/Makefile.am 2015-01-29 00:13:59.156442369 -0800
23 @@ -140,8 +140,7 @@
24 # mkfs.ntfs[.8] hard link
25
26 install-exec-hook:
27 - $(INSTALL) -d $(DESTDIR)/sbin
28 - $(LN_S) -f $(sbindir)/mkntfs $(DESTDIR)/sbin/mkfs.ntfs
29 + $(LN_S) -f mkntfs $(DESTDIR)/$(sbindir)/mkfs.ntfs
30
31 install-data-hook:
32 $(INSTALL) -d $(DESTDIR)$(man8dir)
33 diff -ur ntfs-3g_ntfsprogs-2014.2.15.orig/src/Makefile.am ntfs-3g_ntfsprogs-2014.2.15/src/Makefile.am
34 --- ntfs-3g_ntfsprogs-2014.2.15.orig/src/Makefile.am 2015-01-29 00:12:51.789936248 -0800
35 +++ ntfs-3g_ntfsprogs-2014.2.15/src/Makefile.am 2015-01-29 00:14:00.570411008 -0800
36 @@ -68,9 +68,8 @@
37
38 if ENABLE_MOUNT_HELPER
39 install-exec-local: install-rootbinPROGRAMS
40 - $(MKDIR_P) "$(DESTDIR)/sbin"
41 - $(LN_S) -f "$(rootbindir)/ntfs-3g" "$(DESTDIR)/sbin/mount.ntfs-3g"
42 - $(LN_S) -f "$(rootbindir)/lowntfs-3g" "$(DESTDIR)/sbin/mount.lowntfs-3g"
43 + $(LN_S) -f "../bin/ntfs-3g" "$(DESTDIR)/$(sbindir)/mount.ntfs-3g"
44 + $(LN_S) -f "../bin/lowntfs-3g" "$(DESTDIR)/$(sbindir)/mount.lowntfs-3g"
45 endif
46
47 install-data-local: install-man8
48 @@ -80,7 +79,7 @@
49 uninstall-local:
50 $(RM) -f "$(DESTDIR)$(man8dir)/mount.ntfs-3g.8"
51 if ENABLE_MOUNT_HELPER
52 - $(RM) -f "$(DESTDIR)/sbin/mount.ntfs-3g" "$(DESTDIR)/sbin/mount.lowntfs-3g"
53 + $(RM) -f "$(DESTDIR)/$(sbindir)/mount.ntfs-3g" "$(DESTDIR)/$(sbindir)/mount.lowntfs-3g"
54 endif
55
56 endif # ENABLE_NTFS_3G
57
58
59
60 1.1 sys-fs/ntfs3g/files/ntfs3g-2014.2.15-update-fuse-lite-to-support-ioctls.patch
61
62 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-fs/ntfs3g/files/ntfs3g-2014.2.15-update-fuse-lite-to-support-ioctls.patch?rev=1.1&view=markup
63 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-fs/ntfs3g/files/ntfs3g-2014.2.15-update-fuse-lite-to-support-ioctls.patch?rev=1.1&content-type=text/plain
64
65 Index: ntfs3g-2014.2.15-update-fuse-lite-to-support-ioctls.patch
66 ===================================================================
67 diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_common.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_common.h
68 --- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_common.h 2014-02-15 14:07:52.000000000 +0000
69 +++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_common.h 2014-07-31 13:47:17.401904166 +0100
70 @@ -49,6 +49,22 @@
71 #endif
72
73 #define FUSE_CAP_BIG_WRITES (1 << 5)
74 +#define FUSE_CAP_IOCTL_DIR (1 << 11)
75 +
76 +/**
77 + * Ioctl flags
78 + *
79 + * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine
80 + * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed
81 + * FUSE_IOCTL_RETRY: retry with new iovecs
82 + * FUSE_IOCTL_DIR: is a directory
83 + */
84 +#define FUSE_IOCTL_COMPAT (1 << 0)
85 +#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
86 +#define FUSE_IOCTL_RETRY (1 << 2)
87 +#define FUSE_IOCTL_DIR (1 << 4)
88 +
89 +#define FUSE_IOCTL_MAX_IOV 256
90
91 /**
92 * Information about open files
93 diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse.h
94 --- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse.h 2014-02-15 14:07:52.000000000 +0000
95 +++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse.h 2014-07-31 13:47:17.401904166 +0100
96 @@ -420,9 +420,27 @@
97 * Introduced in version 2.6
98 */
99 int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
100 - unsigned int flag_nullpath_ok : 1;
101
102 /**
103 + * Ioctl
104 + *
105 + * flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in
106 + * 64bit environment. The size and direction of data is
107 + * determined by _IOC_*() decoding of cmd. For _IOC_NONE,
108 + * data will be NULL, for _IOC_WRITE data is out area, for
109 + * _IOC_READ in area and if both are set in/out area. In all
110 + * non-NULL cases, the area is of _IOC_SIZE(cmd) bytes.
111 + *
112 + * Introduced in version 2.8
113 + */
114 + int (*ioctl) (const char *, int cmd, void *arg,
115 + struct fuse_file_info *, unsigned int flags, void *data);
116 +
117 + /*
118 + * The flags below have been discarded, they should not be used
119 + */
120 + unsigned int flag_nullpath_ok : 1;
121 + /**
122 * Reserved flags, don't set
123 */
124 unsigned int flag_reserved : 30;
125 @@ -450,10 +468,8 @@
126 /** Private filesystem data */
127 void *private_data;
128
129 -#ifdef POSIXACLS
130 /** Umask of the calling process (introduced in version 2.8) */
131 mode_t umask;
132 -#endif
133 };
134
135 /* ----------------------------------------------------------- *
136 @@ -601,6 +617,8 @@
137 const char *name);
138 int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
139 uint64_t *idx);
140 +int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
141 + struct fuse_file_info *fi, unsigned int flags, void *data);
142 void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn);
143 void fuse_fs_destroy(struct fuse_fs *fs);
144
145 diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_kernel.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_kernel.h
146 --- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_kernel.h 2014-02-15 14:07:52.000000000 +0000
147 +++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_kernel.h 2014-07-31 13:47:17.401904166 +0100
148 @@ -48,13 +48,19 @@
149 /** Version number of this interface */
150 #define FUSE_KERNEL_VERSION 7
151
152 -/** Minor version number of this interface */
153 -#ifdef POSIXACLS
154 -#define FUSE_KERNEL_MINOR_VERSION 12
155 +/** Minor version number of this interface
156 + * We introduce ourself as 7.18 (Posix ACLS : 7.12, IOCTL_DIR : 7.18)
157 + * and we expect features features defined for 7.18, but not implemented
158 + * here to not be triggered by ntfs-3g.
159 + */
160 +#define FUSE_KERNEL_MINOR_VERSION 18
161 +
162 +/*
163 + * For binary compatibility with old kernels we accept falling back to 7.8
164 + */
165 +
166 +#define FUSE_KERNEL_MAJOR_FALLBACK 7
167 #define FUSE_KERNEL_MINOR_FALLBACK 8
168 -#else
169 -#define FUSE_KERNEL_MINOR_VERSION 8
170 -#endif
171
172 /** The node ID of the root inode */
173 #define FUSE_ROOT_ID 1
174 @@ -83,9 +89,7 @@
175 __u32 uid;
176 __u32 gid;
177 __u32 rdev;
178 -#ifdef POSIXACLS
179 __u64 filling; /* JPA needed for minor >= 12, but meaning unknown */
180 -#endif
181 };
182
183 struct fuse_kstatfs {
184 @@ -132,11 +136,13 @@
185 * INIT request/reply flags
186 * FUSE_BIG_WRITES: allow big writes to be issued to the file system
187 * FUSE_DONT_MASK: don't apply umask to file mode on create operations
188 + * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories
189 */
190 #define FUSE_ASYNC_READ (1 << 0)
191 #define FUSE_POSIX_LOCKS (1 << 1)
192 #define FUSE_BIG_WRITES (1 << 5)
193 #define FUSE_DONT_MASK (1 << 6)
194 +#define FUSE_HAS_IOCTL_DIR (1 << 11)
195
196 /**
197 * Release flags
198 @@ -180,6 +186,7 @@
199 FUSE_INTERRUPT = 36,
200 FUSE_BMAP = 37,
201 FUSE_DESTROY = 38,
202 + FUSE_IOCTL = 39,
203 };
204
205 /* The read buffer is required to be at least 8k, but may be much larger */
206 @@ -215,10 +222,8 @@
207 struct fuse_mknod_in {
208 __u32 mode;
209 __u32 rdev;
210 -#ifdef POSIXACLS
211 __u32 umask;
212 __u32 padding;
213 -#endif
214 };
215
216 struct fuse_mkdir_in {
217 @@ -255,20 +260,14 @@
218
219 struct fuse_open_in {
220 __u32 flags;
221 -#ifdef POSIXACLS
222 - __u32 unused;
223 -#else
224 - __u32 mode;
225 -#endif
226 + __u32 mode; /* unused for protocol < 7.12 */
227 };
228
229 struct fuse_create_in {
230 __u32 flags;
231 __u32 mode;
232 -#ifdef POSIXACLS
233 __u32 umask;
234 __u32 padding;
235 -#endif
236 };
237
238 struct fuse_open_out {
239 @@ -305,11 +304,9 @@
240 __u64 offset;
241 __u32 size;
242 __u32 write_flags;
243 -#ifdef POSIXACLS
244 __u64 lock_owner; /* JPA */
245 __u32 flags; /* JPA */
246 __u32 padding; /* JPA */
247 -#endif
248 };
249
250 struct fuse_write_out {
251 @@ -389,6 +386,27 @@
252 __u64 block;
253 };
254
255 +struct fuse_ioctl_in {
256 + __u64 fh;
257 + __u32 flags;
258 + __u32 cmd;
259 + __u64 arg;
260 + __u32 in_size;
261 + __u32 out_size;
262 +};
263 +
264 +struct fuse_ioctl_iovec {
265 + __u64 base;
266 + __u64 len;
267 +};
268 +
269 +struct fuse_ioctl_out {
270 + __s32 result;
271 + __u32 flags;
272 + __u32 in_iovs;
273 + __u32 out_iovs;
274 +};
275 +
276 struct fuse_in_header {
277 __u32 len;
278 __u32 opcode;
279 diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_lowlevel.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_lowlevel.h
280 --- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_lowlevel.h 2014-02-15 14:07:52.000000000 +0000
281 +++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_lowlevel.h 2014-07-31 13:47:17.402904167 +0100
282 @@ -101,10 +101,8 @@
283 /** Thread ID of the calling process */
284 pid_t pid;
285
286 -#ifdef POSIXACLS
287 /** Umask of the calling process (introduced in version 2.8) */
288 mode_t umask;
289 -#endif
290 };
291
292 /* 'to_set' flags in setattr */
293 @@ -805,6 +803,37 @@
294 */
295 void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize,
296 uint64_t idx);
297 + /**
298 + * Ioctl
299 + *
300 + * Note: For unrestricted ioctls (not allowed for FUSE
301 + * servers), data in and out areas can be discovered by giving
302 + * iovs and setting FUSE_IOCTL_RETRY in @flags. For
303 + * restricted ioctls, kernel prepares in/out data area
304 + * according to the information encoded in cmd.
305 + *
306 + * Introduced in version 2.8
307 + *
308 + * Valid replies:
309 + * fuse_reply_ioctl_retry
310 + * fuse_reply_ioctl
311 + * fuse_reply_ioctl_iov
312 + * fuse_reply_err
313 + *
314 + * @param req request handle
315 + * @param ino the inode number
316 + * @param cmd ioctl command
317 + * @param arg ioctl argument
318 + * @param fi file information
319 + * @param flags for FUSE_IOCTL_* flags
320 + * @param in_buf data fetched from the caller
321 + * @param in_bufsz number of fetched bytes
322 + * @param out_bufsz maximum size of output data
323 + */
324 + void (*ioctl) (fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
325 + struct fuse_file_info *fi, unsigned flags,
326 + const void *in_buf, size_t in_bufsz, size_t out_bufsz);
327 +
328 };
329
330 /**
331 @@ -1022,6 +1051,20 @@
332 const char *name, const struct stat *stbuf,
333 off_t off);
334
335 +/**
336 + * Reply to finish ioctl
337 + *
338 + * Possible requests:
339 + * ioctl
340 + *
341 + * @param req request handle
342 + * @param result result to be passed to the caller
343 + * @param buf buffer containing output data
344 + * @param size length of output data
345 + */
346 +int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size);
347 +
348 +
349 /* ----------------------------------------------------------- *
350 * Utility functions *
351 * ----------------------------------------------------------- */
352 diff -ur ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse.c ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse.c
353 --- ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse.c 2014-02-15 14:07:52.000000000 +0000
354 +++ ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse.c 2014-07-31 13:47:17.403904167 +0100
355 @@ -1040,6 +1040,21 @@
356 return -ENOSYS;
357 }
358
359 +int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
360 + struct fuse_file_info *fi, unsigned int flags, void *data)
361 +{
362 + fuse_get_context()->private_data = fs->user_data;
363 + if (fs->op.ioctl) {
364 +/*
365 + if (fs->debug)
366 + fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
367 + (unsigned long long) fi->fh, cmd, flags);
368 +*/
369 + return fs->op.ioctl(path, cmd, arg, fi, flags, data);
370 + } else
371 + return -ENOSYS;
372 +}
373 +
374 static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
375 {
376 struct node *node;
377 @@ -2716,6 +2731,60 @@
378 reply_err(req, err);
379 }
380
381 +static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
382 + struct fuse_file_info *llfi, unsigned int flags,
383 + const void *in_buf, size_t in_bufsz,
384 + size_t out_bufsz)
385 +{
386 + struct fuse *f = req_fuse_prepare(req);
387 + struct fuse_intr_data d;
388 + struct fuse_file_info fi;
389 + char *path, *out_buf = NULL;
390 + int err;
391 +
392 + err = -EPERM;
393 + if (flags & FUSE_IOCTL_UNRESTRICTED)
394 + goto err;
395 +
396 + if (flags & FUSE_IOCTL_DIR)
397 + get_dirhandle(llfi, &fi);
398 + else
399 + fi = *llfi;
400 +
401 + if (out_bufsz) {
402 + err = -ENOMEM;
403 + out_buf = malloc(out_bufsz);
404 + if (!out_buf)
405 + goto err;
406 + }
407 +
408 + assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
409 + if (out_buf)
410 + memcpy(out_buf, in_buf, in_bufsz);
411 +
412 + path = get_path(f, ino); /* Should be get_path_nullok() */
413 + if (!path) {
414 + err = ENOENT;
415 + goto err;
416 + }
417 +
418 + fuse_prepare_interrupt(f, req, &d);
419 +
420 + /* Note : const qualifier dropped */
421 + err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags,
422 + out_buf ? (void*)out_buf : (void*)(uintptr_t)in_buf);
423 +
424 + fuse_finish_interrupt(f, req, &d);
425 + free(path);
426 +
427 + fuse_reply_ioctl(req, err, out_buf, out_bufsz);
428 + goto out;
429 +err:
430 + reply_err(req, err);
431 +out:
432 + free(out_buf);
433 +}
434 +
435 static struct fuse_lowlevel_ops fuse_path_ops = {
436 .init = fuse_lib_init,
437 .destroy = fuse_lib_destroy,
438 @@ -2751,6 +2820,7 @@
439 .getlk = fuse_lib_getlk,
440 .setlk = fuse_lib_setlk,
441 .bmap = fuse_lib_bmap,
442 + .ioctl = fuse_lib_ioctl,
443 };
444
445 struct fuse_session *fuse_get_session(struct fuse *f)
446 diff -ur ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse_lowlevel.c ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse_lowlevel.c
447 --- ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse_lowlevel.c 2014-02-15 14:07:52.000000000 +0000
448 +++ ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse_lowlevel.c 2014-07-31 13:47:17.403904167 +0100
449 @@ -333,12 +333,8 @@
450
451 memset(&arg, 0, sizeof(arg));
452 fill_entry(&arg, e);
453 -#ifdef POSIXACLS
454 return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12
455 ? sizeof(arg) : FUSE_COMPAT_ENTRY_OUT_SIZE));
456 -#else
457 - return send_reply_ok(req, &arg, sizeof(arg));
458 -#endif
459 }
460
461 int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
462 @@ -351,7 +347,6 @@
463
464 memset(&arg, 0, sizeof(arg));
465 fill_entry(&arg.e, e);
466 -#ifdef POSIXACLS
467 if (req->f->conn.proto_minor < 12) {
468 fill_open((struct fuse_open_out*)
469 ((char*)&arg + FUSE_COMPAT_ENTRY_OUT_SIZE), f);
470 @@ -361,10 +356,6 @@
471 fill_open(&arg.o, f);
472 return send_reply_ok(req, &arg, sizeof(arg));
473 }
474 -#else
475 - fill_open(&arg.o, f);
476 - return send_reply_ok(req, &arg, sizeof(arg));
477 -#endif
478 }
479
480 int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
481 @@ -377,12 +368,8 @@
482 arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
483 convert_stat(attr, &arg.attr);
484
485 -#ifdef POSIXACLS
486 return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12
487 ? sizeof(arg) : FUSE_COMPAT_FUSE_ATTR_OUT_SIZE));
488 -#else
489 - return send_reply_ok(req, &arg, sizeof(arg));
490 -#endif
491 }
492
493 int fuse_reply_readlink(fuse_req_t req, const char *linkname)
494 @@ -462,6 +449,28 @@
495 return send_reply_ok(req, &arg, sizeof(arg));
496 }
497
498 +int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
499 +{
500 + struct fuse_ioctl_out arg;
501 + struct iovec iov[3];
502 + size_t count = 1;
503 +
504 + memset(&arg, 0, sizeof(arg));
505 + arg.result = result;
506 + iov[count].iov_base = &arg;
507 + iov[count].iov_len = sizeof(arg);
508 + count++;
509 +
510 + if (size) {
511 + /* Note : const qualifier dropped */
512 + iov[count].iov_base = (char *)(uintptr_t) buf;
513 + iov[count].iov_len = size;
514 + count++;
515 + }
516 +
517 + return send_reply_iov(req, 0, iov, count);
518 +}
519 +
520 static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
521 {
522 const char *name = (const char *) inarg;
523 @@ -538,11 +547,9 @@
524 const struct fuse_mknod_in *arg = (const struct fuse_mknod_in *) inarg;
525 const char *name = PARAM(arg);
526
527 -#ifdef POSIXACLS
528 if (req->f->conn.proto_minor >= 12)
529 req->ctx.umask = arg->umask;
530 else
531 -#endif
532 name = (const char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE;
533
534 if (req->f->op.mknod)
535 @@ -555,10 +562,8 @@
536 {
537 const struct fuse_mkdir_in *arg = (const struct fuse_mkdir_in *) inarg;
538
539 -#ifdef POSIXACLS
540 if (req->f->conn.proto_minor >= 12)
541 req->ctx.umask = arg->umask;
542 -#endif
543
544 if (req->f->op.mkdir)
545 req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
546 @@ -630,11 +635,9 @@
547 memset(&fi, 0, sizeof(fi));
548 fi.flags = arg->flags;
549
550 -#ifdef POSIXACLS
551 if (req->f->conn.proto_minor >= 12)
552 req->ctx.umask = arg->umask;
553 else
554 -#endif
555 name = (const char *) inarg + sizeof(struct fuse_open_in);
556
557 req->f->op.create(req, nodeid, name, arg->mode, &fi);
558 @@ -682,7 +685,6 @@
559 fi.writepage = arg->write_flags & 1;
560
561 if (req->f->op.write) {
562 -#ifdef POSIXACLS
563 const char *buf;
564
565 if (req->f->conn.proto_minor >= 12)
566 @@ -690,9 +692,6 @@
567 else
568 buf = ((const char*)arg) + FUSE_COMPAT_WRITE_IN_SIZE;
569 req->f->op.write(req, nodeid, buf, arg->size, arg->offset, &fi);
570 -#else
571 - req->f->op.write(req, nodeid, PARAM(arg), arg->size, arg->offset, &fi);
572 -#endif
573 } else
574 fuse_reply_err(req, ENOSYS);
575 }
576 @@ -1011,6 +1010,39 @@
577 fuse_reply_err(req, ENOSYS);
578 }
579
580 +static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
581 +{
582 + const struct fuse_ioctl_in *arg = (const struct fuse_ioctl_in *) inarg;
583 + unsigned int flags = arg->flags;
584 + const void *in_buf = arg->in_size ? PARAM(arg) : NULL;
585 + struct fuse_file_info fi;
586 +
587 + if (flags & FUSE_IOCTL_DIR &&
588 + !(req->f->conn.want & FUSE_CAP_IOCTL_DIR)) {
589 + fuse_reply_err(req, ENOTTY);
590 + return;
591 + }
592 +
593 + memset(&fi, 0, sizeof(fi));
594 + fi.fh = arg->fh;
595 +
596 +/* TODO JPA (need req->ioctl_64bit in obscure fuse_req_t)
597 +// probably a 64 bit ioctl on a 32-bit cpu
598 +// this is to forward a request from the kernel
599 + if (sizeof(void *) == 4 && req->f->conn.proto_minor >= 16 &&
600 + !(flags & FUSE_IOCTL_32BIT)) {
601 + req->ioctl_64bit = 1;
602 + }
603 +*/
604 +
605 + if (req->f->op.ioctl)
606 + req->f->op.ioctl(req, nodeid, arg->cmd,
607 + (void *)(uintptr_t)arg->arg, &fi, flags,
608 + in_buf, arg->in_size, arg->out_size);
609 + else
610 + fuse_reply_err(req, ENOSYS);
611 +}
612 +
613 static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
614 {
615 const struct fuse_init_in *arg = (const struct fuse_init_in *) inarg;
616 @@ -1047,6 +1079,8 @@
617 #endif
618 if (arg->flags & FUSE_BIG_WRITES)
619 f->conn.capable |= FUSE_CAP_BIG_WRITES;
620 + if (arg->flags & FUSE_HAS_IOCTL_DIR)
621 + f->conn.capable |= FUSE_CAP_IOCTL_DIR;
622 } else {
623 f->conn.async_read = 0;
624 f->conn.max_readahead = 0;
625 @@ -1069,28 +1103,28 @@
626 memset(&outarg, 0, sizeof(outarg));
627 outarg.major = FUSE_KERNEL_VERSION;
628 /*
629 - * if POSIXACLS is not set, protocol 7.8 provides a good
630 - * compatibility with older kernel modules.
631 - * if POSIXACLS is set, we try to use protocol 7.12 supposed
632 - * to have the ability to process the umask conditionnally,
633 - * but, when using an older kernel module, we fallback to 7.8
634 + * Suggest using protocol 7.18 when available, and fallback
635 + * to 7.8 when running on an old kernel.
636 + * Protocol 7.12 has the ability to process the umask
637 + * conditionnally (as needed if POSIXACLS is set)
638 + * Protocol 7.18 has the ability to process the ioctls
639 */
640 -#ifdef POSIXACLS
641 - if (arg->major > 7 || (arg->major == 7 && arg->minor >= 12))
642 + if (arg->major > 7 || (arg->major == 7 && arg->minor >= 18)) {
643 outarg.minor = FUSE_KERNEL_MINOR_VERSION;
644 - else
645 - outarg.minor = FUSE_KERNEL_MINOR_FALLBACK;
646 -#else
647 - outarg.minor = FUSE_KERNEL_MINOR_VERSION;
648 + if (f->conn.want & FUSE_CAP_IOCTL_DIR)
649 + outarg.flags |= FUSE_HAS_IOCTL_DIR;
650 +#ifdef POSIXACLS
651 + if (f->conn.want & FUSE_CAP_DONT_MASK)
652 + outarg.flags |= FUSE_DONT_MASK;
653 #endif
654 + } else {
655 + outarg.major = FUSE_KERNEL_MAJOR_FALLBACK;
656 + outarg.minor = FUSE_KERNEL_MINOR_FALLBACK;
657 + }
658 if (f->conn.async_read)
659 outarg.flags |= FUSE_ASYNC_READ;
660 if (f->op.getlk && f->op.setlk)
661 outarg.flags |= FUSE_POSIX_LOCKS;
662 -#ifdef POSIXACLS
663 - if (f->conn.want & FUSE_CAP_DONT_MASK)
664 - outarg.flags |= FUSE_DONT_MASK;
665 -#endif
666 if (f->conn.want & FUSE_CAP_BIG_WRITES)
667 outarg.flags |= FUSE_BIG_WRITES;
668 outarg.max_readahead = f->conn.max_readahead;
669 @@ -1191,6 +1225,7 @@
670 [FUSE_CREATE] = { do_create, "CREATE" },
671 [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" },
672 [FUSE_BMAP] = { do_bmap, "BMAP" },
673 + [FUSE_IOCTL] = { do_ioctl, "IOCTL" },
674 [FUSE_DESTROY] = { do_destroy, "DESTROY" },
675 };
676
677
678
679
680 1.1 sys-fs/ntfs3g/files/ntfs3g-2014.2.15-fix-fstrim-applied-to-partitons.patch
681
682 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-fs/ntfs3g/files/ntfs3g-2014.2.15-fix-fstrim-applied-to-partitons.patch?rev=1.1&view=markup
683 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-fs/ntfs3g/files/ntfs3g-2014.2.15-fix-fstrim-applied-to-partitons.patch?rev=1.1&content-type=text/plain
684
685 Index: ntfs3g-2014.2.15-fix-fstrim-applied-to-partitons.patch
686 ===================================================================
687 From c26a519da1ed182e7cfd67e7a353932dda53d811 Mon Sep 17 00:00:00 2001
688 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= <jpandre@×××××××××××××××××.net>
689 Date: Mon, 4 Aug 2014 17:39:50 +0200
690 Subject: [PATCH] Fixed fstrim(8) applied to partitions
691
692 The new way goes via /sys/dev/block/MAJOR:MINOR to map partitions to
693 devices and get discard parameters of the parent device. It also ensures
694 that the partition is aligned to the discard block size.
695
696 Contributed by Richard W.M. Jones
697 ---
698 libntfs-3g/ioctl.c | 140 ++++++++++++++++++++++++++---------------------------
699 1 file changed, 68 insertions(+), 72 deletions(-)
700
701 diff --git a/libntfs-3g/ioctl.c b/libntfs-3g/ioctl.c
702 index bbbceb9..eb7c8e7 100644
703 --- a/libntfs-3g/ioctl.c
704 +++ b/libntfs-3g/ioctl.c
705 @@ -66,8 +66,6 @@
706 #include <linux/fs.h>
707 #endif
708
709 -#include <dirent.h>
710 -
711 #include "compat.h"
712 #include "debug.h"
713 #include "bitmap.h"
714 @@ -135,17 +133,14 @@ static int read_u64(const char *path, u64 *n)
715 }
716
717 /* Find discard limits for current backing device.
718 - * XXX Kernel makes this a pain in the neck.
719 */
720 -static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity,
721 +static int fstrim_limits(ntfs_volume *vol,
722 + u64 *discard_alignment,
723 + u64 *discard_granularity,
724 u64 *discard_max_bytes)
725 {
726 struct stat statbuf;
727 - DIR *dir;
728 - struct dirent *d;
729 - char path[80];
730 - char line[64];
731 - char dev[64];
732 + char path1[80], path2[80];
733 int ret;
734
735 /* Stat the backing device. Caller has ensured it is a block device. */
736 @@ -155,82 +150,78 @@ static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity,
737 return -errno;
738 }
739
740 - /* Now look for a /sys/block/<dev>/dev file which contains
741 - * "major:minor\n".
742 + /* For whole devices,
743 + * /sys/dev/block/MAJOR:MINOR/discard_alignment
744 + * /sys/dev/block/MAJOR:MINOR/queue/discard_granularity
745 + * /sys/dev/block/MAJOR:MINOR/queue/discard_max_bytes
746 + * will exist.
747 + * For partitions, we also need to check the parent device:
748 + * /sys/dev/block/MAJOR:MINOR/../queue/discard_granularity
749 + * /sys/dev/block/MAJOR:MINOR/../queue/discard_max_bytes
750 */
751 - snprintf(dev, sizeof dev, "%d:%d\n",
752 + snprintf(path1, sizeof path1, "/sys/dev/block/%d:%d",
753 major(statbuf.st_rdev), minor(statbuf.st_rdev));
754
755 - dir = opendir("/sys/block");
756 - if (dir == NULL) {
757 - ntfs_log_debug("fstrim_limits: could not open /sys/block\n");
758 - return -errno;
759 + snprintf(path2, sizeof path2, "%s/discard_alignment", path1);
760 + ret = read_u64(path2, discard_alignment);
761 + if (ret) {
762 + if (ret != -ENOENT)
763 + return ret;
764 + else
765 + /* We would expect this file to exist on all
766 + * modern kernels. But for the sake of very
767 + * old kernels:
768 + */
769 + goto not_found;
770 }
771 - for (;;) {
772 - errno = 0;
773 - d = readdir(dir);
774 - if (!d) break;
775
776 - snprintf(path, sizeof path, "/sys/block/%s/dev", d->d_name);
777 - ret = read_line(path, line, sizeof line);
778 - if (ret)
779 - continue;
780 - if (strcmp(line, dev) == 0)
781 - goto found;
782 + snprintf(path2, sizeof path2, "%s/queue/discard_granularity", path1);
783 + ret = read_u64(path2, discard_granularity);
784 + if (ret) {
785 + if (ret != -ENOENT)
786 + return ret;
787 + else {
788 + snprintf(path2, sizeof path2,
789 + "%s/../queue/discard_granularity", path1);
790 + ret = read_u64(path2, discard_granularity);
791 + if (ret) {
792 + if (ret != -ENOENT)
793 + return ret;
794 + else
795 + goto not_found;
796 + }
797 + }
798 }
799
800 - /* Check readdir didn't fail. */
801 - if (errno != 0) {
802 - ret = -errno;
803 - ntfs_log_debug("fstrim_limits: readdir failed\n");
804 - goto out;
805 + snprintf(path2, sizeof path2, "%s/queue/discard_max_bytes", path1);
806 + ret = read_u64(path2, discard_max_bytes);
807 + if (ret) {
808 + if (ret != -ENOENT)
809 + return ret;
810 + else {
811 + snprintf(path2, sizeof path2,
812 + "%s/../queue/discard_max_bytes", path1);
813 + ret = read_u64(path2, discard_max_bytes);
814 + if (ret) {
815 + if (ret != -ENOENT)
816 + return ret;
817 + else
818 + goto not_found;
819 + }
820 + }
821 }
822
823 + return 0;
824 +
825 +not_found:
826 /* If we reach here then we didn't find the device. This is
827 * not an error, but set discard_max_bytes = 0 to indicate
828 * that discard is not available.
829 */
830 + *discard_alignment = 0;
831 *discard_granularity = 0;
832 *discard_max_bytes = 0;
833 - ntfs_log_debug("fstrim_limits: /sys/block entry corresponding to device %s not found\n",
834 - vol->dev->d_name);
835 - ret = 0;
836 - goto out;
837 -
838 -found:
839 - /* Found the device at /sys/block/ + d->d_name */
840 - snprintf (path, sizeof path,
841 - "/sys/block/%s/queue/discard_granularity",
842 - d->d_name);
843 - ret = read_u64(path, discard_granularity);
844 - if (ret) {
845 - ntfs_log_debug("fstrim_limits: could not read %s\n", path);
846 - goto out;
847 - }
848 -
849 - snprintf (path, sizeof path,
850 - "/sys/block/%s/queue/discard_max_bytes",
851 - d->d_name);
852 - ret = read_u64(path, discard_max_bytes);
853 - if (ret) {
854 - ntfs_log_debug("fstrim_limits: could not read %s\n", path);
855 - goto out;
856 - }
857 -
858 - ntfs_log_debug("fstrim_limits: device %s discard granularity = %llu max_bytes = %llu\n",
859 - d->d_name,
860 - (unsigned long long) *discard_granularity,
861 - (unsigned long long) *discard_max_bytes);
862 -
863 - ret = 0;
864 -out:
865 - if (closedir (dir) == -1) {
866 - ret = -errno;
867 - ntfs_log_debug("fstrim_limits: closedir failed\n");
868 - return ret;
869 - }
870 -
871 - return ret;
872 + return 0;
873 }
874
875 #define FSTRIM_BUFSIZ 4096
876 @@ -247,7 +238,7 @@ static int fstrim(ntfs_volume *vol, void *data)
877 u64 start = range->start;
878 u64 len = range->len;
879 u64 minlen = range->minlen;
880 - u64 discard_granularity, discard_max_bytes;
881 + u64 discard_alignment, discard_granularity, discard_max_bytes;
882 u8 *buf = NULL;
883 LCN start_buf;
884 int ret;
885 @@ -279,9 +270,14 @@ static int fstrim(ntfs_volume *vol, void *data)
886 return -EOPNOTSUPP;
887 }
888
889 - ret = fstrim_limits(vol, &discard_granularity, &discard_max_bytes);
890 + ret = fstrim_limits(vol, &discard_alignment,
891 + &discard_granularity, &discard_max_bytes);
892 if (ret)
893 return ret;
894 + if (discard_alignment != 0) {
895 + ntfs_log_debug("fstrim: backing device is not aligned for discards\n");
896 + return -EOPNOTSUPP;
897 + }
898 if (discard_granularity > vol->cluster_size) {
899 ntfs_log_debug("fstrim: discard granularity of backing device is larger than cluster size\n");
900 return -EOPNOTSUPP;
901 --
902 1.9.3
903
904
905
906
907 1.1 sys-fs/ntfs3g/files/ntfs3g-2014.2.15-implement-fstrim.patch
908
909 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-fs/ntfs3g/files/ntfs3g-2014.2.15-implement-fstrim.patch?rev=1.1&view=markup
910 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-fs/ntfs3g/files/ntfs3g-2014.2.15-implement-fstrim.patch?rev=1.1&content-type=text/plain
911
912 Index: ntfs3g-2014.2.15-implement-fstrim.patch
913 ===================================================================
914 diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/configure.ac ntfs-3g_ntfsprogs-2014.2.15/configure.ac
915 --- ntfs-3g_ntfsprogs-2014.2.15.old/configure.ac 2014-02-15 14:07:52.000000000 +0000
916 +++ ntfs-3g_ntfsprogs-2014.2.15/configure.ac 2014-07-31 13:51:24.425065808 +0100
917 @@ -463,7 +463,8 @@
918 regex.h endian.h byteswap.h sys/byteorder.h sys/disk.h sys/endian.h \
919 sys/param.h sys/ioctl.h sys/mkdev.h sys/mount.h sys/stat.h sys/types.h \
920 sys/vfs.h sys/statvfs.h sys/sysmacros.h linux/major.h linux/fd.h \
921 - linux/hdreg.h machine/endian.h windows.h syslog.h pwd.h malloc.h])
922 + linux/fs.h inttypes.h linux/hdreg.h \
923 + machine/endian.h windows.h syslog.h pwd.h malloc.h])
924
925 # Checks for typedefs, structures, and compiler characteristics.
926 AC_HEADER_STDBOOL
927 diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/ioctl.h ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/ioctl.h
928 --- ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/ioctl.h 1970-01-01 01:00:00.000000000 +0100
929 +++ ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/ioctl.h 2014-07-31 13:51:24.426065810 +0100
930 @@ -0,0 +1,30 @@
931 +/*
932 + *
933 + * Copyright (c) 2014 Jean-Pierre Andre
934 + *
935 + */
936 +
937 +/*
938 + * This program is free software; you can redistribute it and/or modify
939 + * it under the terms of the GNU General Public License as published by
940 + * the Free Software Foundation; either version 2 of the License, or
941 + * (at your option) any later version.
942 + *
943 + * This program is distributed in the hope that it will be useful,
944 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
945 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
946 + * GNU General Public License for more details.
947 + *
948 + * You should have received a copy of the GNU General Public License
949 + * along with this program (in the main directory of the NTFS-3G
950 + * distribution in the file COPYING); if not, write to the Free Software
951 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
952 + */
953 +
954 +#ifndef IOCTL_H
955 +#define IOCTL_H
956 +
957 +int ntfs_ioctl(ntfs_inode *ni, int cmd, void *arg,
958 + unsigned int flags, void *data);
959 +
960 +#endif /* IOCTL_H */
961 diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/volume.h ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/volume.h
962 --- ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/volume.h 2014-02-15 14:07:52.000000000 +0000
963 +++ ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/volume.h 2014-07-31 13:51:24.426065810 +0100
964 @@ -36,9 +36,7 @@
965 #ifdef HAVE_SYS_PARAM_H
966 #include <sys/param.h>
967 #endif
968 -#ifdef HAVE_SYS_MOUNT_H
969 -#include <sys/mount.h>
970 -#endif
971 + /* Do not #include <sys/mount.h> here : conflicts with <linux/fs.h> */
972 #ifdef HAVE_MNTENT_H
973 #include <mntent.h>
974 #endif
975 diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/ioctl.c ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/ioctl.c
976 --- ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/ioctl.c 1970-01-01 01:00:00.000000000 +0100
977 +++ ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/ioctl.c 2014-07-31 13:51:24.427065813 +0100
978 @@ -0,0 +1,382 @@
979 +/**
980 + * ioctl.c - Processing of ioctls
981 + *
982 + * This module is part of ntfs-3g library
983 + *
984 + * Copyright (c) 2014 Jean-Pierre Andre
985 + * Copyright (c) 2014 Red Hat, Inc.
986 + *
987 + * This program/include file is free software; you can redistribute it and/or
988 + * modify it under the terms of the GNU General Public License as published
989 + * by the Free Software Foundation; either version 2 of the License, or
990 + * (at your option) any later version.
991 + *
992 + * This program/include file is distributed in the hope that it will be
993 + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
994 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
995 + * GNU General Public License for more details.
996 + *
997 + * You should have received a copy of the GNU General Public License
998 + * along with this program (in the main directory of the NTFS-3G
999 + * distribution in the file COPYING); if not, write to the Free Software
1000 + * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1001 + */
1002 +
1003 +#include "config.h"
1004 +
1005 +#ifdef HAVE_STDIO_H
1006 +#include <stdio.h>
1007 +#endif
1008 +#ifdef HAVE_INTTYPES_H
1009 +#include <inttypes.h>
1010 +#endif
1011 +#ifdef HAVE_STRING_H
1012 +#include <string.h>
1013 +#endif
1014 +#ifdef HAVE_ERRNO_H
1015 +#include <errno.h>
1016 +#endif
1017 +#ifdef HAVE_FCNTL_H
1018 +#include <fcntl.h>
1019 +#endif
1020 +#ifdef HAVE_UNISTD_H
1021 +#include <unistd.h>
1022 +#endif
1023 +#ifdef HAVE_STDLIB_H
1024 +#include <stdlib.h>
1025 +#endif
1026 +#ifdef HAVE_LIMITS_H
1027 +#include <limits.h>
1028 +#endif
1029 +#include <syslog.h>
1030 +
1031 +#ifdef HAVE_SETXATTR
1032 +#include <sys/xattr.h>
1033 +#endif
1034 +
1035 +#ifdef HAVE_SYS_TYPES_H
1036 +#include <sys/types.h>
1037 +#endif
1038 +
1039 +#ifdef HAVE_SYS_STAT_H
1040 +#include <sys/stat.h>
1041 +#endif
1042 +
1043 +#ifdef HAVE_LINUX_FS_H
1044 +#include <linux/fs.h>
1045 +#endif
1046 +
1047 +#include <dirent.h>
1048 +
1049 +#include "compat.h"
1050 +#include "debug.h"
1051 +#include "bitmap.h"
1052 +#include "attrib.h"
1053 +#include "inode.h"
1054 +#include "layout.h"
1055 +#include "volume.h"
1056 +#include "index.h"
1057 +#include "logging.h"
1058 +#include "ntfstime.h"
1059 +#include "unistr.h"
1060 +#include "dir.h"
1061 +#include "security.h"
1062 +#include "ioctl.h"
1063 +#include "misc.h"
1064 +
1065 +#if defined(FITRIM) && defined(BLKDISCARD)
1066 +
1067 +/* Issue a TRIM request to the underlying device for the given clusters. */
1068 +static int fstrim_clusters(ntfs_volume *vol, LCN lcn, s64 length)
1069 +{
1070 + struct ntfs_device *dev = vol->dev;
1071 + uint64_t range[2];
1072 +
1073 + ntfs_log_debug("fstrim_clusters: %lld length %lld\n",
1074 + (long long) lcn, (long long) length);
1075 +
1076 + range[0] = lcn << vol->cluster_size_bits;
1077 + range[1] = length << vol->cluster_size_bits;
1078 +
1079 + if (dev->d_ops->ioctl(dev, BLKDISCARD, range) == -1) {
1080 + ntfs_log_debug("fstrim_one_cluster: ioctl failed: %m\n");
1081 + return -errno;
1082 + }
1083 + return 0;
1084 +}
1085 +
1086 +static int read_line(const char *path, char *line, size_t max_bytes)
1087 +{
1088 + FILE *fp;
1089 +
1090 + fp = fopen(path, "r");
1091 + if (fp == NULL)
1092 + return -errno;
1093 + if (fgets(line, max_bytes, fp) == NULL) {
1094 + int ret = -EIO; /* fgets doesn't set errno */
1095 + fclose(fp);
1096 + return ret;
1097 + }
1098 + fclose (fp);
1099 + return 0;
1100 +}
1101 +
1102 +static int read_u64(const char *path, u64 *n)
1103 +{
1104 + char line[64];
1105 + int ret;
1106 +
1107 + ret = read_line(path, line, sizeof line);
1108 + if (ret)
1109 + return ret;
1110 + if (sscanf(line, "%" SCNu64, n) != 1)
1111 + return -EINVAL;
1112 + return 0;
1113 +}
1114 +
1115 +/* Find discard limits for current backing device.
1116 + * XXX Kernel makes this a pain in the neck.
1117 + */
1118 +static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity,
1119 + u64 *discard_max_bytes)
1120 +{
1121 + struct stat statbuf;
1122 + DIR *dir;
1123 + struct dirent *d;
1124 + char path[80];
1125 + char line[64];
1126 + char dev[64];
1127 + int ret;
1128 +
1129 + /* Stat the backing device. Caller has ensured it is a block device. */
1130 + if (stat(vol->dev->d_name, &statbuf) == -1) {
1131 + ntfs_log_debug("fstrim_limits: could not stat %s\n",
1132 + vol->dev->d_name);
1133 + return -errno;
1134 + }
1135 +
1136 + /* Now look for a /sys/block/<dev>/dev file which contains
1137 + * "major:minor\n".
1138 + */
1139 + snprintf(dev, sizeof dev, "%d:%d\n",
1140 + major(statbuf.st_rdev), minor(statbuf.st_rdev));
1141 +
1142 + dir = opendir("/sys/block");
1143 + if (dir == NULL) {
1144 + ntfs_log_debug("fstrim_limits: could not open /sys/block\n");
1145 + return -errno;
1146 + }
1147 + for (;;) {
1148 + errno = 0;
1149 + d = readdir(dir);
1150 + if (!d) break;
1151 +
1152 + snprintf(path, sizeof path, "/sys/block/%s/dev", d->d_name);
1153 + ret = read_line(path, line, sizeof line);
1154 + if (ret)
1155 + continue;
1156 + if (strcmp(line, dev) == 0)
1157 + goto found;
1158 + }
1159 +
1160 + /* Check readdir didn't fail. */
1161 + if (errno != 0) {
1162 + ret = -errno;
1163 + ntfs_log_debug("fstrim_limits: readdir failed\n");
1164 + goto out;
1165 + }
1166 +
1167 + /* If we reach here then we didn't find the device. This is
1168 + * not an error, but set discard_max_bytes = 0 to indicate
1169 + * that discard is not available.
1170 + */
1171 + *discard_granularity = 0;
1172 + *discard_max_bytes = 0;
1173 + ntfs_log_debug("fstrim_limits: /sys/block entry corresponding to device %s not found\n",
1174 + vol->dev->d_name);
1175 + ret = 0;
1176 + goto out;
1177 +
1178 +found:
1179 + /* Found the device at /sys/block/ + d->d_name */
1180 + snprintf (path, sizeof path,
1181 + "/sys/block/%s/queue/discard_granularity",
1182 + d->d_name);
1183 + ret = read_u64(path, discard_granularity);
1184 + if (ret) {
1185 + ntfs_log_debug("fstrim_limits: could not read %s\n", path);
1186 + goto out;
1187 + }
1188 +
1189 + snprintf (path, sizeof path,
1190 + "/sys/block/%s/queue/discard_max_bytes",
1191 + d->d_name);
1192 + ret = read_u64(path, discard_max_bytes);
1193 + if (ret) {
1194 + ntfs_log_debug("fstrim_limits: could not read %s\n", path);
1195 + goto out;
1196 + }
1197 +
1198 + ntfs_log_debug("fstrim_limits: device %s discard granularity = %llu max_bytes = %llu\n",
1199 + d->d_name,
1200 + (unsigned long long) *discard_granularity,
1201 + (unsigned long long) *discard_max_bytes);
1202 +
1203 + ret = 0;
1204 +out:
1205 + if (closedir (dir) == -1) {
1206 + ret = -errno;
1207 + ntfs_log_debug("fstrim_limits: closedir failed\n");
1208 + return ret;
1209 + }
1210 +
1211 + return ret;
1212 +}
1213 +
1214 +#define FSTRIM_BUFSIZ 4096
1215 +
1216 +/* Trim the filesystem.
1217 + *
1218 + * Free blocks between 'start' and 'start+len-1' (both byte offsets)
1219 + * are found and TRIM requests are sent to the block device. 'minlen'
1220 + * is the minimum continguous free range to discard.
1221 + */
1222 +static int fstrim(ntfs_volume *vol, void *data)
1223 +{
1224 + struct fstrim_range *range = data;
1225 + u64 start = range->start;
1226 + u64 len = range->len;
1227 + u64 minlen = range->minlen;
1228 + u64 discard_granularity, discard_max_bytes;
1229 + u8 *buf = NULL;
1230 + LCN start_buf;
1231 + int ret;
1232 +
1233 + ntfs_log_debug("fstrim: start=%llu len=%llu minlen=%llu\n",
1234 + (unsigned long long) start,
1235 + (unsigned long long) len,
1236 + (unsigned long long) minlen);
1237 +
1238 + /* Fail if user tries to use the fstrim -o/-l/-m options.
1239 + * XXX We could fix these limitations in future.
1240 + */
1241 + if (start != 0 || len != (uint64_t)-1) {
1242 + ntfs_log_debug("fstrim: setting start or length is not supported\n");
1243 + return -EINVAL;
1244 + }
1245 + if (minlen > vol->cluster_size) {
1246 + ntfs_log_debug("fstrim: minlen > cluster size is not supported\n");
1247 + return -EINVAL;
1248 + }
1249 +
1250 + /* Only block devices are supported. It would be possible to
1251 + * support backing files (ie. without using loop) but the
1252 + * ioctls used to punch holes in files are completely
1253 + * different.
1254 + */
1255 + if (!NDevBlock(vol->dev)) {
1256 + ntfs_log_debug("fstrim: not supported for non-block-device\n");
1257 + return -EOPNOTSUPP;
1258 + }
1259 +
1260 + ret = fstrim_limits(vol, &discard_granularity, &discard_max_bytes);
1261 + if (ret)
1262 + return ret;
1263 + if (discard_granularity > vol->cluster_size) {
1264 + ntfs_log_debug("fstrim: discard granularity of backing device is larger than cluster size\n");
1265 + return -EOPNOTSUPP;
1266 + }
1267 + if (discard_max_bytes == 0) {
1268 + ntfs_log_debug("fstrim: backing device does not support discard (discard_max_bytes == 0)\n");
1269 + return -EOPNOTSUPP;
1270 + }
1271 +
1272 + /* Sync the device before doing anything. */
1273 + ret = ntfs_device_sync(vol->dev);
1274 + if (ret)
1275 + return ret;
1276 +
1277 + /* Read through the bitmap. */
1278 + buf = ntfs_malloc(FSTRIM_BUFSIZ);
1279 + if (buf == NULL)
1280 + return -errno;
1281 + for (start_buf = 0; start_buf < vol->nr_clusters;
1282 + start_buf += FSTRIM_BUFSIZ * 8) {
1283 + s64 count;
1284 + s64 br;
1285 + LCN end_buf, start_lcn;
1286 +
1287 + /* start_buf is LCN of first cluster in the current buffer.
1288 + * end_buf is LCN of last cluster + 1 in the current buffer.
1289 + */
1290 + end_buf = start_buf + FSTRIM_BUFSIZ*8;
1291 + if (end_buf > vol->nr_clusters)
1292 + end_buf = vol->nr_clusters;
1293 + count = (end_buf - start_buf) / 8;
1294 +
1295 + br = ntfs_attr_pread(vol->lcnbmp_na, start_buf/8, count, buf);
1296 + if (br != count) {
1297 + if (br >= 0)
1298 + ret = -EIO;
1299 + else
1300 + ret = -errno;
1301 + goto free_out;
1302 + }
1303 +
1304 + /* Trim the clusters in large as possible blocks, but
1305 + * not larger than discard_max_bytes.
1306 + */
1307 + for (start_lcn = start_buf; start_lcn < end_buf; ++start_lcn) {
1308 + if (!ntfs_bit_get(buf, start_lcn-start_buf)) {
1309 + LCN end_lcn;
1310 +
1311 + /* Cluster 'start_lcn' is not in use,
1312 + * find end of this run.
1313 + */
1314 + end_lcn = start_lcn+1;
1315 + while (end_lcn < end_buf &&
1316 + (u64) (end_lcn-start_lcn) << vol->cluster_size_bits
1317 + < discard_max_bytes &&
1318 + !ntfs_bit_get(buf, end_lcn-start_buf))
1319 + end_lcn++;
1320 +
1321 + ret = fstrim_clusters(vol,
1322 + start_lcn, end_lcn-start_lcn);
1323 + if (ret)
1324 + goto free_out;
1325 +
1326 + start_lcn = end_lcn-1;
1327 + }
1328 + }
1329 + }
1330 +
1331 + ret = 0;
1332 +free_out:
1333 + free(buf);
1334 + return ret;
1335 +}
1336 +
1337 +#endif /* FITRIM && BLKDISCARD */
1338 +
1339 +int ntfs_ioctl(ntfs_inode *ni, int cmd, void *arg __attribute__((unused)),
1340 + unsigned int flags __attribute__((unused)), void *data)
1341 +{
1342 + int ret = 0;
1343 +
1344 + switch (cmd) {
1345 +#if defined(FITRIM) && defined(BLKDISCARD)
1346 + case FITRIM:
1347 + if (!ni || !data)
1348 + ret = -EINVAL;
1349 + else
1350 + ret = fstrim(ni->vol, data);
1351 + break;
1352 +#else
1353 +#warning FITRIM or BLKDISCARD not defined
1354 +#endif
1355 + default :
1356 + ret = -EINVAL;
1357 + break;
1358 + }
1359 + return (ret);
1360 +}
1361 diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/Makefile.am ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/Makefile.am
1362 --- ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/Makefile.am 2014-02-15 14:07:52.000000000 +0000
1363 +++ ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/Makefile.am 2014-07-31 13:51:24.426065810 +0100
1364 @@ -30,6 +30,7 @@
1365 efs.c \
1366 index.c \
1367 inode.c \
1368 + ioctl.c \
1369 lcnalloc.c \
1370 logfile.c \
1371 logging.c \
1372 diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/src/lowntfs-3g.c ntfs-3g_ntfsprogs-2014.2.15/src/lowntfs-3g.c
1373 --- ntfs-3g_ntfsprogs-2014.2.15.old/src/lowntfs-3g.c 2014-02-15 14:07:52.000000000 +0000
1374 +++ ntfs-3g_ntfsprogs-2014.2.15/src/lowntfs-3g.c 2014-07-31 13:51:24.429065815 +0100
1375 @@ -81,7 +81,12 @@
1376 #include <sys/dirent.h>
1377 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
1378
1379 +#ifdef HAVE_LINUX_FS_H
1380 +#include <linux/fs.h>
1381 +#endif
1382 +
1383 #include "compat.h"
1384 +#include "bitmap.h"
1385 #include "attrib.h"
1386 #include "inode.h"
1387 #include "volume.h"
1388 @@ -97,6 +102,7 @@
1389 #include "logging.h"
1390 #include "xattrs.h"
1391 #include "misc.h"
1392 +#include "ioctl.h"
1393
1394 #include "ntfs-3g_common.h"
1395
1396 @@ -564,8 +570,6 @@
1397 }
1398 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
1399
1400 -#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \
1401 - || (defined(__APPLE__) || defined(__DARWIN__))
1402 static void ntfs_init(void *userdata __attribute__((unused)),
1403 struct fuse_conn_info *conn)
1404 {
1405 @@ -582,8 +586,8 @@
1406 >= SAFE_CAPACITY_FOR_BIG_WRITES))
1407 conn->want |= FUSE_CAP_BIG_WRITES;
1408 #endif
1409 + conn->want |= FUSE_CAP_IOCTL_DIR;
1410 }
1411 -#endif /* defined(FUSE_CAP_DONT_MASK) || (defined(__APPLE__) || defined(__DARWIN__)) */
1412
1413 static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx,
1414 ntfs_inode *ni, struct stat *stbuf)
1415 @@ -2573,6 +2577,48 @@
1416 fuse_reply_err(req, 0);
1417 }
1418
1419 +static void ntfs_fuse_ioctl(fuse_req_t req __attribute__((unused)),
1420 + fuse_ino_t ino __attribute__((unused)),
1421 + int cmd, void *arg,
1422 + struct fuse_file_info *fi __attribute__((unused)),
1423 + unsigned flags, const void *data,
1424 + size_t in_bufsz, size_t out_bufsz)
1425 +{
1426 + ntfs_inode *ni;
1427 + char *buf = (char*)NULL;
1428 + int bufsz;
1429 + int ret = 0;
1430 +
1431 + if (flags & FUSE_IOCTL_COMPAT) {
1432 + ret = -ENOSYS;
1433 + } else {
1434 + ni = ntfs_inode_open(ctx->vol, INODE(ino));
1435 + if (!ni) {
1436 + ret = -errno;
1437 + goto fail;
1438 + }
1439 + bufsz = (in_bufsz > out_bufsz ? in_bufsz : out_bufsz);
1440 + if (bufsz) {
1441 + buf = ntfs_malloc(bufsz);
1442 + if (!buf) {
1443 + ret = ENOMEM;
1444 + goto fail;
1445 + }
1446 + memcpy(buf, data, in_bufsz);
1447 + }
1448 + ret = ntfs_ioctl(ni, cmd, arg, flags, buf);
1449 + if (ntfs_inode_close (ni))
1450 + set_fuse_error(&ret);
1451 + }
1452 + if (ret)
1453 +fail :
1454 + fuse_reply_err(req, -ret);
1455 + else
1456 + fuse_reply_ioctl(req, 0, buf, out_bufsz);
1457 + if (buf)
1458 + free(buf);
1459 +}
1460 +
1461 static void ntfs_fuse_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
1462 uint64_t vidx)
1463 {
1464 @@ -3496,6 +3542,7 @@
1465 .fsyncdir = ntfs_fuse_fsync,
1466 .bmap = ntfs_fuse_bmap,
1467 .destroy = ntfs_fuse_destroy2,
1468 + .ioctl = ntfs_fuse_ioctl,
1469 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
1470 .access = ntfs_fuse_access,
1471 #endif
1472 @@ -3512,10 +3559,7 @@
1473 .setbkuptime = ntfs_macfuse_setbkuptime,
1474 .setchgtime = ntfs_macfuse_setchgtime,
1475 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
1476 -#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \
1477 - || (defined(__APPLE__) || defined(__DARWIN__))
1478 .init = ntfs_init
1479 -#endif
1480 };
1481
1482 static int ntfs_fuse_init(void)
1483 diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/src/ntfs-3g.c ntfs-3g_ntfsprogs-2014.2.15/src/ntfs-3g.c
1484 --- ntfs-3g_ntfsprogs-2014.2.15.old/src/ntfs-3g.c 2014-02-15 14:07:52.000000000 +0000
1485 +++ ntfs-3g_ntfsprogs-2014.2.15/src/ntfs-3g.c 2014-07-31 13:51:24.430065816 +0100
1486 @@ -96,6 +96,7 @@
1487 #include "logging.h"
1488 #include "xattrs.h"
1489 #include "misc.h"
1490 +#include "ioctl.h"
1491
1492 #include "ntfs-3g_common.h"
1493
1494 @@ -636,8 +637,6 @@
1495 }
1496 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
1497
1498 -#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \
1499 - || (defined(__APPLE__) || defined(__DARWIN__))
1500 static void *ntfs_init(struct fuse_conn_info *conn)
1501 {
1502 #if defined(__APPLE__) || defined(__DARWIN__)
1503 @@ -653,9 +652,9 @@
1504 >= SAFE_CAPACITY_FOR_BIG_WRITES))
1505 conn->want |= FUSE_CAP_BIG_WRITES;
1506 #endif
1507 + conn->want |= FUSE_CAP_IOCTL_DIR;
1508 return NULL;
1509 }
1510 -#endif /* defined(FUSE_CAP_DONT_MASK) || (defined(__APPLE__) || defined(__DARWIN__)) */
1511
1512 static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
1513 {
1514 @@ -2412,6 +2411,28 @@
1515 return (ret);
1516 }
1517
1518 +static int ntfs_fuse_ioctl(const char *path,
1519 + int cmd, void *arg,
1520 + struct fuse_file_info *fi __attribute__((unused)),
1521 + unsigned int flags, void *data)
1522 +{
1523 + ntfs_inode *ni;
1524 + int ret;
1525 +
1526 + if (flags & FUSE_IOCTL_COMPAT)
1527 + return -ENOSYS;
1528 +
1529 + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
1530 + if (!ni)
1531 + return -errno;
1532 +
1533 + ret = ntfs_ioctl(ni, cmd, arg, flags, data);
1534 +
1535 + if (ntfs_inode_close (ni))
1536 + set_fuse_error(&ret);
1537 + return ret;
1538 +}
1539 +
1540 static int ntfs_fuse_bmap(const char *path, size_t blocksize, uint64_t *idx)
1541 {
1542 ntfs_inode *ni;
1543 @@ -3335,6 +3356,7 @@
1544 .fsyncdir = ntfs_fuse_fsync,
1545 .bmap = ntfs_fuse_bmap,
1546 .destroy = ntfs_fuse_destroy2,
1547 + .ioctl = ntfs_fuse_ioctl,
1548 #if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
1549 .access = ntfs_fuse_access,
1550 .opendir = ntfs_fuse_opendir,
1551 @@ -3352,10 +3374,7 @@
1552 .setbkuptime = ntfs_macfuse_setbkuptime,
1553 .setchgtime = ntfs_macfuse_setchgtime,
1554 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
1555 -#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \
1556 - || (defined(__APPLE__) || defined(__DARWIN__))
1557 .init = ntfs_init
1558 -#endif
1559 };
1560
1561 static int ntfs_fuse_init(void)