|
|
1.1 root 1: /*
2: * Block driver for RAW files (posix)
3: *
4: * Copyright (c) 2006 Fabrice Bellard
5: *
6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
24: #include "qemu-common.h"
25: #include "qemu-timer.h"
26: #include "qemu-char.h"
27: #include "qemu-log.h"
28: #include "block_int.h"
29: #include "module.h"
1.1.1.2 ! root 30: #include "block/raw-posix-aio.h"
1.1 root 31:
32: #ifdef CONFIG_COCOA
33: #include <paths.h>
34: #include <sys/param.h>
35: #include <IOKit/IOKitLib.h>
36: #include <IOKit/IOBSD.h>
37: #include <IOKit/storage/IOMediaBSDClient.h>
38: #include <IOKit/storage/IOMedia.h>
39: #include <IOKit/storage/IOCDMedia.h>
40: //#include <IOKit/storage/IOCDTypes.h>
41: #include <CoreFoundation/CoreFoundation.h>
42: #endif
43:
44: #ifdef __sun__
45: #define _POSIX_PTHREAD_SEMANTICS 1
46: #include <signal.h>
47: #include <sys/dkio.h>
48: #endif
49: #ifdef __linux__
50: #include <sys/ioctl.h>
51: #include <linux/cdrom.h>
52: #include <linux/fd.h>
53: #endif
1.1.1.2 ! root 54: #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1 root 55: #include <signal.h>
56: #include <sys/disk.h>
57: #include <sys/cdio.h>
58: #endif
59:
60: #ifdef __OpenBSD__
61: #include <sys/ioctl.h>
62: #include <sys/disklabel.h>
63: #include <sys/dkio.h>
64: #endif
65:
66: #ifdef __DragonFly__
67: #include <sys/ioctl.h>
68: #include <sys/diskslice.h>
69: #endif
70:
71: //#define DEBUG_FLOPPY
72:
73: //#define DEBUG_BLOCK
74: #if defined(DEBUG_BLOCK)
75: #define DEBUG_BLOCK_PRINT(formatCstr, ...) do { if (qemu_log_enabled()) \
76: { qemu_log(formatCstr, ## __VA_ARGS__); qemu_log_flush(); } } while (0)
77: #else
78: #define DEBUG_BLOCK_PRINT(formatCstr, ...)
79: #endif
80:
81: /* OS X does not have O_DSYNC */
82: #ifndef O_DSYNC
83: #ifdef O_SYNC
84: #define O_DSYNC O_SYNC
85: #elif defined(O_FSYNC)
86: #define O_DSYNC O_FSYNC
87: #endif
88: #endif
89:
90: /* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
91: #ifndef O_DIRECT
92: #define O_DIRECT O_DSYNC
93: #endif
94:
95: #define FTYPE_FILE 0
96: #define FTYPE_CD 1
97: #define FTYPE_FD 2
98:
99: #define ALIGNED_BUFFER_SIZE (32 * 512)
100:
101: /* if the FD is not accessed during that time (in ms), we try to
102: reopen it to see if the disk has been changed */
103: #define FD_OPEN_TIMEOUT 1000
104:
105: typedef struct BDRVRawState {
106: int fd;
107: int type;
108: unsigned int lseek_err_cnt;
109: int open_flags;
110: #if defined(__linux__)
111: /* linux floppy specific */
112: int64_t fd_open_time;
113: int64_t fd_error_time;
114: int fd_got_error;
115: int fd_media_changed;
116: #endif
1.1.1.2 ! root 117: #ifdef CONFIG_LINUX_AIO
! 118: int use_aio;
! 119: void *aio_ctx;
! 120: #endif
1.1 root 121: uint8_t* aligned_buf;
122: } BDRVRawState;
123:
124: static int fd_open(BlockDriverState *bs);
125: static int64_t raw_getlength(BlockDriverState *bs);
126:
1.1.1.2 ! root 127: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1 root 128: static int cdrom_reopen(BlockDriverState *bs);
129: #endif
130:
131: static int raw_open_common(BlockDriverState *bs, const char *filename,
132: int bdrv_flags, int open_flags)
133: {
134: BDRVRawState *s = bs->opaque;
135: int fd, ret;
136:
137: s->lseek_err_cnt = 0;
138:
139: s->open_flags = open_flags | O_BINARY;
140: s->open_flags &= ~O_ACCMODE;
141: if ((bdrv_flags & BDRV_O_ACCESS) == BDRV_O_RDWR) {
142: s->open_flags |= O_RDWR;
143: } else {
144: s->open_flags |= O_RDONLY;
145: bs->read_only = 1;
146: }
147:
148: /* Use O_DSYNC for write-through caching, no flags for write-back caching,
149: * and O_DIRECT for no caching. */
150: if ((bdrv_flags & BDRV_O_NOCACHE))
151: s->open_flags |= O_DIRECT;
152: else if (!(bdrv_flags & BDRV_O_CACHE_WB))
153: s->open_flags |= O_DSYNC;
154:
155: s->fd = -1;
1.1.1.2 ! root 156: fd = qemu_open(filename, s->open_flags, 0644);
1.1 root 157: if (fd < 0) {
158: ret = -errno;
159: if (ret == -EROFS)
160: ret = -EACCES;
161: return ret;
162: }
163: s->fd = fd;
164: s->aligned_buf = NULL;
1.1.1.2 ! root 165:
1.1 root 166: if ((bdrv_flags & BDRV_O_NOCACHE)) {
167: s->aligned_buf = qemu_blockalign(bs, ALIGNED_BUFFER_SIZE);
168: if (s->aligned_buf == NULL) {
1.1.1.2 ! root 169: goto out_close;
1.1 root 170: }
171: }
1.1.1.2 ! root 172:
! 173: #ifdef CONFIG_LINUX_AIO
! 174: if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
! 175: (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
! 176:
! 177: /* We're falling back to POSIX AIO in some cases */
! 178: paio_init();
! 179:
! 180: s->aio_ctx = laio_init();
! 181: if (!s->aio_ctx) {
! 182: goto out_free_buf;
! 183: }
! 184: s->use_aio = 1;
! 185: } else
! 186: #endif
! 187: {
! 188: if (paio_init() < 0) {
! 189: goto out_free_buf;
! 190: }
! 191: #ifdef CONFIG_LINUX_AIO
! 192: s->use_aio = 0;
! 193: #endif
! 194: }
! 195:
1.1 root 196: return 0;
1.1.1.2 ! root 197:
! 198: out_free_buf:
! 199: qemu_vfree(s->aligned_buf);
! 200: out_close:
! 201: close(fd);
! 202: return -errno;
1.1 root 203: }
204:
205: static int raw_open(BlockDriverState *bs, const char *filename, int flags)
206: {
207: BDRVRawState *s = bs->opaque;
208: int open_flags = 0;
209:
210: s->type = FTYPE_FILE;
211: if (flags & BDRV_O_CREAT)
212: open_flags = O_CREAT | O_TRUNC;
213:
214: return raw_open_common(bs, filename, flags, open_flags);
215: }
216:
217: /* XXX: use host sector size if necessary with:
218: #ifdef DIOCGSECTORSIZE
219: {
220: unsigned int sectorsize = 512;
221: if (!ioctl(fd, DIOCGSECTORSIZE, §orsize) &&
222: sectorsize > bufsize)
223: bufsize = sectorsize;
224: }
225: #endif
226: #ifdef CONFIG_COCOA
227: u_int32_t blockSize = 512;
228: if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
229: bufsize = blockSize;
230: }
231: #endif
232: */
233:
234: /*
235: * offset and count are in bytes, but must be multiples of 512 for files
236: * opened with O_DIRECT. buf must be aligned to 512 bytes then.
237: *
238: * This function may be called without alignment if the caller ensures
239: * that O_DIRECT is not in effect.
240: */
241: static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
242: uint8_t *buf, int count)
243: {
244: BDRVRawState *s = bs->opaque;
245: int ret;
246:
247: ret = fd_open(bs);
248: if (ret < 0)
249: return ret;
250:
251: if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
252: ++(s->lseek_err_cnt);
253: if(s->lseek_err_cnt <= 10) {
254: DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
255: "] lseek failed : %d = %s\n",
256: s->fd, bs->filename, offset, buf, count,
257: bs->total_sectors, errno, strerror(errno));
258: }
259: return -1;
260: }
261: s->lseek_err_cnt=0;
262:
263: ret = read(s->fd, buf, count);
264: if (ret == count)
265: goto label__raw_read__success;
266:
267: /* Allow reads beyond the end (needed for pwrite) */
268: if ((ret == 0) && bs->growable) {
269: int64_t size = raw_getlength(bs);
270: if (offset >= size) {
271: memset(buf, 0, count);
272: ret = count;
273: goto label__raw_read__success;
274: }
275: }
276:
277: DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
278: "] read failed %d : %d = %s\n",
279: s->fd, bs->filename, offset, buf, count,
280: bs->total_sectors, ret, errno, strerror(errno));
281:
282: /* Try harder for CDrom. */
283: if (bs->type == BDRV_TYPE_CDROM) {
284: lseek(s->fd, offset, SEEK_SET);
285: ret = read(s->fd, buf, count);
286: if (ret == count)
287: goto label__raw_read__success;
288: lseek(s->fd, offset, SEEK_SET);
289: ret = read(s->fd, buf, count);
290: if (ret == count)
291: goto label__raw_read__success;
292:
293: DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
294: "] retry read failed %d : %d = %s\n",
295: s->fd, bs->filename, offset, buf, count,
296: bs->total_sectors, ret, errno, strerror(errno));
297: }
298:
299: label__raw_read__success:
300:
301: return (ret < 0) ? -errno : ret;
302: }
303:
304: /*
305: * offset and count are in bytes, but must be multiples of 512 for files
306: * opened with O_DIRECT. buf must be aligned to 512 bytes then.
307: *
308: * This function may be called without alignment if the caller ensures
309: * that O_DIRECT is not in effect.
310: */
311: static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
312: const uint8_t *buf, int count)
313: {
314: BDRVRawState *s = bs->opaque;
315: int ret;
316:
317: ret = fd_open(bs);
318: if (ret < 0)
319: return -errno;
320:
321: if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
322: ++(s->lseek_err_cnt);
323: if(s->lseek_err_cnt) {
324: DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
325: PRId64 "] lseek failed : %d = %s\n",
326: s->fd, bs->filename, offset, buf, count,
327: bs->total_sectors, errno, strerror(errno));
328: }
329: return -EIO;
330: }
331: s->lseek_err_cnt = 0;
332:
333: ret = write(s->fd, buf, count);
334: if (ret == count)
335: goto label__raw_write__success;
336:
337: DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
338: "] write failed %d : %d = %s\n",
339: s->fd, bs->filename, offset, buf, count,
340: bs->total_sectors, ret, errno, strerror(errno));
341:
342: label__raw_write__success:
343:
344: return (ret < 0) ? -errno : ret;
345: }
346:
347:
348: /*
349: * offset and count are in bytes and possibly not aligned. For files opened
350: * with O_DIRECT, necessary alignments are ensured before calling
351: * raw_pread_aligned to do the actual read.
352: */
353: static int raw_pread(BlockDriverState *bs, int64_t offset,
354: uint8_t *buf, int count)
355: {
356: BDRVRawState *s = bs->opaque;
357: int size, ret, shift, sum;
358:
359: sum = 0;
360:
361: if (s->aligned_buf != NULL) {
362:
363: if (offset & 0x1ff) {
364: /* align offset on a 512 bytes boundary */
365:
366: shift = offset & 0x1ff;
367: size = (shift + count + 0x1ff) & ~0x1ff;
368: if (size > ALIGNED_BUFFER_SIZE)
369: size = ALIGNED_BUFFER_SIZE;
370: ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size);
371: if (ret < 0)
372: return ret;
373:
374: size = 512 - shift;
375: if (size > count)
376: size = count;
377: memcpy(buf, s->aligned_buf + shift, size);
378:
379: buf += size;
380: offset += size;
381: count -= size;
382: sum += size;
383:
384: if (count == 0)
385: return sum;
386: }
387: if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
388:
389: /* read on aligned buffer */
390:
391: while (count) {
392:
393: size = (count + 0x1ff) & ~0x1ff;
394: if (size > ALIGNED_BUFFER_SIZE)
395: size = ALIGNED_BUFFER_SIZE;
396:
397: ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
398: if (ret < 0)
399: return ret;
400:
401: size = ret;
402: if (size > count)
403: size = count;
404:
405: memcpy(buf, s->aligned_buf, size);
406:
407: buf += size;
408: offset += size;
409: count -= size;
410: sum += size;
411: }
412:
413: return sum;
414: }
415: }
416:
417: return raw_pread_aligned(bs, offset, buf, count) + sum;
418: }
419:
420: static int raw_read(BlockDriverState *bs, int64_t sector_num,
421: uint8_t *buf, int nb_sectors)
422: {
423: int ret;
424:
425: ret = raw_pread(bs, sector_num * 512, buf, nb_sectors * 512);
426: if (ret == (nb_sectors * 512))
427: ret = 0;
428: return ret;
429: }
430:
431: /*
432: * offset and count are in bytes and possibly not aligned. For files opened
433: * with O_DIRECT, necessary alignments are ensured before calling
434: * raw_pwrite_aligned to do the actual write.
435: */
436: static int raw_pwrite(BlockDriverState *bs, int64_t offset,
437: const uint8_t *buf, int count)
438: {
439: BDRVRawState *s = bs->opaque;
440: int size, ret, shift, sum;
441:
442: sum = 0;
443:
444: if (s->aligned_buf != NULL) {
445:
446: if (offset & 0x1ff) {
447: /* align offset on a 512 bytes boundary */
448: shift = offset & 0x1ff;
449: ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, 512);
450: if (ret < 0)
451: return ret;
452:
453: size = 512 - shift;
454: if (size > count)
455: size = count;
456: memcpy(s->aligned_buf + shift, buf, size);
457:
458: ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf, 512);
459: if (ret < 0)
460: return ret;
461:
462: buf += size;
463: offset += size;
464: count -= size;
465: sum += size;
466:
467: if (count == 0)
468: return sum;
469: }
470: if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
471:
472: while ((size = (count & ~0x1ff)) != 0) {
473:
474: if (size > ALIGNED_BUFFER_SIZE)
475: size = ALIGNED_BUFFER_SIZE;
476:
477: memcpy(s->aligned_buf, buf, size);
478:
479: ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
480: if (ret < 0)
481: return ret;
482:
483: buf += ret;
484: offset += ret;
485: count -= ret;
486: sum += ret;
487: }
488: /* here, count < 512 because (count & ~0x1ff) == 0 */
489: if (count) {
490: ret = raw_pread_aligned(bs, offset, s->aligned_buf, 512);
491: if (ret < 0)
492: return ret;
493: memcpy(s->aligned_buf, buf, count);
494:
495: ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, 512);
496: if (ret < 0)
497: return ret;
498: if (count < ret)
499: ret = count;
500:
501: sum += ret;
502: }
503: return sum;
504: }
505: }
506: return raw_pwrite_aligned(bs, offset, buf, count) + sum;
507: }
508:
509: static int raw_write(BlockDriverState *bs, int64_t sector_num,
510: const uint8_t *buf, int nb_sectors)
511: {
512: int ret;
513: ret = raw_pwrite(bs, sector_num * 512, buf, nb_sectors * 512);
514: if (ret == (nb_sectors * 512))
515: ret = 0;
516: return ret;
517: }
518:
1.1.1.2 ! root 519: /*
! 520: * Check if all memory in this vector is sector aligned.
! 521: */
! 522: static int qiov_is_aligned(QEMUIOVector *qiov)
1.1 root 523: {
1.1.1.2 ! root 524: int i;
1.1 root 525:
1.1.1.2 ! root 526: for (i = 0; i < qiov->niov; i++) {
! 527: if ((uintptr_t) qiov->iov[i].iov_base % 512) {
! 528: return 0;
1.1 root 529: }
530: }
531:
1.1.1.2 ! root 532: return 1;
1.1 root 533: }
534:
1.1.1.2 ! root 535: static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
! 536: int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
! 537: BlockDriverCompletionFunc *cb, void *opaque, int type)
1.1 root 538: {
539: BDRVRawState *s = bs->opaque;
540:
541: if (fd_open(bs) < 0)
542: return NULL;
543:
544: /*
545: * If O_DIRECT is used the buffer needs to be aligned on a sector
1.1.1.2 ! root 546: * boundary. Check if this is the case or telll the low-level
! 547: * driver that it needs to copy the buffer.
1.1 root 548: */
1.1.1.2 ! root 549: if (s->aligned_buf) {
! 550: if (!qiov_is_aligned(qiov)) {
! 551: type |= QEMU_AIO_MISALIGNED;
! 552: #ifdef CONFIG_LINUX_AIO
! 553: } else if (s->use_aio) {
! 554: return laio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov,
! 555: nb_sectors, cb, opaque, type);
! 556: #endif
! 557: }
! 558: }
1.1 root 559:
1.1.1.2 ! root 560: return paio_submit(bs, s->fd, sector_num, qiov, nb_sectors,
! 561: cb, opaque, type);
1.1 root 562: }
563:
564: static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
565: int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
566: BlockDriverCompletionFunc *cb, void *opaque)
567: {
1.1.1.2 ! root 568: return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
! 569: cb, opaque, QEMU_AIO_READ);
1.1 root 570: }
571:
572: static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
573: int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
574: BlockDriverCompletionFunc *cb, void *opaque)
575: {
1.1.1.2 ! root 576: return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
! 577: cb, opaque, QEMU_AIO_WRITE);
1.1 root 578: }
1.1.1.2 ! root 579:
! 580: static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
! 581: BlockDriverCompletionFunc *cb, void *opaque)
1.1 root 582: {
1.1.1.2 ! root 583: BDRVRawState *s = bs->opaque;
! 584:
! 585: if (fd_open(bs) < 0)
! 586: return NULL;
1.1 root 587:
1.1.1.2 ! root 588: return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
! 589: }
1.1 root 590:
591: static void raw_close(BlockDriverState *bs)
592: {
593: BDRVRawState *s = bs->opaque;
594: if (s->fd >= 0) {
595: close(s->fd);
596: s->fd = -1;
597: if (s->aligned_buf != NULL)
598: qemu_free(s->aligned_buf);
599: }
600: }
601:
602: static int raw_truncate(BlockDriverState *bs, int64_t offset)
603: {
604: BDRVRawState *s = bs->opaque;
605: if (s->type != FTYPE_FILE)
606: return -ENOTSUP;
607: if (ftruncate(s->fd, offset) < 0)
608: return -errno;
609: return 0;
610: }
611:
612: #ifdef __OpenBSD__
613: static int64_t raw_getlength(BlockDriverState *bs)
614: {
615: BDRVRawState *s = bs->opaque;
616: int fd = s->fd;
617: struct stat st;
618:
619: if (fstat(fd, &st))
620: return -1;
621: if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
622: struct disklabel dl;
623:
624: if (ioctl(fd, DIOCGDINFO, &dl))
625: return -1;
626: return (uint64_t)dl.d_secsize *
627: dl.d_partitions[DISKPART(st.st_rdev)].p_size;
628: } else
629: return st.st_size;
630: }
631: #else /* !__OpenBSD__ */
632: static int64_t raw_getlength(BlockDriverState *bs)
633: {
634: BDRVRawState *s = bs->opaque;
635: int fd = s->fd;
636: int64_t size;
1.1.1.2 ! root 637: #ifdef CONFIG_BSD
1.1 root 638: struct stat sb;
1.1.1.2 ! root 639: #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1 root 640: int reopened = 0;
641: #endif
642: #endif
643: #ifdef __sun__
644: struct dk_minfo minfo;
645: int rv;
646: #endif
647: int ret;
648:
649: ret = fd_open(bs);
650: if (ret < 0)
651: return ret;
652:
1.1.1.2 ! root 653: #ifdef CONFIG_BSD
! 654: #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1 root 655: again:
656: #endif
657: if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
658: #ifdef DIOCGMEDIASIZE
659: if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
660: #elif defined(DIOCGPART)
661: {
662: struct partinfo pi;
663: if (ioctl(fd, DIOCGPART, &pi) == 0)
664: size = pi.media_size;
665: else
666: size = 0;
667: }
668: if (size == 0)
669: #endif
670: #ifdef CONFIG_COCOA
671: size = LONG_LONG_MAX;
672: #else
673: size = lseek(fd, 0LL, SEEK_END);
674: #endif
1.1.1.2 ! root 675: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1 root 676: switch(s->type) {
677: case FTYPE_CD:
678: /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */
679: if (size == 2048LL * (unsigned)-1)
680: size = 0;
681: /* XXX no disc? maybe we need to reopen... */
682: if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) {
683: reopened = 1;
684: goto again;
685: }
686: }
687: #endif
688: } else
689: #endif
690: #ifdef __sun__
691: /*
692: * use the DKIOCGMEDIAINFO ioctl to read the size.
693: */
694: rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
695: if ( rv != -1 ) {
696: size = minfo.dki_lbsize * minfo.dki_capacity;
697: } else /* there are reports that lseek on some devices
698: fails, but irc discussion said that contingency
699: on contingency was overkill */
700: #endif
701: {
702: size = lseek(fd, 0, SEEK_END);
703: }
704: return size;
705: }
706: #endif
707:
708: static int raw_create(const char *filename, QEMUOptionParameter *options)
709: {
710: int fd;
711: int result = 0;
712: int64_t total_size = 0;
713:
714: /* Read out options */
715: while (options && options->name) {
716: if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
717: total_size = options->value.n / 512;
718: }
719: options++;
720: }
721:
722: fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
723: 0644);
724: if (fd < 0) {
725: result = -errno;
726: } else {
727: if (ftruncate(fd, total_size * 512) != 0) {
728: result = -errno;
729: }
730: if (close(fd) != 0) {
731: result = -errno;
732: }
733: }
734: return result;
735: }
736:
737: static void raw_flush(BlockDriverState *bs)
738: {
739: BDRVRawState *s = bs->opaque;
1.1.1.2 ! root 740: qemu_fdatasync(s->fd);
1.1 root 741: }
742:
743:
744: static QEMUOptionParameter raw_create_options[] = {
745: {
746: .name = BLOCK_OPT_SIZE,
747: .type = OPT_SIZE,
748: .help = "Virtual disk size"
749: },
750: { NULL }
751: };
752:
753: static BlockDriver bdrv_raw = {
754: .format_name = "raw",
755: .instance_size = sizeof(BDRVRawState),
756: .bdrv_probe = NULL, /* no probe for protocols */
757: .bdrv_open = raw_open,
758: .bdrv_read = raw_read,
759: .bdrv_write = raw_write,
760: .bdrv_close = raw_close,
761: .bdrv_create = raw_create,
762: .bdrv_flush = raw_flush,
763:
764: .bdrv_aio_readv = raw_aio_readv,
765: .bdrv_aio_writev = raw_aio_writev,
1.1.1.2 ! root 766: .bdrv_aio_flush = raw_aio_flush,
1.1 root 767:
768: .bdrv_truncate = raw_truncate,
769: .bdrv_getlength = raw_getlength,
770:
771: .create_options = raw_create_options,
772: };
773:
774: /***********************************************/
775: /* host device */
776:
777: #ifdef CONFIG_COCOA
778: static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
779: static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
780:
781: kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
782: {
783: kern_return_t kernResult;
784: mach_port_t masterPort;
785: CFMutableDictionaryRef classesToMatch;
786:
787: kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
788: if ( KERN_SUCCESS != kernResult ) {
789: printf( "IOMasterPort returned %d\n", kernResult );
790: }
791:
792: classesToMatch = IOServiceMatching( kIOCDMediaClass );
793: if ( classesToMatch == NULL ) {
794: printf( "IOServiceMatching returned a NULL dictionary.\n" );
795: } else {
796: CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
797: }
798: kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
799: if ( KERN_SUCCESS != kernResult )
800: {
801: printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
802: }
803:
804: return kernResult;
805: }
806:
807: kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
808: {
809: io_object_t nextMedia;
810: kern_return_t kernResult = KERN_FAILURE;
811: *bsdPath = '\0';
812: nextMedia = IOIteratorNext( mediaIterator );
813: if ( nextMedia )
814: {
815: CFTypeRef bsdPathAsCFString;
816: bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
817: if ( bsdPathAsCFString ) {
818: size_t devPathLength;
819: strcpy( bsdPath, _PATH_DEV );
820: strcat( bsdPath, "r" );
821: devPathLength = strlen( bsdPath );
822: if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
823: kernResult = KERN_SUCCESS;
824: }
825: CFRelease( bsdPathAsCFString );
826: }
827: IOObjectRelease( nextMedia );
828: }
829:
830: return kernResult;
831: }
832:
833: #endif
834:
835: static int hdev_probe_device(const char *filename)
836: {
837: struct stat st;
838:
839: /* allow a dedicated CD-ROM driver to match with a higher priority */
840: if (strstart(filename, "/dev/cdrom", NULL))
841: return 50;
842:
843: if (stat(filename, &st) >= 0 &&
844: (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
845: return 100;
846: }
847:
848: return 0;
849: }
850:
851: static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
852: {
853: BDRVRawState *s = bs->opaque;
854:
855: #ifdef CONFIG_COCOA
856: if (strstart(filename, "/dev/cdrom", NULL)) {
857: kern_return_t kernResult;
858: io_iterator_t mediaIterator;
859: char bsdPath[ MAXPATHLEN ];
860: int fd;
861:
862: kernResult = FindEjectableCDMedia( &mediaIterator );
863: kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
864:
865: if ( bsdPath[ 0 ] != '\0' ) {
866: strcat(bsdPath,"s0");
867: /* some CDs don't have a partition 0 */
868: fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
869: if (fd < 0) {
870: bsdPath[strlen(bsdPath)-1] = '1';
871: } else {
872: close(fd);
873: }
874: filename = bsdPath;
875: }
876:
877: if ( mediaIterator )
878: IOObjectRelease( mediaIterator );
879: }
880: #endif
881:
882: s->type = FTYPE_FILE;
1.1.1.2 ! root 883: #if defined(__linux__)
1.1 root 884: if (strstart(filename, "/dev/sg", NULL)) {
885: bs->sg = 1;
886: }
887: #endif
888:
889: return raw_open_common(bs, filename, flags, 0);
890: }
891:
892: #if defined(__linux__)
893: /* Note: we do not have a reliable method to detect if the floppy is
894: present. The current method is to try to open the floppy at every
895: I/O and to keep it opened during a few hundreds of ms. */
896: static int fd_open(BlockDriverState *bs)
897: {
898: BDRVRawState *s = bs->opaque;
899: int last_media_present;
900:
901: if (s->type != FTYPE_FD)
902: return 0;
903: last_media_present = (s->fd >= 0);
904: if (s->fd >= 0 &&
905: (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
906: close(s->fd);
907: s->fd = -1;
908: #ifdef DEBUG_FLOPPY
909: printf("Floppy closed\n");
910: #endif
911: }
912: if (s->fd < 0) {
913: if (s->fd_got_error &&
914: (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
915: #ifdef DEBUG_FLOPPY
916: printf("No floppy (open delayed)\n");
917: #endif
918: return -EIO;
919: }
920: s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK);
921: if (s->fd < 0) {
922: s->fd_error_time = qemu_get_clock(rt_clock);
923: s->fd_got_error = 1;
924: if (last_media_present)
925: s->fd_media_changed = 1;
926: #ifdef DEBUG_FLOPPY
927: printf("No floppy\n");
928: #endif
929: return -EIO;
930: }
931: #ifdef DEBUG_FLOPPY
932: printf("Floppy opened\n");
933: #endif
934: }
935: if (!last_media_present)
936: s->fd_media_changed = 1;
937: s->fd_open_time = qemu_get_clock(rt_clock);
938: s->fd_got_error = 0;
939: return 0;
940: }
941:
942: static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
943: {
944: BDRVRawState *s = bs->opaque;
945:
946: return ioctl(s->fd, req, buf);
947: }
948:
949: static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
950: unsigned long int req, void *buf,
951: BlockDriverCompletionFunc *cb, void *opaque)
952: {
953: BDRVRawState *s = bs->opaque;
954:
955: if (fd_open(bs) < 0)
956: return NULL;
1.1.1.2 ! root 957: return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
1.1 root 958: }
959:
1.1.1.2 ! root 960: #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1 root 961: static int fd_open(BlockDriverState *bs)
962: {
963: BDRVRawState *s = bs->opaque;
964:
965: /* this is just to ensure s->fd is sane (its called by io ops) */
966: if (s->fd >= 0)
967: return 0;
968: return -EIO;
969: }
970: #else /* !linux && !FreeBSD */
971:
972: static int fd_open(BlockDriverState *bs)
973: {
974: return 0;
975: }
976:
977: #endif /* !linux && !FreeBSD */
978:
979: static int hdev_create(const char *filename, QEMUOptionParameter *options)
980: {
981: int fd;
982: int ret = 0;
983: struct stat stat_buf;
984: int64_t total_size = 0;
985:
986: /* Read out options */
987: while (options && options->name) {
988: if (!strcmp(options->name, "size")) {
989: total_size = options->value.n / 512;
990: }
991: options++;
992: }
993:
994: fd = open(filename, O_WRONLY | O_BINARY);
995: if (fd < 0)
996: return -EIO;
997:
998: if (fstat(fd, &stat_buf) < 0)
999: ret = -EIO;
1000: else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
1001: ret = -EIO;
1002: else if (lseek(fd, 0, SEEK_END) < total_size * 512)
1003: ret = -ENOSPC;
1004:
1005: close(fd);
1006: return ret;
1007: }
1008:
1009: static BlockDriver bdrv_host_device = {
1.1.1.2 ! root 1010: .format_name = "host_device",
! 1011: .instance_size = sizeof(BDRVRawState),
! 1012: .bdrv_probe_device = hdev_probe_device,
! 1013: .bdrv_open = hdev_open,
! 1014: .bdrv_close = raw_close,
1.1 root 1015: .bdrv_create = hdev_create,
1.1.1.2 ! root 1016: .create_options = raw_create_options,
! 1017: .no_zero_init = 1,
! 1018: .bdrv_flush = raw_flush,
1.1 root 1019:
1020: .bdrv_aio_readv = raw_aio_readv,
1021: .bdrv_aio_writev = raw_aio_writev,
1.1.1.2 ! root 1022: .bdrv_aio_flush = raw_aio_flush,
1.1 root 1023:
1024: .bdrv_read = raw_read,
1025: .bdrv_write = raw_write,
1026: .bdrv_getlength = raw_getlength,
1027:
1028: /* generic scsi device */
1029: #ifdef __linux__
1030: .bdrv_ioctl = hdev_ioctl,
1031: .bdrv_aio_ioctl = hdev_aio_ioctl,
1032: #endif
1033: };
1034:
1035: #ifdef __linux__
1036: static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
1037: {
1038: BDRVRawState *s = bs->opaque;
1039: int ret;
1040:
1041: s->type = FTYPE_FD;
1042:
1043: /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
1044: ret = raw_open_common(bs, filename, flags, O_NONBLOCK);
1045: if (ret)
1046: return ret;
1047:
1048: /* close fd so that we can reopen it as needed */
1049: close(s->fd);
1050: s->fd = -1;
1051: s->fd_media_changed = 1;
1052:
1053: return 0;
1054: }
1055:
1056: static int floppy_probe_device(const char *filename)
1057: {
1058: if (strstart(filename, "/dev/fd", NULL))
1059: return 100;
1060: return 0;
1061: }
1062:
1063:
1064: static int floppy_is_inserted(BlockDriverState *bs)
1065: {
1066: return fd_open(bs) >= 0;
1067: }
1068:
1069: static int floppy_media_changed(BlockDriverState *bs)
1070: {
1071: BDRVRawState *s = bs->opaque;
1072: int ret;
1073:
1074: /*
1075: * XXX: we do not have a true media changed indication.
1076: * It does not work if the floppy is changed without trying to read it.
1077: */
1078: fd_open(bs);
1079: ret = s->fd_media_changed;
1080: s->fd_media_changed = 0;
1081: #ifdef DEBUG_FLOPPY
1082: printf("Floppy changed=%d\n", ret);
1083: #endif
1084: return ret;
1085: }
1086:
1087: static int floppy_eject(BlockDriverState *bs, int eject_flag)
1088: {
1089: BDRVRawState *s = bs->opaque;
1090: int fd;
1091:
1092: if (s->fd >= 0) {
1093: close(s->fd);
1094: s->fd = -1;
1095: }
1096: fd = open(bs->filename, s->open_flags | O_NONBLOCK);
1097: if (fd >= 0) {
1098: if (ioctl(fd, FDEJECT, 0) < 0)
1099: perror("FDEJECT");
1100: close(fd);
1101: }
1102:
1103: return 0;
1104: }
1105:
1106: static BlockDriver bdrv_host_floppy = {
1107: .format_name = "host_floppy",
1108: .instance_size = sizeof(BDRVRawState),
1109: .bdrv_probe_device = floppy_probe_device,
1110: .bdrv_open = floppy_open,
1111: .bdrv_close = raw_close,
1112: .bdrv_create = hdev_create,
1.1.1.2 ! root 1113: .create_options = raw_create_options,
! 1114: .no_zero_init = 1,
1.1 root 1115: .bdrv_flush = raw_flush,
1116:
1117: .bdrv_aio_readv = raw_aio_readv,
1118: .bdrv_aio_writev = raw_aio_writev,
1.1.1.2 ! root 1119: .bdrv_aio_flush = raw_aio_flush,
1.1 root 1120:
1121: .bdrv_read = raw_read,
1122: .bdrv_write = raw_write,
1123: .bdrv_getlength = raw_getlength,
1124:
1125: /* removable device support */
1126: .bdrv_is_inserted = floppy_is_inserted,
1127: .bdrv_media_changed = floppy_media_changed,
1128: .bdrv_eject = floppy_eject,
1129: };
1130:
1131: static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1132: {
1133: BDRVRawState *s = bs->opaque;
1134:
1135: s->type = FTYPE_CD;
1136:
1137: /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
1138: return raw_open_common(bs, filename, flags, O_NONBLOCK);
1139: }
1140:
1141: static int cdrom_probe_device(const char *filename)
1142: {
1143: if (strstart(filename, "/dev/cd", NULL))
1144: return 100;
1145: return 0;
1146: }
1147:
1148: static int cdrom_is_inserted(BlockDriverState *bs)
1149: {
1150: BDRVRawState *s = bs->opaque;
1151: int ret;
1152:
1153: ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1154: if (ret == CDS_DISC_OK)
1155: return 1;
1156: return 0;
1157: }
1158:
1159: static int cdrom_eject(BlockDriverState *bs, int eject_flag)
1160: {
1161: BDRVRawState *s = bs->opaque;
1162:
1163: if (eject_flag) {
1164: if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
1165: perror("CDROMEJECT");
1166: } else {
1167: if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
1168: perror("CDROMEJECT");
1169: }
1170:
1171: return 0;
1172: }
1173:
1174: static int cdrom_set_locked(BlockDriverState *bs, int locked)
1175: {
1176: BDRVRawState *s = bs->opaque;
1177:
1178: if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
1179: /*
1180: * Note: an error can happen if the distribution automatically
1181: * mounts the CD-ROM
1182: */
1183: /* perror("CDROM_LOCKDOOR"); */
1184: }
1185:
1186: return 0;
1187: }
1188:
1189: static BlockDriver bdrv_host_cdrom = {
1190: .format_name = "host_cdrom",
1191: .instance_size = sizeof(BDRVRawState),
1192: .bdrv_probe_device = cdrom_probe_device,
1193: .bdrv_open = cdrom_open,
1194: .bdrv_close = raw_close,
1195: .bdrv_create = hdev_create,
1.1.1.2 ! root 1196: .create_options = raw_create_options,
! 1197: .no_zero_init = 1,
1.1 root 1198: .bdrv_flush = raw_flush,
1199:
1200: .bdrv_aio_readv = raw_aio_readv,
1201: .bdrv_aio_writev = raw_aio_writev,
1.1.1.2 ! root 1202: .bdrv_aio_flush = raw_aio_flush,
1.1 root 1203:
1204: .bdrv_read = raw_read,
1205: .bdrv_write = raw_write,
1206: .bdrv_getlength = raw_getlength,
1207:
1208: /* removable device support */
1209: .bdrv_is_inserted = cdrom_is_inserted,
1210: .bdrv_eject = cdrom_eject,
1211: .bdrv_set_locked = cdrom_set_locked,
1212:
1213: /* generic scsi device */
1214: .bdrv_ioctl = hdev_ioctl,
1215: .bdrv_aio_ioctl = hdev_aio_ioctl,
1216: };
1217: #endif /* __linux__ */
1218:
1.1.1.2 ! root 1219: #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1 root 1220: static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1221: {
1222: BDRVRawState *s = bs->opaque;
1223: int ret;
1224:
1225: s->type = FTYPE_CD;
1226:
1227: ret = raw_open_common(bs, filename, flags, 0);
1228: if (ret)
1229: return ret;
1230:
1231: /* make sure the door isnt locked at this time */
1232: ioctl(s->fd, CDIOCALLOW);
1233: return 0;
1234: }
1235:
1236: static int cdrom_probe_device(const char *filename)
1237: {
1238: if (strstart(filename, "/dev/cd", NULL) ||
1239: strstart(filename, "/dev/acd", NULL))
1240: return 100;
1241: return 0;
1242: }
1243:
1244: static int cdrom_reopen(BlockDriverState *bs)
1245: {
1246: BDRVRawState *s = bs->opaque;
1247: int fd;
1248:
1249: /*
1250: * Force reread of possibly changed/newly loaded disc,
1251: * FreeBSD seems to not notice sometimes...
1252: */
1253: if (s->fd >= 0)
1254: close(s->fd);
1255: fd = open(bs->filename, s->open_flags, 0644);
1256: if (fd < 0) {
1257: s->fd = -1;
1258: return -EIO;
1259: }
1260: s->fd = fd;
1261:
1262: /* make sure the door isnt locked at this time */
1263: ioctl(s->fd, CDIOCALLOW);
1264: return 0;
1265: }
1266:
1267: static int cdrom_is_inserted(BlockDriverState *bs)
1268: {
1269: return raw_getlength(bs) > 0;
1270: }
1271:
1272: static int cdrom_eject(BlockDriverState *bs, int eject_flag)
1273: {
1274: BDRVRawState *s = bs->opaque;
1275:
1276: if (s->fd < 0)
1277: return -ENOTSUP;
1278:
1279: (void) ioctl(s->fd, CDIOCALLOW);
1280:
1281: if (eject_flag) {
1282: if (ioctl(s->fd, CDIOCEJECT) < 0)
1283: perror("CDIOCEJECT");
1284: } else {
1285: if (ioctl(s->fd, CDIOCCLOSE) < 0)
1286: perror("CDIOCCLOSE");
1287: }
1288:
1289: if (cdrom_reopen(bs) < 0)
1290: return -ENOTSUP;
1291: return 0;
1292: }
1293:
1294: static int cdrom_set_locked(BlockDriverState *bs, int locked)
1295: {
1296: BDRVRawState *s = bs->opaque;
1297:
1298: if (s->fd < 0)
1299: return -ENOTSUP;
1300: if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
1301: /*
1302: * Note: an error can happen if the distribution automatically
1303: * mounts the CD-ROM
1304: */
1305: /* perror("CDROM_LOCKDOOR"); */
1306: }
1307:
1308: return 0;
1309: }
1310:
1311: static BlockDriver bdrv_host_cdrom = {
1312: .format_name = "host_cdrom",
1313: .instance_size = sizeof(BDRVRawState),
1314: .bdrv_probe_device = cdrom_probe_device,
1315: .bdrv_open = cdrom_open,
1316: .bdrv_close = raw_close,
1317: .bdrv_create = hdev_create,
1.1.1.2 ! root 1318: .create_options = raw_create_options,
! 1319: .no_zero_init = 1,
1.1 root 1320: .bdrv_flush = raw_flush,
1321:
1322: .bdrv_aio_readv = raw_aio_readv,
1323: .bdrv_aio_writev = raw_aio_writev,
1.1.1.2 ! root 1324: .bdrv_aio_flush = raw_aio_flush,
1.1 root 1325:
1326: .bdrv_read = raw_read,
1327: .bdrv_write = raw_write,
1328: .bdrv_getlength = raw_getlength,
1329:
1330: /* removable device support */
1331: .bdrv_is_inserted = cdrom_is_inserted,
1332: .bdrv_eject = cdrom_eject,
1333: .bdrv_set_locked = cdrom_set_locked,
1334: };
1335: #endif /* __FreeBSD__ */
1336:
1337: static void bdrv_raw_init(void)
1338: {
1339: /*
1340: * Register all the drivers. Note that order is important, the driver
1341: * registered last will get probed first.
1342: */
1343: bdrv_register(&bdrv_raw);
1344: bdrv_register(&bdrv_host_device);
1345: #ifdef __linux__
1346: bdrv_register(&bdrv_host_floppy);
1347: bdrv_register(&bdrv_host_cdrom);
1348: #endif
1.1.1.2 ! root 1349: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1 root 1350: bdrv_register(&bdrv_host_cdrom);
1351: #endif
1352: }
1353:
1354: block_init(bdrv_raw_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.