View | Details | Raw Unified | Return to bug 112402
Collapse All | Expand All

(-)fusefs-ntfs/Makefile (-10 / +36 lines)
Lines 7-39 Link Here
7
PORTNAME=	ntfs
7
PORTNAME=	ntfs
8
PORTVERSION=	1.417
8
PORTVERSION=	1.417
9
CATEGORIES=	sysutils
9
CATEGORIES=	sysutils
10
MASTER_SITES=	http://www.ntfs-3g.org/
10
MASTER_SITES=	http://www.ntfs-3g.org/:ntfs \
11
MASTER_SITE_SUBDIR=	fuse
11
		${MASTER_SITE_LOCAL:S|$|alepulver/:ublio|}
12
PKGNAMEPREFIX=	fusefs-
12
PKGNAMEPREFIX=	fusefs-
13
DISTNAME=	${PORTNAME}-3g-${PORTVERSION}
13
DISTNAME=	${PORTNAME}-3g-${PORTVERSION}
14
EXTRACT_SUFX=	.tgz
14
EXTRACT_SUFX=	.tgz
15
DISTFILES=	${DISTNAME}${EXTRACT_SUFX}:ntfs
15
16
16
MAINTAINER=	fjoe@FreeBSD.org
17
MAINTAINER=	fjoe@FreeBSD.org
17
COMMENT=	Mount NTFS partitions and disk images
18
COMMENT=	Mount NTFS partitions and disk images
18
19
20
BUILD_DEPENDS=	fusefs-libs>=2.6.0:${PORTSDIR}/sysutils/fusefs-libs
19
LIB_DEPENDS=	fuse.2:${PORTSDIR}/sysutils/fusefs-libs
21
LIB_DEPENDS=	fuse.2:${PORTSDIR}/sysutils/fusefs-libs
20
RUN_DEPENDS=	${LOCALBASE}/modules/fuse.ko:${PORTSDIR}/sysutils/fusefs-kmod
22
RUN_DEPENDS=	${LOCALBASE}/modules/fuse.ko:${PORTSDIR}/sysutils/fusefs-kmod
21
BUILD_DEPENDS=	fusefs-libs>=2.6.0:${PORTSDIR}/sysutils/fusefs-libs
22
23
23
USE_AUTOTOOLS=	libtool:15
24
GNU_CONFIGURE=	yes
25
CONFIGURE_TARGET=	--build=${ARCH}-portbld-freebsd${OSREL}
26
ONLY_FOR_ARCHS=	i386 amd64
24
ONLY_FOR_ARCHS=	i386 amd64
27
USE_LDCONFIG=	yes
25
USE_LDCONFIG=	yes
26
USE_AUTOTOOLS=	libtool:15
27
CONFIGURE_TARGET=	--build=${ARCH}-portbld-freebsd${OSREL}
28
29
OPTIONS=	LOCK "Lock the device when mounting (avoids access)" off \
30
		UBLIO "Enable user space cache for improved speed" on
31
28
MAN8=		ntfs-3g.8
32
MAN8=		ntfs-3g.8
29
33
30
post-patch:
34
UBLIO_SRC=	libublio-20070103
31
	@${CP} ${FILESDIR}/unix_io_raw.c ${WRKSRC}/libntfs-3g
32
35
33
.include <bsd.port.pre.mk>
36
.include <bsd.port.pre.mk>
34
37
35
.if ${OSVERSION} < 600000
38
.if defined(WITH_LOCK)
36
IGNORE=		depends on kernel module that requires FreeBSD 6 or later
39
CFLAGS+=	-DUSE_LOCK
40
.endif
41
42
.if defined(WITH_UBLIO)
43
DISTFILES+=	${UBLIO_SRC}.tar.gz:ublio
44
EXTRA_PATCHES+=	${FILESDIR}/extra-patch-ublio
45
CFLAGS+=	-DUSE_UBLIO
46
SUB_FILES+=	pkg-message
47
48
post-extract:
49
	@cd ${WRKDIR}/${UBLIO_SRC} && \
50
		${CP} ublio.c ${WRKSRC}/libntfs-3g && \
51
		${CP} *.h ${WRKSRC}/include/ntfs-3g
52
53
post-install:
54
	@${ECHO_CMD}; ${CAT} ${PKGMESSAGE}; ${ECHO_CMD}
55
.else
56
pre-everything::
57
	@${ECHO_MSG}
58
	@${ECHO_MSG} "WARNING: FreeBSD does not have cache support for block devices. This will considerably reduce the performance of this application, please consider enabling the UBLIO option and following the indications in the post-installation message." | ${FMT}
59
	@${ECHO_MSG}
37
.endif
60
.endif
38
61
62
post-patch:
63
	@${REINPLACE_CMD} -e 's|,nonempty||' ${WRKSRC}/src/ntfs-3g.c
64
39
.include <bsd.port.post.mk>
65
.include <bsd.port.post.mk>
(-)fusefs-ntfs/distinfo (+3 lines)
Lines 1-3 Link Here
1
MD5 (ntfs-3g-1.417.tgz) = 9e451f1084461795a96170adb6c4376b
1
MD5 (ntfs-3g-1.417.tgz) = 9e451f1084461795a96170adb6c4376b
2
SHA256 (ntfs-3g-1.417.tgz) = 6eff152c670cb9cab1c3d423aac1ce7825f3bc5f53be5ff1857c0079bd27ecc0
2
SHA256 (ntfs-3g-1.417.tgz) = 6eff152c670cb9cab1c3d423aac1ce7825f3bc5f53be5ff1857c0079bd27ecc0
3
SIZE (ntfs-3g-1.417.tgz) = 562094
3
SIZE (ntfs-3g-1.417.tgz) = 562094
4
MD5 (libublio-20070103.tar.gz) = ec8b05fe4d831111f29485b0ab8a0161
5
SHA256 (libublio-20070103.tar.gz) = 7c87d1cd7a65ab5ab61f9d7b5279bab6c8169d33d552148d396995c767be919f
6
SIZE (libublio-20070103.tar.gz) = 17238
(-)fusefs-ntfs/files/extra-patch-ublio (+69 lines)
Added Link Here
1
--- ./libntfs-3g/Makefile.am.orig	Fri Apr  6 17:22:09 2007
2
+++ ./libntfs-3g/Makefile.am	Mon Apr 30 13:34:44 2007
3
@@ -54,7 +54,8 @@
4
 	security.c	\
5
 	unistr.c	\
6
 	version.c	\
7
-	volume.c
8
+	volume.c \
9
+	ublio.c
10
 
11
 AM_CPPFLAGS = $(linux_ntfsincludedir) $(all_includes)
12
 
13
--- ./src/ntfs-3g.c.orig	Sun Apr 15 20:52:01 2007
14
+++ ./src/ntfs-3g.c	Mon Apr 30 14:12:57 2007
15
@@ -1603,7 +1603,11 @@
16
 	.mkdir		= ntfs_fuse_mkdir,
17
 	.rmdir		= ntfs_fuse_rmdir,
18
 	.utime		= ntfs_fuse_utime,
19
+#ifdef __linux__
20
 	.bmap		= ntfs_fuse_bmap,
21
+#else
22
+	.bmap		= NULL,
23
+#endif
24
 	.destroy        = ntfs_fuse_destroy2,
25
 #ifdef HAVE_SETXATTR
26
 	.getxattr	= ntfs_fuse_getxattr,
27
--- libntfs-3g/Makefile.in.orig	Sun Apr 15 20:50:19 2007
28
+++ libntfs-3g/Makefile.in	Mon Apr 30 14:49:21 2007
29
@@ -97,7 +97,7 @@
30
 	libntfs_3g_la-misc.lo libntfs_3g_la-mst.lo \
31
 	libntfs_3g_la-runlist.lo libntfs_3g_la-security.lo \
32
 	libntfs_3g_la-unistr.lo libntfs_3g_la-version.lo \
