Commit e510e05b5d68386a0518e69eaf364a34bdb6283c

Authored by Anthony Liguori
2 parents f5de141b 63ec93db

Merge commit 'block/master' into staging

* commit 'block/master':
  raw-posix: cleanup ioctl methods
  block: add bdrv_probe_device method
  raw-posix: split hdev drivers
  raw-posix: add a raw_open_common helper
  raw-posix: always store open flags
  fix qemu_aio_flush

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
... ... @@ -103,11 +103,15 @@ void qemu_aio_flush(void)
103 103 do {
104 104 ret = 0;
105 105  
  106 + /*
  107 + * If there are pending emulated aio start them now so flush
  108 + * will be able to return 1.
  109 + */
  110 + qemu_aio_wait();
  111 +
106 112 LIST_FOREACH(node, &aio_handlers, node) {
107 113 ret |= node->io_flush(node->opaque);
108 114 }
109   -
110   - qemu_aio_wait();
111 115 } while (ret > 0);
112 116 }
113 117  
... ...
... ... @@ -209,7 +209,7 @@ static int is_windows_drive_prefix(const char *filename)
209 209 filename[1] == ':');
210 210 }
211 211  
212   -static int is_windows_drive(const char *filename)
  212 +int is_windows_drive(const char *filename)
213 213 {
214 214 if (is_windows_drive_prefix(filename) &&
215 215 filename[2] == '\0')
... ... @@ -249,8 +249,28 @@ static BlockDriver *find_protocol(const char *filename)
249 249 return NULL;
250 250 }
251 251  
252   -/* XXX: force raw format if block or character device ? It would
253   - simplify the BSD case */
  252 +/*
  253 + * Detect host devices. By convention, /dev/cdrom[N] is always
  254 + * recognized as a host CDROM.
  255 + */
  256 +static BlockDriver *find_hdev_driver(const char *filename)
  257 +{
  258 + int score_max = 0, score;
  259 + BlockDriver *drv = NULL, *d;
  260 +
  261 + for (d = first_drv; d; d = d->next) {
  262 + if (d->bdrv_probe_device) {
  263 + score = d->bdrv_probe_device(filename);
  264 + if (score > score_max) {
  265 + score_max = score;
  266 + drv = d;
  267 + }
  268 + }
  269 + }
  270 +
  271 + return drv;
  272 +}
  273 +
