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