33
-	libntfs_3g_la-volume.lo
34
+	libntfs_3g_la-volume.lo libntfs_3g_la-ublio.lo
35
 libntfs_3g_la_OBJECTS = $(am_libntfs_3g_la_OBJECTS)
36
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
37
 depcomp = $(SHELL) $(top_srcdir)/depcomp
38
@@ -261,7 +261,8 @@
39
 	security.c	\
40
 	unistr.c	\
41
 	version.c	\
42
-	volume.c
43
+	volume.c	\
44
+	ublio.c
45
 
46
 AM_CPPFLAGS = $(linux_ntfsincludedir) $(all_includes)
47
 EXTRA_DIST = unix_io.c
48
@@ -359,6 +360,7 @@
49
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-unistr.Plo@am__quote@
50
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-version.Plo@am__quote@
51
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-volume.Plo@am__quote@
52
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-ublio.Plo@am__quote@
53
 
54
 .c.o:
55
 @am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
56
@@ -546,8 +548,13 @@
57
 @am__fastdepCC_TRUE@	if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-volume.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-volume.Tpo" -c -o libntfs_3g_la-volume.lo `test -f 'volume.c' || echo '$(srcdir)/'`volume.c; \
58
 @am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/libntfs_3g_la-volume.Tpo" "$(DEPDIR)/libntfs_3g_la-volume.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-volume.Tpo"; exit 1; fi
59
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	source='volume.c' object='libntfs_3g_la-volume.lo' libtool=yes @AMDEPBACKSLASH@
60
+libntfs_3g_la-ublio.lo: ublio.c
61
+@am__fastdepCC_TRUE@	if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-ublio.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-ublio.Tpo" -c -o libntfs_3g_la-ublio.lo `test -f 'ublio.c' || echo '$(srcdir)/'`ublio.c; \
62
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/libntfs_3g_la-ublio.Tpo" "$(DEPDIR)/libntfs_3g_la-ublio.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-ublio.Tpo"; exit 1; fi
63
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='ublio.c' object='libntfs_3g_la-ublio.lo' libtool=yes @AMDEPBACKSLASH@
64
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
65
 @am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-volume.lo `test -f 'volume.c' || echo '$(srcdir)/'`volume.c
66
+@am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-ublio.lo `test -f 'ublio.c' || echo '$(srcdir)/'`ublio.c
67
 
68
 mostlyclean-libtool:
69
 	-rm -f *.lo
(-)fusefs-ntfs/files/patch-libntfs-3g-device_io.c (-14 lines)
Removed Link Here
1
--- libntfs-3g/device_io.c.orig	Wed Dec  6 04:03:06 2006
2
+++ libntfs-3g/device_io.c	Tue Dec  5 23:04:04 2006
3
@@ -26,7 +26,11 @@
4
 #ifndef __CYGWIN32__
5
 
6
 /* Not on Cygwin; use standard Unix style low level device operations. */
7
+#if defined(__FreeBSD__)
8
+#include "unix_io_raw.c"
9
+#else
10
 #include "unix_io.c"
11
+#endif
12
 
13
 #else /* __CYGWIN32__ */
14
 
(-)fusefs-ntfs/files/patch-libntfs-3g__device.c (+56 lines)
Added Link Here
1
--- ./libntfs-3g/device.c.orig	Tue Jan  9 18:22:57 2007
2
+++ ./libntfs-3g/device.c	Mon Apr 30 13:40:54 2007
3
@@ -63,6 +63,9 @@
4
 #ifdef HAVE_LINUX_HDREG_H
5
 #include <linux/hdreg.h>
6
 #endif
7
+#ifdef __FreeBSD__
8
+#include <sys/disk.h>
9
+#endif
10
 
11
 #include "types.h"
12
 #include "mst.h"
13
@@ -533,6 +536,17 @@
14
 		}
15
 	}
16
 #endif
17
+#ifdef DIOCGMEDIASIZE 
18
+	{       off_t size;
19
+
20
+		if (dev->d_ops->ioctl(dev, DIOCGMEDIASIZE, &size) >= 0) {
21
+			ntfs_log_debug("DIOCGMEDIASIZE nr bytes = %llu (0x%llx)\n",
22
+					(unsigned long long)size,
23
+					(unsigned long long)size);
24
+			return (s64)size / block_size;
25
+		}
26
+	}
27
+#endif
28
 	/*
29
 	 * We couldn't figure it out by using a specialized ioctl,
30
 	 * so do binary search to find the size of the device.
31
@@ -681,7 +695,24 @@
32
 			return sect_size;
33
 		}
34
 	}
35
-#else
36
+#elif defined(DIOCGSECTORSIZE)
37
+	/*
38
+	 * XXX On FreeBSD (where we have DIOCGSECTORSIZE) the low-level I/O
39
+	 * system already knows the sector size, and doing an ioctl is needless.
40
+	 * However, I don't know how to extract that information cleanly,
41
+	 * without letting a bunch of platform specific #ifdef-s to sneak in.
42
+	 * So now I rather just re-do the ioctl...
43
+	 */
44
+	{
45
+		size_t sect_size = 0;
46
+
47
+		if (!dev->d_ops->ioctl(dev, DIOCGSECTORSIZE, &sect_size)) {
48
+			ntfs_log_debug("DIOCGSECTORSIZE sector size = %d bytes\n",
49
+				(int)sect_size);
50
+			return sect_size;
51
+		}
52
+	}
53
+#else
54
 	errno = EOPNOTSUPP;
55
 #endif
56
 	return -1;
(-)fusefs-ntfs/files/patch-libntfs-3g__unix_io.c (+631 lines)
Added Link Here
1
--- libntfs-3g/unix_io.c.orig	Tue Dec 12 20:16:43 2006
2
+++ libntfs-3g/unix_io.c	Thu May  3 22:27:13 2007
3
@@ -54,6 +54,22 @@
4
 #include <linux/fd.h>
5
 #endif
6
 
7
+/*
8
+ * The following build definitions are available:
9
+ * USE_ALIGNED_IO	- All I/O is done by blocks.
10
+ * USE_UBLIO		- Use the ublio user space cache library.
11
+ * USE_LOCK		- Lock the device/file when mounted.
12
+ */
13
+
14
+#ifdef __FreeBSD__
15
+#include <sys/disk.h>
16
+#define USE_ALIGNED_IO	1
17
+#endif
18
+
19
+#if USE_UBLIO
20
+#include <sys/uio.h>
21
+#endif
22
+
23
 #include "types.h"
24
 #include "mst.h"
25
 #include "debug.h"
26
@@ -61,13 +77,90 @@
27
 #include "logging.h"
28
 #include "misc.h"
29
 
30
-#define DEV_FD(dev)	(*(int *)dev->d_private)
31
+#if USE_UBLIO
32
+#define UBLIO_USE_API		1
33
+#include "ublio.h"
34
+#define UBLIO_DEFAULT_ENABLE	1
35
+#define UBLIO_DEFAULT_BLOCKSIZE	1048576
36
+#define UBLIO_DEFAULT_ITEMS	64
37
+#define UBLIO_DEFAULT_GRACE	32
38
+#define UBLIO_DEFAULT_SYNC_IO	0
39
+#endif
40
+
41
+#if USE_ALIGNED_IO
42
+#define RAW_IO_ALIGNED(dev, offset, count)			\
43
+	(DEV_HANDLE(dev)->block_size == 0 ||			\
44
+	 ((offset) % DEV_HANDLE(dev)->block_size == 0 &&	\
45
+	  (count) % DEV_HANDLE(dev)->block_size == 0))
46
+#define RAW_IO_ALIGN(dev, offset)				\
47
+	((offset) / DEV_HANDLE(dev)->block_size * DEV_HANDLE(dev)->block_size)
48
+#define RAW_IO_MAX_SIZE (128 * 1024 * 1024)
49
+#endif
50
+
51
+struct unix_filehandle {
52
+	int fd;
53
+#if USE_ALIGNED_IO
54
+	s64 pos;
55
+	s32 block_size;
56
+	s64 media_size;
57
+#endif
58
+#if USE_UBLIO
59
+	ublio_filehandle_t ublio_fh;
60
+#endif
61
+};
62
+
63
+#define DEV_HANDLE(dev)	((struct unix_filehandle *)dev->d_private)
64
+#define DEV_FD(dev)	(DEV_HANDLE(dev)->fd)
65
 