254 274 static BlockDriver *find_image_format(const char *filename)
255 275 {
256 276 int ret, score, score_max;
... ... @@ -258,23 +278,6 @@ static BlockDriver *find_image_format(const char *filename)
258 278 uint8_t buf[2048];
259 279 BlockDriverState *bs;
260 280  
261   - /* detect host devices. By convention, /dev/cdrom[N] is always
262   - recognized as a host CDROM */
263   - if (strstart(filename, "/dev/cdrom", NULL))
264   - return bdrv_find_format("host_device");
265   -#ifdef _WIN32
266   - if (is_windows_drive(filename))
267   - return bdrv_find_format("host_device");
268   -#else
269   - {
270   - struct stat st;
271   - if (stat(filename, &st) >= 0 &&
272   - (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
273   - return bdrv_find_format("host_device");
274   - }
275   - }
276   -#endif
277   -
278 281 drv = find_protocol(filename);
279 282 /* no need to test disk image formats for vvfat */
280 283 if (drv && strcmp(drv->format_name, "vvfat") == 0)
... ... @@ -394,7 +397,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
394 397 if (flags & BDRV_O_FILE) {
395 398 drv = find_protocol(filename);
396 399 } else if (!drv) {
397   - drv = find_image_format(filename);
  400 + drv = find_hdev_driver(filename);
  401 + if (!drv) {
  402 + drv = find_image_format(filename);
  403 + }
398 404 }
399 405 if (!drv) {
400 406 ret = -ENOENT;
... ...
block/raw-posix.c
... ... @@ -103,17 +103,14 @@ typedef struct BDRVRawState {
103 103 int fd;
104 104 int type;
105 105 unsigned int lseek_err_cnt;
  106 + int open_flags;
106 107 #if defined(__linux__)
107 108 /* linux floppy specific */
108   - int fd_open_flags;
109 109 int64_t fd_open_time;
110 110 int64_t fd_error_time;
111 111 int fd_got_error;
112 112 int fd_media_changed;
113 113 #endif
114   -#if defined(__FreeBSD__)
115   - int cd_open_flags;
116   -#endif
117 114 uint8_t* aligned_buf;
118 115 } BDRVRawState;
119 116  
... ... @@ -122,40 +119,36 @@ static int posix_aio_init(void);
122 119 static int fd_open(BlockDriverState *bs);
123 120  
124 121 #if defined(__FreeBSD__)
125   -static int cd_open(BlockDriverState *bs);
  122 +static int cdrom_reopen(BlockDriverState *bs);
126 123 #endif
127 124  
128   -static int raw_is_inserted(BlockDriverState *bs);
129   -
130   -static int raw_open(BlockDriverState *bs, const char *filename, int flags)
  125 +static int raw_open_common(BlockDriverState *bs, const char *filename,
  126 + int flags)
131 127 {
132 128 BDRVRawState *s = bs->opaque;
133   - int fd, open_flags, ret;
  129 + int fd, ret;
134 130  
135 131 posix_aio_init();
136 132  
137 133 s->lseek_err_cnt = 0;
138 134  
139   - open_flags = O_BINARY;
  135 + s->open_flags |= O_BINARY;
140 136 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
141   - open_flags |= O_RDWR;
  137 + s->open_flags |= O_RDWR;
142 138 } else {
143   - open_flags |= O_RDONLY;
  139 + s->open_flags |= O_RDONLY;
144 140 bs->read_only = 1;
145 141 }
146   - if (flags & BDRV_O_CREAT)
147   - open_flags |= O_CREAT | O_TRUNC;
148 142  
149 143 /* Use O_DSYNC for write-through caching, no flags for write-back caching,
150 144 * and O_DIRECT for no caching. */
151 145 if ((flags & BDRV_O_NOCACHE))
152   - open_flags |= O_DIRECT;
  146 + s->open_flags |= O_DIRECT;
153 147 else if (!(flags & BDRV_O_CACHE_WB))
154   - open_flags |= O_DSYNC;
  148 + s->open_flags |= O_DSYNC;
155 149  
156   - s->type = FTYPE_FILE;
157   -
158   - fd = open(filename, open_flags, 0644);
  150 + s->fd = -1;
  151 + fd = open(filename, s->open_flags, 0644);
159 152 if (fd < 0) {
160 153 ret = -errno;
161 154 if (ret == -EROFS)
... ... @@ -175,6 +168,17 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
175 168 return 0;
176 169 }
177 170  
  171 +static int raw_open(BlockDriverState *bs, const char *filename, int flags)
  172 +{
  173 + BDRVRawState *s = bs->opaque;
  174 +
  175 + s->type = FTYPE_FILE;
  176 + if (flags & BDRV_O_CREAT)
  177 + s->open_flags |= O_CREAT | O_TRUNC;
  178 +
  179 + return raw_open_common(bs, filename, flags);
  180 +}
  181 +
178 182 /* XXX: use host sector size if necessary with:
179 183 #ifdef DIOCGSECTORSIZE
180 184 {
... ... @@ -802,7 +806,7 @@ again:
802 806 if (size == 2048LL * (unsigned)-1)
803 807 size = 0;
804 808 /* XXX no disc? maybe we need to reopen... */
805   - if (size <= 0 && !reopened && cd_open(bs) >= 0) {
  809 + if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) {
806 810 reopened = 1;
807 811 goto again;
808 812 }
... ... @@ -949,12 +953,25 @@ kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex ma
949 953  
950 954 #endif
951 955  
  956 +static int hdev_probe_device(const char *filename)
  957 +{
  958 + struct stat st;
  959 +
  960 + /* allow a dedicated CD-ROM driver to match with a higher priority */
  961 + if (strstart(filename, "/dev/cdrom", NULL))
  962 + return 50;
  963 +
  964 + if (stat(filename, &st) >= 0 &&
  965 + (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
  966 + return 100;
  967 + }
  968 +
  969 + return 0;
  970 +}
  971 +
952 972 static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
953 973 {
954 974 BDRVRawState *s = bs->opaque;
955   - int fd, open_flags, ret;
956   -
957   - posix_aio_init();
958 975  
959 976 #ifdef CONFIG_COCOA
960 977 if (strstart(filename, "/dev/cdrom", NULL)) {
... ... @@ -982,67 +999,15 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
982 999 IOObjectRelease( mediaIterator );
983 1000 }
984 1001 #endif
985   - open_flags = O_BINARY;
986   - if ((flags & BDRV_O_ACCESS) == O_RDWR) {
987   - open_flags |= O_RDWR;
988   - } else {
989   - open_flags |= O_RDONLY;
990   - bs->read_only = 1;
991   - }
992   - /* Use O_DSYNC for write-through caching, no flags for write-back caching,
993   - * and O_DIRECT for no caching. */
994   - if ((flags & BDRV_O_NOCACHE))
995   - open_flags |= O_DIRECT;
996   - else if (!(flags & BDRV_O_CACHE_WB))
997   - open_flags |= O_DSYNC;
998 1002  
999 1003 s->type = FTYPE_FILE;
1000   -#if defined(__linux__)
1001   - if (strstart(filename, "/dev/cd", NULL)) {
1002   - /* open will not fail even if no CD is inserted */
1003   - open_flags |= O_NONBLOCK;
1004   - s->type = FTYPE_CD;
1005   - } else if (strstart(filename, "/dev/fd", NULL)) {
1006   - s->type = FTYPE_FD;
1007   - s->fd_open_flags = open_flags;
1008   - /* open will not fail even if no floppy is inserted */
1009   - open_flags |= O_NONBLOCK;
1010   -#ifdef CONFIG_AIO
1011   - } else if (strstart(filename, "/dev/sg", NULL)) {
  1004 +#if defined(__linux__) && defined(CONFIG_AIO)
  1005 + if (strstart(filename, "/dev/sg", NULL)) {
1012 1006 bs->sg = 1;
1013   -#endif
1014   - }
1015   -#endif
1016   -#if defined(__FreeBSD__)
1017   - if (strstart(filename, "/dev/cd", NULL) ||
1018   - strstart(filename, "/dev/acd", NULL)) {
1019   - s->type = FTYPE_CD;
1020   - s->cd_open_flags = open_flags;
1021 1007 }
1022 1008 #endif
1023   - s->fd = -1;
1024   - fd = open(filename, open_flags, 0644);
1025   - if (fd < 0) {
1026   - ret = -errno;
1027   - if (ret == -EROFS)
1028   - ret = -EACCES;
1029   - return ret;
1030   - }
1031   - s->fd = fd;
1032   -#if defined(__FreeBSD__)
1033   - /* make sure the door isnt locked at this time */
1034   - if (s->type == FTYPE_CD)
1035   - ioctl (s->fd, CDIOCALLOW);
1036   -#endif
1037   -#if defined(__linux__)
1038   - /* close fd so that we can reopen it as needed */
1039   - if (s->type == FTYPE_FD) {
1040   - close(s->fd);
1041   - s->fd = -1;
1042   - s->fd_media_changed = 1;
1043   - }
1044   -#endif
1045   - return 0;
  1009 +
  1010 + return raw_open_common(bs, filename, flags);
1046 1011 }
1047 1012  
1048 1013 #if defined(__linux__)
... ... @@ -1073,7 +1038,7 @@ static int fd_open(BlockDriverState *bs)
1073 1038 #endif
1074 1039 return -EIO;
1075 1040 }
1076   - s->fd = open(bs->filename, s->fd_open_flags);
  1041 + s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK);
1077 1042 if (s->fd < 0) {
1078 1043 s->fd_error_time = qemu_get_clock(rt_clock);
1079 1044 s->fd_got_error = 1;
... ... @@ -1095,106 +1060,7 @@ static int fd_open(BlockDriverState *bs)
1095 1060 return 0;
1096 1061 }
1097 1062  
1098   -static int raw_is_inserted(BlockDriverState *bs)
1099   -{
1100   - BDRVRawState *s = bs->opaque;
1101   - int ret;
1102   -
1103   - switch(s->type) {
1104   - case FTYPE_CD:
1105   - ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1106   - if (ret == CDS_DISC_OK)
1107   - return 1;
1108   - else
1109   - return 0;
1110   - break;
1111   - case FTYPE_FD:
1112   - ret = fd_open(bs);
1113   - return (ret >= 0);
1114   - default:
1115   - return 1;
1116   - }
1117   -}
1118   -
1119   -/* currently only used by fdc.c, but a CD version would be good too */
1120   -static int raw_media_changed(BlockDriverState *bs)
1121   -{
1122   - BDRVRawState *s = bs->opaque;
1123   -
1124   - switch(s->type) {
1125   - case FTYPE_FD:
1126   - {
1127   - int ret;
1128   - /* XXX: we do not have a true media changed indication. It
1129   - does not work if the floppy is changed without trying
1130   - to read it */
1131   - fd_open(bs);
1132   - ret = s->fd_media_changed;
1133   - s->fd_media_changed = 0;
1134   -#ifdef DEBUG_FLOPPY
1135   - printf("Floppy changed=%d\n", ret);
1136   -#endif
1137   - return ret;
1138   - }
1139   - default:
1140   - return -ENOTSUP;
1141   - }
1142   -}
1143   -
1144   -static int raw_eject(BlockDriverState *bs, int eject_flag)
1145   -{
1146   - BDRVRawState *s = bs->opaque;
1147   -
1148   - switch(s->type) {
1149   - case FTYPE_CD:
1150   - if (eject_flag) {
1151   - if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
1152   - perror("CDROMEJECT");
1153   - } else {
1154   - if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
1155   - perror("CDROMEJECT");
1156   - }
1157   - break;
1158   - case FTYPE_FD:
1159   - {
1160   - int fd;
1161   - if (s->fd >= 0) {
1162   - close(s->fd);
1163   - s->fd = -1;
1164   - }
1165   - fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
1166   - if (fd >= 0) {
1167   - if (ioctl(fd, FDEJECT, 0) < 0)
1168   - perror("FDEJECT");
1169   - close(fd);
1170   - }
1171   - }
1172   - break;
1173   - default:
1174   - return -ENOTSUP;
1175   - }
1176   - return 0;
1177   -}
1178   -
1179   -static int raw_set_locked(BlockDriverState *bs, int locked)
1180   -{
1181   - BDRVRawState *s = bs->opaque;
1182   -
1183   - switch(s->type) {
1184   - case FTYPE_CD:
1185   - if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
1186   - /* Note: an error can happen if the distribution automatically
1187   - mounts the CD-ROM */
1188   - // perror("CDROM_LOCKDOOR");
1189   - }
1190   - break;
1191   - default:
1192   - return -ENOTSUP;
1193   - }
1194   - return 0;
1195   -}
1196   -
1197   -static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
  1063 +static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1198 1064 {
1199 1065 BDRVRawState *s = bs->opaque;
1200 1066  
... ... @@ -1202,7 +1068,7 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1202 1068 }
1203 1069  
1204 1070 #ifdef CONFIG_AIO
1205   -static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
  1071 +static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
1206 1072 unsigned long int req, void *buf,
1207 1073 BlockDriverCompletionFunc *cb, void *opaque)
1208 1074 {
... ... @@ -1235,7 +1101,6 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
1235 1101 #endif
1236 1102  
1237 1103 #elif defined(__FreeBSD__)
1238   -
1239 1104 static int fd_open(BlockDriverState *bs)
1240 1105 {
1241 1106 BDRVRawState *s = bs->opaque;
... ... @@ -1245,207 +1110,392 @@ static int fd_open(BlockDriverState *bs)
1245 1110 return 0;
1246 1111 return -EIO;
1247 1112 }
  1113 +#else /* !linux && !FreeBSD */
1248 1114  
1249   -static int cd_open(BlockDriverState *bs)
  1115 +static int fd_open(BlockDriverState *bs)
  1116 +{
  1117 + return 0;
  1118 +}
  1119 +
  1120 +#endif /* !linux && !FreeBSD */
  1121 +
  1122 +static int hdev_create(const char *filename, QEMUOptionParameter *options)
1250 1123 {
1251   -#if defined(__FreeBSD__)
1252   - BDRVRawState *s = bs->opaque;
1253 1124 int fd;
  1125 + int ret = 0;
  1126 + struct stat stat_buf;
  1127 + int64_t total_size = 0;
1254 1128  
1255   - switch(s->type) {
1256   - case FTYPE_CD:
1257   - /* XXX force reread of possibly changed/newly loaded disc,
1258   - * FreeBSD seems to not notice sometimes... */
1259   - if (s->fd >= 0)
1260   - close (s->fd);
1261   - fd = open(bs->filename, s->cd_open_flags, 0644);
1262   - if (fd < 0) {
1263   - s->fd = -1;
1264   - return -EIO;
  1129 + /* Read out options */
  1130 + while (options && options->name) {
  1131 + if (!strcmp(options->name, "size")) {
  1132 + total_size = options->value.n / 512;
1265 1133 }
1266   - s->fd = fd;
1267   - /* make sure the door isnt locked at this time */
1268   - ioctl (s->fd, CDIOCALLOW);
  1134 + options++;
1269 1135 }
  1136 +
  1137 + fd = open(filename, O_WRONLY | O_BINARY);
  1138 + if (fd < 0)
  1139 + return -EIO;
  1140 +
  1141 + if (fstat(fd, &stat_buf) < 0)
  1142 + ret = -EIO;
  1143 + else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
  1144 + ret = -EIO;
  1145 + else if (lseek(fd, 0, SEEK_END) < total_size * 512)
  1146 + ret = -ENOSPC;
  1147 +
  1148 + close(fd);
  1149 + return ret;
  1150 +}
  1151 +
  1152 +static BlockDriver bdrv_host_device = {
  1153 + .format_name = "host_device",
  1154 + .instance_size = sizeof(BDRVRawState),
  1155 + .bdrv_probe_device = hdev_probe_device,
  1156 + .bdrv_open = hdev_open,
  1157 + .bdrv_close = raw_close,
  1158 + .bdrv_create = hdev_create,
  1159 + .bdrv_flush = raw_flush,
  1160 +
  1161 +#ifdef CONFIG_AIO
  1162 + .bdrv_aio_readv = raw_aio_readv,
  1163 + .bdrv_aio_writev = raw_aio_writev,
1270 1164 #endif
  1165 +
  1166 + .bdrv_read = raw_read,
  1167 + .bdrv_write = raw_write,
  1168 + .bdrv_getlength = raw_getlength,
  1169 +
  1170 + /* generic scsi device */
  1171 +#ifdef __linux__
  1172 + .bdrv_ioctl = hdev_ioctl,
  1173 +#ifdef CONFIG_AIO
  1174 + .bdrv_aio_ioctl = hdev_aio_ioctl,
  1175 +#endif
  1176 +#endif
  1177 +};
  1178 +
  1179 +#ifdef __linux__
  1180 +static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
  1181 +{
  1182 + BDRVRawState *s = bs->opaque;
  1183 + int ret;
  1184 +
  1185 + posix_aio_init();
  1186 +
  1187 + s->type = FTYPE_FD;
  1188 + /* open will not fail even if no floppy is inserted */
  1189 + s->open_flags |= O_NONBLOCK;
  1190 +
  1191 + ret = raw_open_common(bs, filename, flags);
  1192 + if (ret)
  1193 + return ret;
  1194 +
  1195 + /* close fd so that we can reopen it as needed */
  1196 + close(s->fd);
  1197 + s->fd = -1;
  1198 + s->fd_media_changed = 1;
  1199 +
1271 1200 return 0;
1272 1201 }
1273 1202  
1274   -static int raw_is_inserted(BlockDriverState *bs)
  1203 +static int floppy_probe_device(const char *filename)
1275 1204 {
1276   - BDRVRawState *s = bs->opaque;
  1205 + if (strstart(filename, "/dev/fd", NULL))
  1206 + return 100;
  1207 + return 0;
  1208 +}
1277 1209  
1278   - switch(s->type) {
1279   - case FTYPE_CD:
1280   - return (raw_getlength(bs) > 0);
1281   - case FTYPE_FD:
1282   - /* XXX handle this */
1283   - /* FALLTHRU */
1284   - default:
1285   - return 1;
1286   - }
  1210 +
  1211 +static int floppy_is_inserted(BlockDriverState *bs)
  1212 +{
  1213 + return fd_open(bs) >= 0;
1287 1214 }
1288 1215  
1289   -static int raw_media_changed(BlockDriverState *bs)
  1216 +static int floppy_media_changed(BlockDriverState *bs)
1290 1217 {
1291   - return -ENOTSUP;
  1218 + BDRVRawState *s = bs->opaque;
  1219 + int ret;
  1220 +
  1221 + /*
  1222 + * XXX: we do not have a true media changed indication.
  1223 + * It does not work if the floppy is changed without trying to read it.
  1224 + */
  1225 + fd_open(bs);
  1226 + ret = s->fd_media_changed;
  1227 + s->fd_media_changed = 0;
  1228 +#ifdef DEBUG_FLOPPY
  1229 + printf("Floppy changed=%d\n", ret);
  1230 +#endif
  1231 + return ret;
1292 1232 }
1293 1233  
1294   -static int raw_eject(BlockDriverState *bs, int eject_flag)
  1234 +static int floppy_eject(BlockDriverState *bs, int eject_flag)
1295 1235 {
1296 1236 BDRVRawState *s = bs->opaque;
  1237 + int fd;
1297 1238  
1298   - switch(s->type) {
1299   - case FTYPE_CD:
1300   - if (s->fd < 0)
1301   - return -ENOTSUP;
1302   - (void) ioctl (s->fd, CDIOCALLOW);
1303   - if (eject_flag) {
1304   - if (ioctl (s->fd, CDIOCEJECT) < 0)
1305   - perror("CDIOCEJECT");
1306   - } else {
1307   - if (ioctl (s->fd, CDIOCCLOSE) < 0)
1308   - perror("CDIOCCLOSE");
1309   - }
1310   - if (cd_open(bs) < 0)
1311   - return -ENOTSUP;
1312   - break;
1313   - case FTYPE_FD:
1314   - /* XXX handle this */
1315   - /* FALLTHRU */
1316   - default:
1317   - return -ENOTSUP;
  1239 + if (s->fd >= 0) {
  1240 + close(s->fd);
  1241 + s->fd = -1;
  1242 + }
  1243 + fd = open(bs->filename, s->open_flags | O_NONBLOCK);
  1244 + if (fd >= 0) {
  1245 + if (ioctl(fd, FDEJECT, 0) < 0)
  1246 + perror("FDEJECT");
  1247 + close(fd);
1318 1248 }
  1249 +
1319 1250 return 0;
1320 1251 }
1321 1252  
1322   -static int raw_set_locked(BlockDriverState *bs, int locked)
  1253 +static BlockDriver bdrv_host_floppy = {
  1254 + .format_name = "host_floppy",
  1255 + .instance_size = sizeof(BDRVRawState),
  1256 + .bdrv_probe_device = floppy_probe_device,
  1257 + .bdrv_open = floppy_open,
  1258 + .bdrv_close = raw_close,
  1259 + .bdrv_create = hdev_create,
  1260 + .bdrv_flush = raw_flush,
  1261 +
  1262 +#ifdef CONFIG_AIO
  1263 + .bdrv_aio_readv = raw_aio_readv,
  1264 + .bdrv_aio_writev = raw_aio_writev,
  1265 +#endif
  1266 +
  1267 + .bdrv_read = raw_read,
  1268 + .bdrv_write = raw_write,
  1269 + .bdrv_getlength = raw_getlength,
  1270 +
  1271 + /* removable device support */
  1272 + .bdrv_is_inserted = floppy_is_inserted,
  1273 + .bdrv_media_changed = floppy_media_changed,
  1274 + .bdrv_eject = floppy_eject,
  1275 +};
  1276 +
  1277 +static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1323 1278 {
1324 1279 BDRVRawState *s = bs->opaque;
1325 1280  
1326   - switch(s->type) {
1327   - case FTYPE_CD:
1328   - if (s->fd < 0)
1329   - return -ENOTSUP;
1330   - if (ioctl (s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
1331   - /* Note: an error can happen if the distribution automatically
1332   - mounts the CD-ROM */
1333   - // perror("CDROM_LOCKDOOR");
1334   - }
1335   - break;
1336   - default:
1337   - return -ENOTSUP;
1338   - }
1339   - return 0;
  1281 + /* open will not fail even if no CD is inserted */
  1282 + s->open_flags |= O_NONBLOCK;
  1283 + s->type = FTYPE_CD;
  1284 +
  1285 + return raw_open_common(bs, filename, flags);
1340 1286 }
1341 1287  
1342   -static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
  1288 +static int cdrom_probe_device(const char *filename)
1343 1289 {
1344   - return -ENOTSUP;
  1290 + if (strstart(filename, "/dev/cd", NULL))
  1291 + return 100;
  1292 + return 0;
1345 1293 }
1346   -#else /* !linux && !FreeBSD */
1347 1294  
1348   -static int fd_open(BlockDriverState *bs)
  1295 +static int cdrom_is_inserted(BlockDriverState *bs)
1349 1296 {
  1297 + BDRVRawState *s = bs->opaque;
  1298 + int ret;
  1299 +
  1300 + ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
  1301 + if (ret == CDS_DISC_OK)
  1302 + return 1;
1350 1303 return 0;
1351 1304 }
1352 1305  
1353   -static int raw_is_inserted(BlockDriverState *bs)
  1306 +static int cdrom_eject(BlockDriverState *bs, int eject_flag)
1354 1307 {
1355   - return 1;
  1308 + BDRVRawState *s = bs->opaque;
  1309 +
  1310 + if (eject_flag) {
  1311 + if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
  1312 + perror("CDROMEJECT");
  1313 + } else {
  1314 + if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
  1315 + perror("CDROMEJECT");
  1316 + }
  1317 +
  1318 + return 0;
1356 1319 }
1357 1320  
1358   -static int raw_media_changed(BlockDriverState *bs)
  1321 +static int cdrom_set_locked(BlockDriverState *bs, int locked)
1359 1322 {
1360   - return -ENOTSUP;
  1323 + BDRVRawState *s = bs->opaque;
  1324 +
  1325 + if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
  1326 + /*
  1327 + * Note: an error can happen if the distribution automatically
  1328 + * mounts the CD-ROM
  1329 + */
  1330 + /* perror("CDROM_LOCKDOOR"); */
  1331 + }
  1332 +
  1333 + return 0;
1361 1334 }
1362 1335  
1363   -static int raw_eject(BlockDriverState *bs, int eject_flag)
  1336 +static BlockDriver bdrv_host_cdrom = {
  1337 + .format_name = "host_cdrom",
  1338 + .instance_size = sizeof(BDRVRawState),
  1339 + .bdrv_probe_device = cdrom_probe_device,
  1340 + .bdrv_open = cdrom_open,
  1341 + .bdrv_close = raw_close,
  1342 + .bdrv_create = hdev_create,
  1343 + .bdrv_flush = raw_flush,
  1344 +
  1345 +#ifdef CONFIG_AIO
  1346 + .bdrv_aio_readv = raw_aio_readv,
  1347 + .bdrv_aio_writev = raw_aio_writev,
  1348 +#endif
  1349 +
  1350 + .bdrv_read = raw_read,
  1351 + .bdrv_write = raw_write,
  1352 + .bdrv_getlength = raw_getlength,
  1353 +
  1354 + /* removable device support */
  1355 + .bdrv_is_inserted = cdrom_is_inserted,
  1356 + .bdrv_eject = cdrom_eject,
  1357 + .bdrv_set_locked = cdrom_set_locked,
  1358 +
  1359 + /* generic scsi device */
  1360 + .bdrv_ioctl = hdev_ioctl,
  1361 +#ifdef CONFIG_AIO
  1362 + .bdrv_aio_ioctl = hdev_aio_ioctl,
  1363 +#endif
  1364 +};
  1365 +#endif /* __linux__ */
  1366 +
  1367 +#ifdef __FreeBSD__
  1368 +static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1364 1369 {
1365   - return -ENOTSUP;
  1370 + BDRVRawState *s = bs->opaque;
  1371 + int ret;
  1372 +
  1373 + s->type = FTYPE_CD;
  1374 +
  1375 + ret = raw_open_common(bs, filename, flags);
  1376 + if (ret)
  1377 + return ret;
  1378 +
  1379 + /* make sure the door isnt locked at this time */
  1380 + ioctl(s->fd, CDIOCALLOW);
  1381 + return 0;
1366 1382 }
1367 1383  
1368   -static int raw_set_locked(BlockDriverState *bs, int locked)
  1384 +static int cdrom_probe_device(const char *filename)
1369 1385 {
1370   - return -ENOTSUP;
  1386 + if (strstart(filename, "/dev/cd", NULL) ||
  1387 + strstart(filename, "/dev/acd", NULL))
  1388 + return 100;
  1389 + return 0;
1371 1390 }
1372 1391  
1373   -static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
  1392 +static int cdrom_reopen(BlockDriverState *bs)
1374 1393 {
1375   - return -ENOTSUP;
  1394 + BDRVRawState *s = bs->opaque;
  1395 + int fd;
  1396 +
  1397 + /*
  1398 + * Force reread of possibly changed/newly loaded disc,
  1399 + * FreeBSD seems to not notice sometimes...
  1400 + */
  1401 + if (s->fd >= 0)
  1402 + close(s->fd);
  1403 + fd = open(bs->filename, s->open_flags, 0644);
  1404 + if (fd < 0) {
  1405 + s->fd = -1;
  1406 + return -EIO;
  1407 + }
  1408 + s->fd = fd;
  1409 +
  1410 + /* make sure the door isnt locked at this time */
  1411 + ioctl(s->fd, CDIOCALLOW);
  1412 + return 0;
1376 1413 }
1377 1414  
1378   -static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
1379   - unsigned long int req, void *buf,
1380   - BlockDriverCompletionFunc *cb, void *opaque)
  1415 +static int cdrom_is_inserted(BlockDriverState *bs)
1381 1416 {
1382   - return NULL;
  1417 + return raw_getlength(bs) > 0;
1383 1418 }
1384   -#endif /* !linux && !FreeBSD */
1385 1419  
1386   -static int hdev_create(const char *filename, QEMUOptionParameter *options)
  1420 +static int cdrom_eject(BlockDriverState *bs, int eject_flag)
1387 1421 {
1388   - int fd;
1389   - int ret = 0;
1390   - struct stat stat_buf;
1391   - int64_t total_size = 0;
  1422 + BDRVRawState *s = bs->opaque;
1392 1423  
1393   - /* Read out options */
1394   - while (options && options->name) {
1395   - if (!strcmp(options->name, "size")) {
1396   - total_size = options->value.n / 512;
1397   - }
1398   - options++;
  1424 + if (s->fd < 0)
  1425 + return -ENOTSUP;
  1426 +
  1427 + (void) ioctl(s->fd, CDIOCALLOW);
  1428 +
  1429 + if (eject_flag) {
  1430 + if (ioctl(s->fd, CDIOCEJECT) < 0)
  1431 + perror("CDIOCEJECT");
  1432 + } else {
  1433 + if (ioctl(s->fd, CDIOCCLOSE) < 0)
  1434 + perror("CDIOCCLOSE");
1399 1435 }
1400 1436  
1401   - fd = open(filename, O_WRONLY | O_BINARY);
1402   - if (fd < 0)
1403   - return -EIO;
  1437 + if (cdrom_reopen(bs) < 0)
  1438 + return -ENOTSUP;
  1439 + return 0;
  1440 +}
1404 1441  
1405   - if (fstat(fd, &stat_buf) < 0)
1406   - ret = -EIO;
1407   - else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
1408   - ret = -EIO;
1409   - else if (lseek(fd, 0, SEEK_END) < total_size * 512)
1410   - ret = -ENOSPC;
  1442 +static int cdrom_set_locked(BlockDriverState *bs, int locked)
  1443 +{
  1444 + BDRVRawState *s = bs->opaque;
1411 1445  
1412   - close(fd);
1413   - return ret;
  1446 + if (s->fd < 0)
  1447 + return -ENOTSUP;
  1448 + if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
  1449 + /*
  1450 + * Note: an error can happen if the distribution automatically
  1451 + * mounts the CD-ROM
  1452 + */
  1453 + /* perror("CDROM_LOCKDOOR"); */
  1454 + }
  1455 +
  1456 + return 0;
1414 1457 }
1415 1458  
1416   -static BlockDriver bdrv_host_device = {
1417   - .format_name = "host_device",
1418   - .instance_size = sizeof(BDRVRawState),
1419   - .bdrv_open = hdev_open,
1420   - .bdrv_close = raw_close,
  1459 +static BlockDriver bdrv_host_cdrom = {
  1460 + .format_name = "host_cdrom",
  1461 + .instance_size = sizeof(BDRVRawState),
  1462 + .bdrv_probe_device = cdrom_probe_device,
  1463 + .bdrv_open = cdrom_open,
  1464 + .bdrv_close = raw_close,
1421 1465 .bdrv_create = hdev_create,
1422   - .bdrv_flush = raw_flush,
  1466 + .bdrv_flush = raw_flush,
1423 1467  
1424 1468 #ifdef CONFIG_AIO
1425   - .bdrv_aio_readv = raw_aio_readv,
1426   - .bdrv_aio_writev = raw_aio_writev,
  1469 + .bdrv_aio_readv = raw_aio_readv,
  1470 + .bdrv_aio_writev = raw_aio_writev,
1427 1471 #endif
1428 1472  
1429 1473 .bdrv_read = raw_read,
1430 1474 .bdrv_write = raw_write,
1431   - .bdrv_getlength = raw_getlength,
  1475 + .bdrv_getlength = raw_getlength,
1432 1476  
1433 1477 /* removable device support */
1434   - .bdrv_is_inserted = raw_is_inserted,
1435   - .bdrv_media_changed = raw_media_changed,
1436   - .bdrv_eject = raw_eject,
1437   - .bdrv_set_locked = raw_set_locked,
1438   - /* generic scsi device */
1439   - .bdrv_ioctl = raw_ioctl,
1440   -#ifdef CONFIG_AIO
1441   - .bdrv_aio_ioctl = raw_aio_ioctl,
1442   -#endif
  1478 + .bdrv_is_inserted = cdrom_is_inserted,
  1479 + .bdrv_eject = cdrom_eject,
  1480 + .bdrv_set_locked = cdrom_set_locked,
1443 1481 };
  1482 +#endif /* __FreeBSD__ */
1444 1483  
1445 1484 static void bdrv_raw_init(void)
1446 1485 {
  1486 + /*
  1487 + * Register all the drivers. Note that order is important, the driver
  1488 + * registered last will get probed first.
  1489 + */
1447 1490 bdrv_register(&bdrv_raw);
1448 1491 bdrv_register(&bdrv_host_device);
  1492 +#ifdef __linux__
  1493 + bdrv_register(&bdrv_host_floppy);
  1494 + bdrv_register(&bdrv_host_cdrom);
  1495 +#endif
  1496 +#ifdef __FreeBSD__
  1497 + bdrv_register(&bdrv_host_cdrom);
  1498 +#endif
1449 1499 }
1450 1500  
1451 1501 block_init(bdrv_raw_init);
... ...
block/raw-win32.c
... ... @@ -306,6 +306,15 @@ static int find_device_type(BlockDriverState *bs, const char *filename)
306 306 }
307 307 }
308 308  
  309 +static int hdev_probe_device(const char *filename)
  310 +{
  311 + if (strstart(filename, "/dev/cdrom", NULL))
  312 + return 100;
  313 + if (is_windows_drive(filename))
  314 + return 100;
  315 + return 0;
  316 +}
  317 +
309 318 static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
310 319 {
311 320 BDRVRawState *s = bs->opaque;
... ... @@ -391,6 +400,7 @@ static int raw_set_locked(BlockDriverState *bs, int locked)
391 400 static BlockDriver bdrv_host_device = {
392 401 .format_name = "host_device",
393 402 .instance_size = sizeof(BDRVRawState),
  403 + .bdrv_probe_device = hdev_probe_device,
394 404 .bdrv_open = hdev_open,
395 405 .bdrv_close = raw_close,
396 406 .bdrv_flush = raw_flush,
... ...
block_int.h
... ... @@ -48,6 +48,7 @@ struct BlockDriver {
48 48 const char *format_name;
49 49 int instance_size;
50 50 int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
  51 + int (*bdrv_probe_device)(const char *filename);
51 52 int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
52 53 int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
53 54 uint8_t *buf, int nb_sectors);
... ... @@ -177,4 +178,8 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size);
177 178  
178 179 extern BlockDriverState *bdrv_first;
179 180  
  181 +#ifdef _WIN32
  182 +int is_windows_drive(const char *filename);
  183 +#endif
  184 +
180 185 #endif /* BLOCK_INT_H */
... ...
qemu-aio.h
... ... @@ -24,9 +24,10 @@ typedef int (AioFlushHandler)(void *opaque);
24 24 * outstanding AIO operations have been completed or cancelled. */
25 25 void qemu_aio_flush(void);
26 26  
27   -/* Wait for a single AIO completion to occur. This function will until a
28   - * single AIO opeartion has completed. It is intended to be used as a looping
29   - * primative when simulating synchronous IO based on asynchronous IO. */
  27 +/* Wait for a single AIO completion to occur. This function will wait
  28 + * until a single AIO event has completed and it will ensure something
  29 + * has moved before returning. This can issue new pending aio as
  30 + * result of executing I/O completion or bh callbacks. */
30 31 void qemu_aio_wait(void);
31 32  
32 33 /* Register a file descriptor and associated callbacks. Behaves very similarly
... ...