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,11 +103,15 @@ void qemu_aio_flush(void)
103 do { 103 do {
104 ret = 0; 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 LIST_FOREACH(node, &aio_handlers, node) { 112 LIST_FOREACH(node, &aio_handlers, node) {
107 ret |= node->io_flush(node->opaque); 113 ret |= node->io_flush(node->opaque);
108 } 114 }
109 -  
110 - qemu_aio_wait();  
111 } while (ret > 0); 115 } while (ret > 0);
112 } 116 }
113 117
@@ -209,7 +209,7 @@ static int is_windows_drive_prefix(const char *filename) @@ -209,7 +209,7 @@ static int is_windows_drive_prefix(const char *filename)
209 filename[1] == ':'); 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 if (is_windows_drive_prefix(filename) && 214 if (is_windows_drive_prefix(filename) &&
215 filename[2] == '\0') 215 filename[2] == '\0')
@@ -249,8 +249,28 @@ static BlockDriver *find_protocol(const char *filename) @@ -249,8 +249,28 @@ static BlockDriver *find_protocol(const char *filename)
249 return NULL; 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 static BlockDriver *find_image_format(const char *filename) 274 static BlockDriver *find_image_format(const char *filename)
255 { 275 {
256 int ret, score, score_max; 276 int ret, score, score_max;
@@ -258,23 +278,6 @@ static BlockDriver *find_image_format(const char *filename) @@ -258,23 +278,6 @@ static BlockDriver *find_image_format(const char *filename)
258 uint8_t buf[2048]; 278 uint8_t buf[2048];
259 BlockDriverState *bs; 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 drv = find_protocol(filename); 281 drv = find_protocol(filename);
279 /* no need to test disk image formats for vvfat */ 282 /* no need to test disk image formats for vvfat */
280 if (drv && strcmp(drv->format_name, "vvfat") == 0) 283 if (drv && strcmp(drv->format_name, "vvfat") == 0)
@@ -394,7 +397,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, @@ -394,7 +397,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
394 if (flags & BDRV_O_FILE) { 397 if (flags & BDRV_O_FILE) {
395 drv = find_protocol(filename); 398 drv = find_protocol(filename);
396 } else if (!drv) { 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 if (!drv) { 405 if (!drv) {
400 ret = -ENOENT; 406 ret = -ENOENT;
block/raw-posix.c
@@ -103,17 +103,14 @@ typedef struct BDRVRawState { @@ -103,17 +103,14 @@ typedef struct BDRVRawState {
103 int fd; 103 int fd;
104 int type; 104 int type;
105 unsigned int lseek_err_cnt; 105 unsigned int lseek_err_cnt;
  106 + int open_flags;
106 #if defined(__linux__) 107 #if defined(__linux__)
107 /* linux floppy specific */ 108 /* linux floppy specific */
108 - int fd_open_flags;  
109 int64_t fd_open_time; 109 int64_t fd_open_time;
110 int64_t fd_error_time; 110 int64_t fd_error_time;
111 int fd_got_error; 111 int fd_got_error;
112 int fd_media_changed; 112 int fd_media_changed;
113 #endif 113 #endif
114 -#if defined(__FreeBSD__)  
115 - int cd_open_flags;  
116 -#endif  
117 uint8_t* aligned_buf; 114 uint8_t* aligned_buf;
118 } BDRVRawState; 115 } BDRVRawState;
119 116
@@ -122,40 +119,36 @@ static int posix_aio_init(void); @@ -122,40 +119,36 @@ static int posix_aio_init(void);
122 static int fd_open(BlockDriverState *bs); 119 static int fd_open(BlockDriverState *bs);
123 120
124 #if defined(__FreeBSD__) 121 #if defined(__FreeBSD__)
125 -static int cd_open(BlockDriverState *bs); 122 +static int cdrom_reopen(BlockDriverState *bs);
126 #endif 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 BDRVRawState *s = bs->opaque; 128 BDRVRawState *s = bs->opaque;
133 - int fd, open_flags, ret; 129 + int fd, ret;
134 130
135 posix_aio_init(); 131 posix_aio_init();
136 132
137 s->lseek_err_cnt = 0; 133 s->lseek_err_cnt = 0;
138 134
139 - open_flags = O_BINARY; 135 + s->open_flags |= O_BINARY;
140 if ((flags & BDRV_O_ACCESS) == O_RDWR) { 136 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
141 - open_flags |= O_RDWR; 137 + s->open_flags |= O_RDWR;
142 } else { 138 } else {
143 - open_flags |= O_RDONLY; 139 + s->open_flags |= O_RDONLY;
144 bs->read_only = 1; 140 bs->read_only = 1;
145 } 141 }
146 - if (flags & BDRV_O_CREAT)  
147 - open_flags |= O_CREAT | O_TRUNC;  
148 142
149 /* Use O_DSYNC for write-through caching, no flags for write-back caching, 143 /* Use O_DSYNC for write-through caching, no flags for write-back caching,
150 * and O_DIRECT for no caching. */ 144 * and O_DIRECT for no caching. */
151 if ((flags & BDRV_O_NOCACHE)) 145 if ((flags & BDRV_O_NOCACHE))
152 - open_flags |= O_DIRECT; 146 + s->open_flags |= O_DIRECT;
153 else if (!(flags & BDRV_O_CACHE_WB)) 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 if (fd < 0) { 152 if (fd < 0) {
160 ret = -errno; 153 ret = -errno;
161 if (ret == -EROFS) 154 if (ret == -EROFS)
@@ -175,6 +168,17 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) @@ -175,6 +168,17 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
175 return 0; 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 /* XXX: use host sector size if necessary with: 182 /* XXX: use host sector size if necessary with:
179 #ifdef DIOCGSECTORSIZE 183 #ifdef DIOCGSECTORSIZE
180 { 184 {
@@ -802,7 +806,7 @@ again: @@ -802,7 +806,7 @@ again:
802 if (size == 2048LL * (unsigned)-1) 806 if (size == 2048LL * (unsigned)-1)
803 size = 0; 807 size = 0;
804 /* XXX no disc? maybe we need to reopen... */ 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 reopened = 1; 810 reopened = 1;
807 goto again; 811 goto again;
808 } 812 }
@@ -949,12 +953,25 @@ kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex ma @@ -949,12 +953,25 @@ kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex ma
949 953
950 #endif 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 static int hdev_open(BlockDriverState *bs, const char *filename, int flags) 972 static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
953 { 973 {
954 BDRVRawState *s = bs->opaque; 974 BDRVRawState *s = bs->opaque;
955 - int fd, open_flags, ret;  
956 -  
957 - posix_aio_init();  
958 975
959 #ifdef CONFIG_COCOA 976 #ifdef CONFIG_COCOA
960 if (strstart(filename, "/dev/cdrom", NULL)) { 977 if (strstart(filename, "/dev/cdrom", NULL)) {
@@ -982,67 +999,15 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) @@ -982,67 +999,15 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
982 IOObjectRelease( mediaIterator ); 999 IOObjectRelease( mediaIterator );
983 } 1000 }
984 #endif 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 s->type = FTYPE_FILE; 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 bs->sg = 1; 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 #endif 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 #if defined(__linux__) 1013 #if defined(__linux__)
@@ -1073,7 +1038,7 @@ static int fd_open(BlockDriverState *bs) @@ -1073,7 +1038,7 @@ static int fd_open(BlockDriverState *bs)
1073 #endif 1038 #endif
1074 return -EIO; 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 if (s->fd < 0) { 1042 if (s->fd < 0) {
1078 s->fd_error_time = qemu_get_clock(rt_clock); 1043 s->fd_error_time = qemu_get_clock(rt_clock);
1079 s->fd_got_error = 1; 1044 s->fd_got_error = 1;
@@ -1095,106 +1060,7 @@ static int fd_open(BlockDriverState *bs) @@ -1095,106 +1060,7 @@ static int fd_open(BlockDriverState *bs)
1095 return 0; 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 BDRVRawState *s = bs->opaque; 1065 BDRVRawState *s = bs->opaque;
1200 1066
@@ -1202,7 +1068,7 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) @@ -1202,7 +1068,7 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1202 } 1068 }
1203 1069
1204 #ifdef CONFIG_AIO 1070 #ifdef CONFIG_AIO
1205 -static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, 1071 +static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
1206 unsigned long int req, void *buf, 1072 unsigned long int req, void *buf,
1207 BlockDriverCompletionFunc *cb, void *opaque) 1073 BlockDriverCompletionFunc *cb, void *opaque)
1208 { 1074 {
@@ -1235,7 +1101,6 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, @@ -1235,7 +1101,6 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
1235 #endif 1101 #endif
1236 1102
1237 #elif defined(__FreeBSD__) 1103 #elif defined(__FreeBSD__)
1238 -  
1239 static int fd_open(BlockDriverState *bs) 1104 static int fd_open(BlockDriverState *bs)
1240 { 1105 {
1241 BDRVRawState *s = bs->opaque; 1106 BDRVRawState *s = bs->opaque;
@@ -1245,207 +1110,392 @@ static int fd_open(BlockDriverState *bs) @@ -1245,207 +1110,392 @@ static int fd_open(BlockDriverState *bs)
1245 return 0; 1110 return 0;
1246 return -EIO; 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 int fd; 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 #endif 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 return 0; 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 BDRVRawState *s = bs->opaque; 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 return 0; 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 BDRVRawState *s = bs->opaque; 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 return 0; 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 .bdrv_create = hdev_create, 1465 .bdrv_create = hdev_create,
1422 - .bdrv_flush = raw_flush, 1466 + .bdrv_flush = raw_flush,
1423 1467
1424 #ifdef CONFIG_AIO 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 #endif 1471 #endif
1428 1472
1429 .bdrv_read = raw_read, 1473 .bdrv_read = raw_read,
1430 .bdrv_write = raw_write, 1474 .bdrv_write = raw_write,
1431 - .bdrv_getlength = raw_getlength, 1475 + .bdrv_getlength = raw_getlength,
1432 1476
1433 /* removable device support */ 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 static void bdrv_raw_init(void) 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 bdrv_register(&bdrv_raw); 1490 bdrv_register(&bdrv_raw);
1448 bdrv_register(&bdrv_host_device); 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 block_init(bdrv_raw_init); 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,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 static int hdev_open(BlockDriverState *bs, const char *filename, int flags) 318 static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
310 { 319 {
311 BDRVRawState *s = bs->opaque; 320 BDRVRawState *s = bs->opaque;
@@ -391,6 +400,7 @@ static int raw_set_locked(BlockDriverState *bs, int locked) @@ -391,6 +400,7 @@ static int raw_set_locked(BlockDriverState *bs, int locked)
391 static BlockDriver bdrv_host_device = { 400 static BlockDriver bdrv_host_device = {
392 .format_name = "host_device", 401 .format_name = "host_device",
393 .instance_size = sizeof(BDRVRawState), 402 .instance_size = sizeof(BDRVRawState),
  403 + .bdrv_probe_device = hdev_probe_device,
394 .bdrv_open = hdev_open, 404 .bdrv_open = hdev_open,
395 .bdrv_close = raw_close, 405 .bdrv_close = raw_close,
396 .bdrv_flush = raw_flush, 406 .bdrv_flush = raw_flush,
block_int.h
@@ -48,6 +48,7 @@ struct BlockDriver { @@ -48,6 +48,7 @@ struct BlockDriver {
48 const char *format_name; 48 const char *format_name;
49 int instance_size; 49 int instance_size;
50 int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename); 50 int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
  51 + int (*bdrv_probe_device)(const char *filename);
51 int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags); 52 int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
52 int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, 53 int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
53 uint8_t *buf, int nb_sectors); 54 uint8_t *buf, int nb_sectors);
@@ -177,4 +178,8 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size); @@ -177,4 +178,8 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size);
177 178
178 extern BlockDriverState *bdrv_first; 179 extern BlockDriverState *bdrv_first;
179 180
  181 +#ifdef _WIN32
  182 +int is_windows_drive(const char *filename);
  183 +#endif
  184 +
180 #endif /* BLOCK_INT_H */ 185 #endif /* BLOCK_INT_H */
qemu-aio.h
@@ -24,9 +24,10 @@ typedef int (AioFlushHandler)(void *opaque); @@ -24,9 +24,10 @@ typedef int (AioFlushHandler)(void *opaque);
24 * outstanding AIO operations have been completed or cancelled. */ 24 * outstanding AIO operations have been completed or cancelled. */
25 void qemu_aio_flush(void); 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 void qemu_aio_wait(void); 31 void qemu_aio_wait(void);
31 32
32 /* Register a file descriptor and associated callbacks. Behaves very similarly 33 /* Register a file descriptor and associated callbacks. Behaves very similarly