66
 /* Define to nothing if not present on this system. */
67
 #ifndef O_EXCL
68
 #	define O_EXCL 0
69
 #endif
70
 
71
+#if USE_ALIGNED_IO
72
+/**
73
+ * Get block_size and media_size
74
+ */
75
+static int
76
+raw_io_get_size(struct ntfs_device *dev)
77
+{
78
+	int bs;
79
+	off_t ms;
80
+	struct stat sb;
81
+
82
+	if (fstat(DEV_FD(dev), &sb) < 0) {
83
+		ntfs_log_perror("Failed to stat '%s'", dev->d_name);
84
+		return -1;
85
+	}
86
+
87
+	if (S_ISREG(sb.st_mode)) {
88
+		DEV_HANDLE(dev)->media_size = sb.st_size;
89
+		ntfs_log_trace("%s: regular file (media_size %lld)\n",
90
+		    dev->d_name, DEV_HANDLE(dev)->media_size);
91
+		if (getenv("FORCE_ALIGNED_IO"))
92
+			DEV_HANDLE(dev)->block_size = 512;
93
+		return 0;
94
+	}
95
+
96
+	if (ioctl(DEV_FD(dev), DIOCGSECTORSIZE, &bs) < 0) {
97
+		ntfs_log_perror("Failed to ioctl(DIOCGSECTORSIZE) '%s'",
98
+		    dev->d_name);
99
+		return -1;
100
+	}
101
+	DEV_HANDLE(dev)->block_size = bs;
102
+	ntfs_log_trace("%s: block size %d\n", dev->d_name, bs);
103
+
104
+	if (ioctl(DEV_FD(dev), DIOCGMEDIASIZE, &ms) < 0) {
105
+		ntfs_log_perror("Failed to ioctl(DIOCGMEDIASIZE) '%s'",
106
+		    dev->d_name);
107
+		return -1;
108
+	}
109
+	DEV_HANDLE(dev)->media_size = ms;
110
+	ntfs_log_trace("%s: media size %lld\n", dev->d_name, ms);
111
+	return 0;
112
+}
113
+#endif
114
+
115
 /**
116
  * ntfs_device_unix_io_open - Open a device and lock it exclusively
117
  * @dev:
118
@@ -79,9 +172,21 @@
119
  */
120
 static int ntfs_device_unix_io_open(struct ntfs_device *dev, int flags)
121
 {
122
+#if USE_ALIGNED_IO
123
+	size_t sectsize;
124
+#endif
125
+#if USE_LOCK
126
 	struct flock flk;
127
+#endif
128
 	struct stat sbuf;
129
-	int err;
130
+	struct unix_filehandle *ufh;
131
+	int err = 0;
132
+	int is_special = 0;
133
+#if USE_UBLIO
134
+	struct ublio_param up;
135
+	int use_ublio = 0;
136
+	char *xenv, *xgarbage;
137
+#endif
138
 
139
 	if (NDevOpen(dev)) {
140
 		errno = EBUSY;
141
@@ -91,20 +196,28 @@
142
 		ntfs_log_perror("Failed to access '%s'", dev->d_name);
143
 		return -1;
144
 	}
145
-	if (S_ISBLK(sbuf.st_mode))
146
-		NDevSetBlock(dev);
147
+	if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode))
148
+		is_special = 1;
149
 	
150
-	dev->d_private = ntfs_malloc(sizeof(int));
151
-	if (!dev->d_private)
152
+	ufh = ntfs_malloc(sizeof(*ufh));
153
+	if (!ufh)
154
 		return -1;
155
+	dev->d_private = ufh;
156
+#if USE_ALIGNED_IO
157
+	ufh->fd = -1;
158
+	ufh->pos = 0;
159
+	ufh->block_size = 0;
160
+	ufh->media_size = 0;
161
+#endif
162
+
163
 	/*
164
 	 * Open file for exclusive access if mounting r/w.
165
 	 * Fuseblk takes care about block devices.
166
 	 */ 
167
-	if (!NDevBlock(dev) && (flags & O_RDWR) == O_RDWR)
168
+	if (!is_special && (flags & O_RDWR) == O_RDWR)
169
 		flags |= O_EXCL;
170
-	*(int*)dev->d_private = open(dev->d_name, flags);
171
-	if (*(int*)dev->d_private == -1) {
172
+	ufh->fd = open(dev->d_name, flags);
173
+	if (ufh->fd == -1) {
174
 		err = errno;
175
 		goto err_out;
176
 	}
177
@@ -112,6 +225,37 @@
178
 	if ((flags & O_RDWR) != O_RDWR)
179
 		NDevSetReadOnly(dev);
180
 	
181
+#if USE_UBLIO
182
+	ufh->ublio_fh = NULL;
183
+	if ((xenv = getenv("NTFS_USE_UBLIO")) &&
184
+	    (xenv[0] == '0' || xenv[0] == '1') && xenv[1] == '\0')
185
+		use_ublio = (xenv[0] == '1');
186
+	else
187
+		use_ublio = UBLIO_DEFAULT_ENABLE;
188
+	if ((xenv = getenv("UBLIO_BLOCKSIZE")))
189
+		up.up_blocksize = strtoul(xenv, &xgarbage, 10);
190
+	if (!xenv || *xgarbage != '\0')
191
+		up.up_blocksize = UBLIO_DEFAULT_BLOCKSIZE;
192
+	if ((xenv = getenv("UBLIO_ITEMS")))
193
+		up.up_items = strtoul(xenv, &xgarbage, 10);
194
+	if (!xenv || *xgarbage != '\0')
195
+		up.up_items = UBLIO_DEFAULT_ITEMS;
196
+	if ((xenv = getenv("UBLIO_GRACE")))
197
+		up.up_grace = strtoul(xenv, &xgarbage, 10);
198
+	if (!xenv || *xgarbage != '\0')
199
+		up.up_grace = UBLIO_DEFAULT_GRACE;
200
+	if ((xenv = getenv("UBLIO_SYNC_IO")) &&
201
+	    (xenv[0] == '0' || xenv[0] == '1') && xenv[1] == '\0')
202
+		up.up_sync_io = (xenv[0] == '1');
203
+	else
204
+		up.up_sync_io = UBLIO_DEFAULT_SYNC_IO;
205
+	up.up_priv	= &ufh->fd;
206
+	up.up_pread	= NULL;
207
+	up.up_preadv	= NULL;
208
+	up.up_pwrite	= NULL;
209
+	up.up_pwritev	= NULL;
210
+#endif
211
+#if USE_LOCK
212
 	memset(&flk, 0, sizeof(flk));
213
 	if (NDevReadOnly(dev))
214
 		flk.l_type = F_RDLCK;
215
@@ -119,7 +263,21 @@
216
 		flk.l_type = F_WRLCK;
217
 	flk.l_whence = SEEK_SET;
218
 	flk.l_start = flk.l_len = 0LL;
219
-	if (fcntl(DEV_FD(dev), F_SETLK, &flk)) {
220
+#endif
221
+#if USE_ALIGNED_IO
222
+	if (raw_io_get_size(dev) < 0) {
223
+		err = errno;
224
+		close(DEV_FD(dev));
225
+		goto err_out;
226
+	}
227
+	if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode))
228
+		NDevSetBlock(dev);
229
+#else
230
+	if (S_ISBLK(sbuf.st_mode))
231
+		NDevSetBlock(dev);
232
+#endif /* USE_ALIGNED_IO */
233
+#if USE_LOCK
234
+	if (!NDevBlock(dev) && fcntl(DEV_FD(dev), F_SETLK, &flk)) {
235
 		err = errno;
236
 		ntfs_log_perror("Failed to %s lock '%s'", NDevReadOnly(dev) ? 
237
 				"read" : "write", dev->d_name);
238
@@ -127,7 +285,16 @@
239
 			ntfs_log_perror("Failed to close '%s'", dev->d_name);
240
 		goto err_out;
241
 	}
242
-	
243
+#endif
244
+#if USE_UBLIO
245
+	if (use_ublio) {
246
+		ufh->ublio_fh = ublio_open(&up);
247
+		if (!ufh->ublio_fh) {
248
+			close(DEV_FD(dev));
249
+			goto err_out;
250
+		}
251
+	}
252
+#endif
253
 	NDevSetOpen(dev);
254
 	return 0;
255
 err_out:
256
@@ -147,7 +314,10 @@
257
  */
258
 static int ntfs_device_unix_io_close(struct ntfs_device *dev)
259
 {
260
+	/* XXX no error if fysnc, fcntl (ublio_close) fails? */
261
+#if USE_LOCK
262
 	struct flock flk;
263
+#endif
264
 
265
 	if (!NDevOpen(dev)) {
266
 		errno = EBADF;
267
@@ -155,14 +325,21 @@
268
 	}
269
 	if (NDevDirty(dev))
270
 		fsync(DEV_FD(dev));
271
+#if USE_LOCK
272
 	/* Release exclusive (mandatory) lock on the whole device. */
273
 	memset(&flk, 0, sizeof(flk));
274
 	flk.l_type = F_UNLCK;
275
 	flk.l_whence = SEEK_SET;
276
 	flk.l_start = flk.l_len = 0LL;
277
-	if (fcntl(DEV_FD(dev), F_SETLK, &flk))
278
+
279
+	if (!NDevBlock(dev) && fcntl(DEV_FD(dev), F_SETLK, &flk))
280
 		ntfs_log_perror("ntfs_device_unix_io_close: Warning: Could not "
281
-				"unlock %s", dev->d_name);
282
+			"unlock %s", dev->d_name);
283
+#endif
284
+#if USE_UBLIO
285
+	if (DEV_HANDLE(dev)->ublio_fh)
286
+		ublio_close(DEV_HANDLE(dev)->ublio_fh);
287
+#endif
288
 	/* Close the file descriptor and clear our open flag. */
289
 	if (close(DEV_FD(dev)))
290
 		return -1;
291
@@ -185,10 +362,235 @@
292
 static s64 ntfs_device_unix_io_seek(struct ntfs_device *dev, s64 offset,
293
 		int whence)
294
 {
295
+#if USE_ALIGNED_IO
296
+	s64 abs_pos;
297
+
298
+	ntfs_log_trace("seek offset = 0x%llx, whence = %d.\n", offset, whence);
299
+	switch (whence) {
300
+	case SEEK_SET:
301
+		abs_pos = offset;
302
+		break;
303
+
304
+	case SEEK_CUR:
305
+		abs_pos = DEV_HANDLE(dev)->pos + offset;
306
+		break;
307
+
308
+	case SEEK_END:
309
+		abs_pos = DEV_HANDLE(dev)->media_size + offset;
310
+		break;
311
+
312
+	default:
313
+		ntfs_log_trace("Wrong mode %d.\n", whence);
314
+		errno = EINVAL;
315
+		return -1;
316
+	}
317
+
318
+	if (abs_pos < 0 || abs_pos > DEV_HANDLE(dev)->media_size) {
319
+		ntfs_log_trace("Seeking outsize seekable area.\n");
320
+		errno = EINVAL;
321
+		return -1;
322
+	}
323
+	DEV_HANDLE(dev)->pos = abs_pos;
324
+	return abs_pos;
325
+#else
326
 	return lseek(DEV_FD(dev), offset, whence);
327
+#endif
328
+}
329
+
330
+#if USE_ALIGNED_IO
331
+
332
+#if USE_UBLIO
333
+#define pread_wrap(fd, buf, count, off)					\
334
+	(DEV_HANDLE(fd)->ublio_fh ?					\
335
+	ublio_pread(DEV_HANDLE(fd)->ublio_fh, buf, count, off) :	\
336
+	pread(DEV_FD(fd), buf, count, off))
337
+#define pwrite_wrap(fd, buf, count, off)				\
338
+	(DEV_HANDLE(fd)->ublio_fh ?					\
339
+	ublio_pwrite(DEV_HANDLE(fd)->ublio_fh, buf, count, off) :	\
340
+	pwrite(DEV_FD(fd), buf, count, off))
341
+#else
342
+#define pread_wrap(fd, buf, count, off)		\
343
+	pread(DEV_FD(fd), buf, count, off)
344
+#define pwrite_wrap(fd, buf, count, off)	\
345
+	pwrite(DEV_FD(fd), buf, count, off)
346
+#endif
347
+
348
+/**
349
+ * aligned_pread - Perform an aligned positioned read from the device
350
+ */
351
+static s64 aligned_pread(struct ntfs_device *dev, void *buf, s64 count, s64 offset)
352
+{
353
+	s64 start, start_aligned;
354
+	s64 end, end_aligned;
355
+	size_t count_aligned;
356
+	char *buf_aligned;
357
+	ssize_t nr;
358
+
359
+	/* short-circuit for regular files */
360
+	start = offset;
361
+	if (count > RAW_IO_MAX_SIZE)
362
+		count = RAW_IO_MAX_SIZE;
363
+	if (RAW_IO_ALIGNED(dev, start, count))
364
+		return pread_wrap(dev, buf, count, start);
365
+
366
+	/*
367
+	 * +- start_aligned                 +- end_aligned
368
+	 * |                                |
369
+	 * |     +- start           +- end  |
370
+	 * v     v                  v       v
371
+	 * |----------|----------|----------|
372
+	 *       ^                  ^
373
+	 *       +----- count ------+
374
+	 * ^                                ^
375
+	 * +-------- count_aligned ---------+
376
+	 */
377
+	start_aligned = RAW_IO_ALIGN(dev, start);
378
+	end = start + count;
379
+	end_aligned = RAW_IO_ALIGN(dev, end) +
380
+	    (RAW_IO_ALIGNED(dev, end, 0) ? 0 : DEV_HANDLE(dev)->block_size);
381
+	count_aligned = end_aligned - start_aligned;
382
+	ntfs_log_trace(
383
+	    "%s: count = 0x%llx/0x%x, start = 0x%llx/0x%llx, end = 0x%llx/0x%llx\n",
384
+	    dev->d_name, count, count_aligned,
385
+	    start, start_aligned, end, end_aligned);
386
+
387
+	/* allocate buffer */
388
+	buf_aligned = ntfs_malloc(count_aligned);
389
+	if (buf_aligned == NULL) {
390
+		ntfs_log_trace("ntfs_malloc(%d) failed\n", count_aligned);
391
+		return -1;
392
+	}
393
+
394
+	/* read aligned data */
395
+	nr = pread_wrap(dev, buf_aligned, count_aligned, start_aligned);
396
+	if (nr == 0)
397
+		return 0;
398
+	if (nr < 0 || nr < start - start_aligned) {
399
+		free(buf_aligned);
400
+		return -1;
401
+	}
402
+
403
+	/* copy out */
404
+	memcpy(buf, buf_aligned + (start - start_aligned), count);
405
+	free(buf_aligned);
406
+
407
+	nr -= start - start_aligned;
408
+	if (nr > count)
409
+		nr = count;
410
+	return nr;
411
 }
412
 
413
 /**
414
+ * aligned_pwrite - Perform an aligned positioned write from the device
415
+ */
416
+static s64 aligned_pwrite(struct ntfs_device *dev, void *buf, s64 count, s64 offset)
417
+{
418
+	s64 start, start_aligned;
419
+	s64 end, end_aligned;
420
+	size_t count_aligned;
421
+	char *buf_aligned;
422
+	ssize_t nw;
423
+
424
+	if (NDevReadOnly(dev)) {
425
+		errno = EROFS;
426
+		return -1;
427
+	}
428
+	NDevSetDirty(dev);
429
+
430
+	/* short-circuit for regular files */
431
+	start = offset;
432
+	if (count > RAW_IO_MAX_SIZE)
433
+		count = RAW_IO_MAX_SIZE;
434
+	if (RAW_IO_ALIGNED(dev, start, count))
435
+		return pwrite_wrap(dev, buf, count, start);
436
+
437
+	/*
438
+	 * +- start_aligned                 +- end_aligned
439
+	 * |                                |
440
+	 * |     +- start           +- end  |
441
+	 * v     v                  v       v
442
+	 * |----------|----------|----------|
443
+	 *       ^                  ^
444
+	 *       +----- count ------+
445
+	 * ^                                ^
446
+	 * +-------- count_aligned ---------+
447
+	 */
448
+	start_aligned = RAW_IO_ALIGN(dev, start);
449
+	end = start + count;
450
+	end_aligned = RAW_IO_ALIGN(dev, end) +
451
+	    (RAW_IO_ALIGNED(dev, end, 0) ? 0 : DEV_HANDLE(dev)->block_size);
452
+	count_aligned = end_aligned - start_aligned;
453
+	ntfs_log_trace(
454
+	    "%s: count = 0x%llx/0x%x, start = 0x%llx/0x%llx, end = 0x%llx/0x%llx\n",
455
+	    dev->d_name, count, count_aligned,
456
+	    start, start_aligned, end, end_aligned);
457
+
458
+	/* allocate buffer */
459
+	buf_aligned = ntfs_malloc(count_aligned);
460
+	if (buf_aligned == NULL) {
461
+		ntfs_log_trace("ntfs_malloc(%d) failed\n", count_aligned);
462
+		return -1;
463
+	}
464
+
465
+	/* read aligned lead-in */
466
+	if (pread_wrap(dev, buf_aligned, DEV_HANDLE(dev)->block_size, start_aligned) != DEV_HANDLE(dev)->block_size) {
467
+		ntfs_log_trace("read lead-in failed\n");
468
+		free(buf_aligned);
469
+		return -1;
470
+	}
471
+
472
+	/* read aligned lead-out */
473
+	if (end != end_aligned && count_aligned > DEV_HANDLE(dev)->block_size) {
474
+		if (pread_wrap(dev, buf_aligned + count_aligned - DEV_HANDLE(dev)->block_size, DEV_HANDLE(dev)->block_size, end_aligned - DEV_HANDLE(dev)->block_size) != DEV_HANDLE(dev)->block_size) {
475
+			ntfs_log_trace("read lead-out failed\n");
476
+			free(buf_aligned);
477
+			return -1;
478
+		}
479
+	}
480
+
481
+	/* copy data to write */
482
+	memcpy(buf_aligned + (start - start_aligned), buf, count);
483
+
484
+	/* write aligned data */
485
+	nw = pwrite_wrap(dev, buf_aligned, count_aligned, start_aligned);
486
+	free(buf_aligned);
487
+	if (nw < 0 || nw < start - start_aligned)
488
+		return -1;
489
+
490
+	nw -= start - start_aligned;
491
+	if (nw > count)
492
+		nw = count;
493
+	return nw;
494
+}
495
+
496
+/**
497
+ * aligned_read - Perform an aligned read from the device
498
+ */
499
+static s64 aligned_read(struct ntfs_device *dev, void *buf, s64 count)
500
+{
501
+	s64 nr = aligned_pread(dev, buf, count, DEV_HANDLE(dev)->pos);
502
+	if (nr > 0)
503
+		DEV_HANDLE(dev)->pos += nr;
504
+	return nr;
505
+}
506
+
507
+/**
508
+ * aligned_write - Perform an aligned read from the device
509
+ */
510
+static s64 aligned_write(struct ntfs_device *dev, void *buf, s64 count)
511
+{
512
+	s64 nw = aligned_pwrite(dev, buf, count, DEV_HANDLE(dev)->pos);
513
+	if (nw > 0)
514
+		DEV_HANDLE(dev)->pos += nw;
515
+	return nw;
516
+}
517
+
518
+#undef ublio_pwrite
519
+#undef ublio_pread
520
+
521
+#endif
522
+
523
+/**
524
  * ntfs_device_unix_io_read - Read from the device, from the current location
525
  * @dev:
526
  * @buf:
527
@@ -201,6 +603,29 @@
528
 static s64 ntfs_device_unix_io_read(struct ntfs_device *dev, void *buf,
529
 		s64 count)
530
 {
531
+#if USE_ALIGNED_IO
532
+	return aligned_read(dev, buf, count);
533
+#elif USE_UBLIO
534
+	if (DEV_HANDLE(dev)->ublio_fh) {
535
+		off_t offset;
536
+		ssize_t res;
537
+
538
+		offset = lseek(DEV_FD(dev), 0, SEEK_CUR);
539
+		if (offset == -1)
540
+			return -1;
541
+
542
+		res = ublio_pread(DEV_HANDLE(dev)->ublio_fh, buf, count,
543
+		    offset);
544
+		if (res == -1)
545
+			return -1;
546
+
547
+		if (lseek(DEV_FD(dev), res, SEEK_CUR) == -1)
548
+			return -1;
549
+
550
+		return res;
551
+	}
552
+#endif
553
+
554
 	return read(DEV_FD(dev), buf, count);
555
 }
556
 
557
@@ -222,6 +647,28 @@
558
 		return -1;
559
 	}
560
 	NDevSetDirty(dev);
561
+#if USE_ALIGNED_IO
562
+	return aligned_write(dev, buf, count);
563
+#elif USE_UBLIO
564
+	if (DEV_HANDLE(dev)->ublio_fh)
565
+		off_t offset;
566
+		ssize_t res;
567
+
568
+		offset = lseek(DEV_FD(dev), 0, SEEK_CUR);
569
+		if (offset == -1)
570
+			return -1;
571
+
572
+		res = ublio_pwrite(DEV_HANDLE(dev)->ublio_fh, (void *)buf,
573
+		    count, offset);
574
+		if (res == -1)
575
+			return -1;
576
+
577
+		if (lseek(DEV_FD(dev), res, SEEK_CUR) == -1)
578
+			return -1;
579
+
580
+		return res;
581
+	}
582
+#endif
583
 	return write(DEV_FD(dev), buf, count);
584
 }
585
 
586
@@ -239,6 +686,13 @@
587
 static s64 ntfs_device_unix_io_pread(struct ntfs_device *dev, void *buf,
588
 		s64 count, s64 offset)
589
 {
590
+#if USE_ALIGNED_IO
591
+	return aligned_pread(dev, buf, count, offset);
592
+#elif USE_UBLIO
593
+	if (DEV_HANDLE(dev)->ublio_fh)
594
+		return ublio_pread(DEV_HANDLE(dev)->ublio_fh, buf, count,
595
+		    offset);
596
+#endif
597
 	return pread(DEV_FD(dev), buf, count, offset);
598
 }
599
 
600
@@ -261,6 +715,13 @@
601
 		return -1;
602
 	}
603
 	NDevSetDirty(dev);
604
+#if USE_ALIGNED_IO
605
+	return aligned_pwrite(dev, buf, count, offset);
606
+#elif USE_UBLIO
607
+	if (DEV_HANDLE(dev)->ublio_fh)
608
+		return ublio_pwrite(DEV_HANDLE(dev)->ublio_fh, (void *)buf,
609
+		    count, offset);
610
+#endif
611
 	return pwrite(DEV_FD(dev), buf, count, offset);
612
 }
613
 
614
@@ -275,7 +736,16 @@
615
 static int ntfs_device_unix_io_sync(struct ntfs_device *dev)
616
 {
617
 	if (!NDevReadOnly(dev)) {
618
-		int res = fsync(DEV_FD(dev));
619
+		int res;
620
+
621
+#if USE_UBLIO
622
+		if (DEV_HANDLE(dev)->ublio_fh) {
623
+			res = ublio_fsync(DEV_HANDLE(dev)->ublio_fh);
624
+			if (res)
625
+				return res;
626
+		}
627
+#endif
628
+		res = fsync(DEV_FD(dev));
629
 		if (!res)
630
 			NDevClearDirty(dev);
631
 		return res;
(-)fusefs-ntfs/files/patch-src-ntfs-3g.c (-11 lines)
Removed Link Here
1
--- src/ntfs-3g.c.orig	Thu Apr 26 01:51:08 2007
2
+++ src/ntfs-3g.c	Thu Apr 26 01:51:15 2007
3
@@ -134,7 +134,7 @@
4
 } opts;
5
 
6
 static const char *EXEC_NAME = "ntfs-3g";
7
-static char def_opts[] = "silent,allow_other,nonempty,";
8
+static char def_opts[] = "silent,allow_other,";
9
 static ntfs_fuse_context_t *ctx;
10
 static u32 ntfs_sequence;
11
 
(-)fusefs-ntfs/files/pkg-message.in (+37 lines)
Added Link Here
1
==============================================================================
2
3
NTFS-3G has been installed, and was built with UBLIO support.
4
5
The UBLIO layer is configured through environment variables, which are read
6
when mounting the filesystem. The following are available:
7
8
NTFS_USE_UBLIO	- Enable the UBLIO cache.
9
UBLIO_BLOCKSIZE	- Actual reads/writes will be multiples of this quantity.
10
UBLIO_ITEMS	- Number of cache entries, each of UBLIO_BLOCKSIZE length.
11
UBLIO_GRACE	- Number of times a cache entry will refuse being recycled.
12
UBLIO_SYNC_IO	- If enabled, all writes will be immediatly executed.
13
14
To give an idea about tuning, here are the default values with some notes
15
(they are only based on some simple benchmarks, and may be wrong):
16
17
NTFS_USE_UBLIO	- 1. Disabling it drastically decreases performance.
18
UBLIO_BLOCKSIZE	- 1048576 (1MB). Larger improves reading/writing speed of
19
		  large files, and smaller makes filesystem operations
20
		  (creation, deletion, moving, find(1)) perform faster.
21
		  Try 2/4MB and 512/256KB for the different approaches. Note
22
		  that after that points performance descreases again.
23
UBLIO_ITEMS	- 64. When greater, increases speed of filesystem operations,
24
		  but consumes more memory. Try 128.
25
UBLIO_GRACE	- 32. Makes the cache items have more chances to be reused.
26
UBLIO_SYNC_IO	- 0. If enabled, highly decreases writing speed, but the data
27
		  is written immediatly to the disk.
28
29
For example (improves performance over large files):
30
31
# env UBLIO_BLOCKSIZE=2097152 ntfs-3g /dev/ad0s1 /mnt
32
33
It is also possible to enforce block aligned I/O on regular files by setting
34
the FORCE_ALIGNED_IO variable (it will be set to 512 bytes), but this is only
35
useful for testing purposes and in practice has no use.
36
37
==============================================================================
(-)fusefs-ntfs/files/unix_io_raw.c (-587 lines)
Removed Link Here
1
/**
2
 * unix_io_raw.c - Unix style disk io functions. Originated from the Linux-NTFS project.
3
 *
4
 * Copyright (c) 2006 Max Khon
5
 *
6
 * This program/include file is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License as published
8
 * by the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program/include file is distributed in the hope that it will be
12
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program (in the main directory of the NTFS-3G
18
 * distribution in the file COPYING); if not, write to the Free Software
19
 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21
22
#ifdef HAVE_CONFIG_H
23
#include "config.h"
24
#endif
25
26
#ifdef HAVE_UNISTD_H
27
#include <unistd.h>
28
#endif
29
#ifdef HAVE_STDLIB_H
30
#include <stdlib.h>
31
#endif
32
#ifdef HAVE_STRING_H
33
#include <string.h>
34
#endif
35
#ifdef HAVE_ERRNO_H
36
#include <errno.h>
37
#endif
38
#ifdef HAVE_STDIO_H
39
#include <stdio.h>
40
#endif
41
#ifdef HAVE_SYS_TYPES_H
42
#include <sys/types.h>
43
#endif
44
#ifdef HAVE_SYS_STAT_H
45
#include <sys/stat.h>
46
#endif
47
#ifdef HAVE_FCNTL_H
48
#include <fcntl.h>
49
#endif
50
#ifdef HAVE_SYS_IOCTL_H
51
#include <sys/ioctl.h>
52
#endif
53
#ifdef HAVE_LINUX_FD_H
54
#include <linux/fd.h>
55
#endif
56
#include <sys/disk.h>
57
58
#include "types.h"
59
#include "mst.h"
60
#include "debug.h"
61
#include "device.h"
62
#include "logging.h"
63
#include "misc.h"
64
65
typedef struct {
66
	int fd;
67
	s64 pos;
68
	s32 block_size;
69
	s64 media_size;
70
} unix_raw_fd;
71
72
#define DEV_FD(dev)	(((unix_raw_fd *) dev->d_private))
73
#define RAW_IO_ALIGNED(dev, offset, count)			\
74
	(DEV_FD(dev)->block_size == 0 ||			\
75
	 ((offset) % DEV_FD(dev)->block_size == 0 &&		\
76
	  (count) % DEV_FD(dev)->block_size == 0))
77
#define RAW_IO_ALIGN(dev, offset)				\
78
	((offset) / DEV_FD(dev)->block_size * DEV_FD(dev)->block_size)
79
#define RAW_IO_MAX_SIZE (128 * 1024 * 1024)
80
81
/* Define to nothing if not present on this system. */
82
#ifndef O_EXCL
83
#	define O_EXCL 0
84
#endif
85
86
/**
87
 * Get block_size and media_size
88
 */
89
static int
90
raw_io_get_size(struct ntfs_device *dev)
91
{
92
	int bs;
93
	off_t ms;
94
	struct stat sb;
95
96
	if (fstat(DEV_FD(dev)->fd, &sb) < 0) {
97
		ntfs_log_perror("Failed to stat '%s'", dev->d_name);
98
		return -1;
99
	}
100
101
	if (S_ISREG(sb.st_mode)) {
102
		DEV_FD(dev)->media_size = sb.st_size;
103
		ntfs_log_trace("%s: regular file (media_size %lld)\n",
104
		    dev->d_name, DEV_FD(dev)->media_size);
105
		return 0;
106
	}
107
108
	if (ioctl(DEV_FD(dev)->fd, DIOCGSECTORSIZE, &bs) < 0) {
109
		ntfs_log_perror("Failed to ioctl(DIOCGSECTORSIZE) '%s'",
110
		    dev->d_name);
111
		return -1;
112
	}
113
	DEV_FD(dev)->block_size = bs;
114
	ntfs_log_trace("%s: block size %d\n", dev->d_name, bs);
115
116
	if (ioctl(DEV_FD(dev)->fd, DIOCGMEDIASIZE, &ms) < 0) {
117
		ntfs_log_perror("Failed to ioctl(DIOCGMEDIASIZE) '%s'",
118
		    dev->d_name);
119
		return -1;
120
	}
121
	DEV_FD(dev)->media_size = ms;
122
	ntfs_log_trace("%s: media size %lld\n", dev->d_name, ms);
123
	return 0;
124
}
125
126
/**
127
 * Aligned read
128
 */
129
static ssize_t
130
raw_io_pread(struct ntfs_device *dev, char *buf, size_t count, s64 offset)
131
{
132
	return pread(DEV_FD(dev)->fd, buf, count, offset);
133
}
134
135
/**
136
 * Aligned write
137
 */
138
static ssize_t
139
raw_io_pwrite(struct ntfs_device *dev, const char *buf, size_t count, s64 offset)
140
{
141
	return pwrite(DEV_FD(dev)->fd, buf, count, offset);
142
}
143
144
/**
145
 * ntfs_device_unix_raw_io_open - Open a device and lock it exclusively
146
 * @dev:
147
 * @flags:
148
 *
149
 * Description...
150
 *
151
 * Returns:
152
 */
153
static int
154
ntfs_device_unix_raw_io_open(struct ntfs_device *dev, int flags)
155
{
156
#if 0
157
	struct flock flk;
158
#endif
159
	struct stat sbuf;
160
	int err;
161
162
	if (NDevOpen(dev)) {
163
		errno = EBUSY;
164
		return -1;
165
	}
166
	if (stat(dev->d_name, &sbuf)) {
167
		ntfs_log_perror("Failed to access '%s'", dev->d_name);
168
		return -1;
169
	}
170
	if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode))
171
		NDevSetBlock(dev);
172
173
	dev->d_private = ntfs_malloc(sizeof(unix_raw_fd));
174
	if (!dev->d_private)
175
		return -1;
176
	DEV_FD(dev)->fd = -1;
177
	DEV_FD(dev)->pos = 0;
178
	DEV_FD(dev)->block_size = 0;
179
	DEV_FD(dev)->media_size = 0;
180
181
	/*
182
	 * Open file for exclusive access if mounting r/w.
183
	 * Fuseblk takes care about block devices.
184
	 */
185
	if (!NDevBlock(dev) && (flags & O_RDWR) == O_RDWR)
186
		flags |= O_EXCL;
187
	DEV_FD(dev)->fd = open(dev->d_name, flags);
188
	if (DEV_FD(dev)->fd == -1) {
189
		err = errno;
190
		goto err_out;
191
	}
192
193
	if ((flags & O_RDWR) != O_RDWR)
194
		NDevSetReadOnly(dev);
195
196
#if 0
197
	memset(&flk, 0, sizeof(flk));
198
	if (NDevReadOnly(dev))
199
		flk.l_type = F_RDLCK;
200
	else
201
		flk.l_type = F_WRLCK;
202
	flk.l_whence = SEEK_SET;
203
	flk.l_start = flk.l_len = 0LL;
204
	if (fcntl(DEV_FD(dev)->fd, F_SETLK, &flk)) {
205
		err = errno;
206
		ntfs_log_perror("Failed to %s lock '%s'", NDevReadOnly(dev) ?
207
				"read" : "write", dev->d_name);
208
		if (close(DEV_FD(dev)->fd))
209
			ntfs_log_perror("Failed to close '%s'", dev->d_name);
210
		goto err_out;
211
	}
212
#endif
213
214
	if (raw_io_get_size(dev) < 0) {
215
		err = errno;
216
		close(DEV_FD(dev)->fd);
217
		goto err_out;
218
	}
219
220
	NDevSetOpen(dev);
221
	return 0;
222
err_out:
223
	free(dev->d_private);
224
	dev->d_private = NULL;
225
	errno = err;
226
	return -1;
227
}
228
229
/**
230
 * ntfs_device_unix_raw_io_close - Close the device, releasing the lock
231
 * @dev:
232
 *
233
 * Description...
234
 *
235
 * Returns:
236
 */
237
static int
238
ntfs_device_unix_raw_io_close(struct ntfs_device *dev)
239
{
240
#if 0
241
	struct flock flk;
242
#endif
243
244
	if (!NDevOpen(dev)) {
245
		errno = EBADF;
246
		return -1;
247
	}
248
	if (NDevDirty(dev))
249
		fsync(DEV_FD(dev)->fd);
250
251
#if 0
252
	/* Release exclusive (mandatory) lock on the whole device. */
253
	memset(&flk, 0, sizeof(flk));
254
	flk.l_type = F_UNLCK;
255
	flk.l_whence = SEEK_SET;
256
	flk.l_start = flk.l_len = 0LL;
257
	if (fcntl(DEV_FD(dev)->fd, F_SETLK, &flk))
258
		ntfs_log_perror("ntfs_device_unix_raw_io_close: Warning: Could not "
259
				"unlock %s", dev->d_name);
260
#endif
261
262
	/* Close the file descriptor and clear our open flag. */
263
	if (close(DEV_FD(dev)->fd))
264
		return -1;
265
	NDevClearOpen(dev);
266
	free(dev->d_private);
267
	dev->d_private = NULL;
268
	return 0;
269
}
270
271
/**
272
 * ntfs_device_unix_raw_io_seek - Seek to a place on the device
273
 * @dev:
274
 * @offset:
275
 * @whence:
276
 *
277
 * Description...
278
 *
279
 * Returns:
280
 */
281
static s64
282
ntfs_device_unix_raw_io_seek(struct ntfs_device *dev, s64 offset, int whence)
283
{
284
	s64 abs_pos;
285
286
	ntfs_log_trace("seek offset = 0x%llx, whence = %d.\n", offset, whence);
287
	switch (whence) {
288
	case SEEK_SET:
289
		abs_pos = offset;
290
		break;
291
292
	case SEEK_CUR:
293
		abs_pos = DEV_FD(dev)->pos + offset;
294
		break;
295
296
	case SEEK_END:
297
		abs_pos = DEV_FD(dev)->media_size + offset;
298
		break;
299
300
	default:
301
		ntfs_log_trace("Wrong mode %d.\n", whence);
302
		errno = EINVAL;
303
		return -1;
304
	}
305
306
	if (abs_pos < 0 || abs_pos > DEV_FD(dev)->media_size) {
307
		ntfs_log_trace("Seeking outsize seekable area.\n");
308
		errno = EINVAL;
309
		return -1;
310
	}
311
	DEV_FD(dev)->pos = abs_pos;
312
	return abs_pos;
313
}
314
315
/**
316
 * ntfs_device_unix_raw_io_pread - Perform a positioned read from the device
317
 * @dev:
318
 * @buf:
319
 * @count:
320
 * @offset:
321
 *
322
 * Description...
323
 *
324
 * Returns:
325
 */
326
static s64
327
ntfs_device_unix_raw_io_pread(struct ntfs_device *dev, void *buf, s64 count, s64 offset)
328
{
329
	s64 start, start_aligned;
330
	s64 end, end_aligned;
331
	size_t count_aligned;
332
	char *buf_aligned;
333
	ssize_t nr;
334
335
	/* short-circuit for regular files */
336
	start = offset;
337
	if (count > RAW_IO_MAX_SIZE)
338
		count = RAW_IO_MAX_SIZE;
339
	if (RAW_IO_ALIGNED(dev, start, count))
340
		return raw_io_pread(dev, buf, count, start);
341
342
	/*
343
	 * +- start_aligned                 +- end_aligned
344
	 * |                                |
345
	 * |     +- start           +- end  |
346
	 * v     v                  v       v
347
	 * |----------|----------|----------|
348
	 *       ^                  ^
349
	 *       +----- count ------+
350
	 * ^                                ^
351
	 * +-------- count_aligned ---------+
352
	 */
353
	start_aligned = RAW_IO_ALIGN(dev, start);
354
	end = start + count;
355
	end_aligned = RAW_IO_ALIGN(dev, end) +
356
	    (RAW_IO_ALIGNED(dev, end, 0) ? 0 : DEV_FD(dev)->block_size);
357
	count_aligned = end_aligned - start_aligned;
358
	ntfs_log_trace(
359
	    "%s: count = 0x%llx/0x%x, start = 0x%llx/0x%llx, end = 0x%llx/0x%llx\n",
360
	    dev->d_name, count, count_aligned,
361
	    start, start_aligned, end, end_aligned);
362
363
	/* allocate buffer */
364
	buf_aligned = ntfs_malloc(count_aligned);
365
	if (buf_aligned == NULL) {
366
		ntfs_log_trace("ntfs_malloc(%d) failed\n", count_aligned);
367
		return -1;
368
	}
369
370
	/* read aligned data */
371
	nr = raw_io_pread(dev, buf_aligned, count_aligned, start_aligned);
372
	if (nr == 0)
373
		return 0;
374
	if (nr < 0 || nr < start - start_aligned) {
375
		free(buf_aligned);
376
		return -1;
377
	}
378
379
	/* copy out */
380
	memcpy(buf, buf_aligned + (start - start_aligned), count);
381
	free(buf_aligned);
382
383
	nr -= start - start_aligned;
384
	if (nr > count)
385
		nr = count;
386
	return nr;
387
}
388
389
/**
390
 * ntfs_device_unix_raw_io_pwrite - Perform a positioned write to the device
391
 * @dev:
392
 * @buf:
393
 * @count:
394
 * @offset:
395
 *
396
 * Description...
397
 *
398
 * Returns:
399
 */
400
static s64
401
ntfs_device_unix_raw_io_pwrite(struct ntfs_device *dev, const void *buf, s64 count, s64 offset)
402
{
403
	s64 start, start_aligned;
404
	s64 end, end_aligned;
405
	size_t count_aligned;
406
	char *buf_aligned;
407
	ssize_t nw;
408
409
	if (NDevReadOnly(dev)) {
410
		errno = EROFS;
411
		return -1;
412
	}
413
	NDevSetDirty(dev);
414
415
	/* short-circuit for regular files */
416
	start = offset;
417
	if (count > RAW_IO_MAX_SIZE)
418
		count = RAW_IO_MAX_SIZE;
419
	if (RAW_IO_ALIGNED(dev, start, count))
420
		return raw_io_pwrite(dev, buf, count, start);
421
422
	/*
423
	 * +- start_aligned                 +- end_aligned
424
	 * |                                |
425
	 * |     +- start           +- end  |
426
	 * v     v                  v       v
427
	 * |----------|----------|----------|
428
	 *       ^                  ^
429
	 *       +----- count ------+
430
	 * ^                                ^
431
	 * +-------- count_aligned ---------+
432
	 */
433
	start_aligned = RAW_IO_ALIGN(dev, start);
434
	end = start + count;
435
	end_aligned = RAW_IO_ALIGN(dev, end) +
436
	    (RAW_IO_ALIGNED(dev, end, 0) ? 0 : DEV_FD(dev)->block_size);
437
	count_aligned = end_aligned - start_aligned;
438
	ntfs_log_trace(
439
	    "%s: count = 0x%llx/0x%x, start = 0x%llx/0x%llx, end = 0x%llx/0x%llx\n",
440
	    dev->d_name, count, count_aligned,
441
	    start, start_aligned, end, end_aligned);
442
443
	/* allocate buffer */
444
	buf_aligned = ntfs_malloc(count_aligned);
445
	if (buf_aligned == NULL) {
446
		ntfs_log_trace("ntfs_malloc(%d) failed\n", count_aligned);
447
		return -1;
448
	}
449
450
	/* read aligned lead-in */
451
	if (raw_io_pread(dev, buf_aligned, DEV_FD(dev)->block_size, start_aligned) != DEV_FD(dev)->block_size) {
452
		ntfs_log_trace("read lead-in failed\n");
453
		free(buf_aligned);
454
		return -1;
455
	}
456
457
	/* read aligned lead-out */
458
	if (end != end_aligned && count_aligned > DEV_FD(dev)->block_size) {
459
		if (raw_io_pread(dev, buf_aligned + count_aligned - DEV_FD(dev)->block_size, DEV_FD(dev)->block_size, end_aligned - DEV_FD(dev)->block_size) != DEV_FD(dev)->block_size) {
460
			ntfs_log_trace("read lead-out failed\n");
461
			free(buf_aligned);
462
			return -1;
463
		}
464
	}
465
466
	/* copy data to write */
467
	memcpy(buf_aligned + (start - start_aligned), buf, count);
468
469
	/* write aligned data */
470
	nw = raw_io_pwrite(dev, buf_aligned, count_aligned, start_aligned);
471
	free(buf_aligned);
472
	if (nw < 0 || nw < start - start_aligned)
473
		return -1;
474
475
	nw -= start - start_aligned;
476
	if (nw > count)
477
		nw = count;
478
	return nw;
479
}
480
481
/**
482
 * ntfs_device_unix_raw_io_read - Read from the device, from the current location
483
 * @dev:
484
 * @buf:
485
 * @count:
486
 *
487
 * Description...
488
 *
489
 * Returns:
490
 */
491
static s64
492
ntfs_device_unix_raw_io_read(struct ntfs_device *dev, void *buf, s64 count)
493
{
494
	s64 nr = ntfs_device_unix_raw_io_pread(
495
	    dev, buf, count, DEV_FD(dev)->pos);
496
	if (nr > 0)
497
		DEV_FD(dev)->pos += nr;
498
	return nr;
499
}
500
501
/**
502
 * ntfs_device_unix_raw_io_write - Write to the device, at the current location
503
 * @dev:
504
 * @buf:
505
 * @count:
506
 *
507
 * Description...
508
 *
509
 * Returns:
510
 */
511
static s64
512
ntfs_device_unix_raw_io_write(struct ntfs_device *dev, const void *buf,
513
		s64 count)
514
{
515
	s64 nw = ntfs_device_unix_raw_io_pwrite(
516
	    dev, buf, count, DEV_FD(dev)->pos);
517
	if (nw > 0)
518
		DEV_FD(dev)->pos += nw;
519
	return nw;
520
}
521
522
/**
523
 * ntfs_device_unix_raw_io_sync - Flush any buffered changes to the device
524
 * @dev:
525
 *
526
 * Description...
527
 *
528
 * Returns:
529
 */
530
static int
531
ntfs_device_unix_raw_io_sync(struct ntfs_device *dev)
532
{
533
	if (!NDevReadOnly(dev)) {
534
		int res = fsync(DEV_FD(dev)->fd);
535
		if (!res)
536
			NDevClearDirty(dev);
537
		return res;
538
	}
539
	return 0;
540
}
541
542
/**
543
 * ntfs_device_unix_raw_io_stat - Get information about the device
544
 * @dev:
545
 * @buf:
546
 *
547
 * Description...
548
 *
549
 * Returns:
550
 */
551
static int
552
ntfs_device_unix_raw_io_stat(struct ntfs_device *dev, struct stat *buf)
553
{
554
	return fstat(DEV_FD(dev)->fd, buf);
555
}
556
557
/**
558
 * ntfs_device_unix_raw_io_ioctl - Perform an ioctl on the device
559
 * @dev:
560
 * @request:
561
 * @argp:
562
 *
563
 * Description...
564
 *
565
 * Returns:
566
 */
567
static int
568
ntfs_device_unix_raw_io_ioctl(struct ntfs_device *dev, int request, void *argp)
569
{
570
	return ioctl(DEV_FD(dev)->fd, request, argp);
571
}
572
573
/**
574
 * Device operations for working with unix style devices and files.
575
 */
576
struct ntfs_device_operations ntfs_device_unix_io_ops = {
577
	.open		= ntfs_device_unix_raw_io_open,
578
	.close		= ntfs_device_unix_raw_io_close,
579
	.seek		= ntfs_device_unix_raw_io_seek,
580
	.read		= ntfs_device_unix_raw_io_read,
581
	.write		= ntfs_device_unix_raw_io_write,
582
	.pread		= ntfs_device_unix_raw_io_pread,
583
	.pwrite		= ntfs_device_unix_raw_io_pwrite,
584
	.sync		= ntfs_device_unix_raw_io_sync,
585
	.stat		= ntfs_device_unix_raw_io_stat,
586
	.ioctl		= ntfs_device_unix_raw_io_ioctl,
587
};

Return to bug 112402