xref: /openbmc/qemu/block.c (revision 3f4cb3d37fb74db3580029624c8acd83dd5f4787)
1fc01f7e7Sbellard /*
2fc01f7e7Sbellard  * QEMU System Emulator block driver
3fc01f7e7Sbellard  *
4fc01f7e7Sbellard  * Copyright (c) 2003 Fabrice Bellard
5fc01f7e7Sbellard  *
6fc01f7e7Sbellard  * Permission is hereby granted, free of charge, to any person obtaining a copy
7fc01f7e7Sbellard  * of this software and associated documentation files (the "Software"), to deal
8fc01f7e7Sbellard  * in the Software without restriction, including without limitation the rights
9fc01f7e7Sbellard  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10fc01f7e7Sbellard  * copies of the Software, and to permit persons to whom the Software is
11fc01f7e7Sbellard  * furnished to do so, subject to the following conditions:
12fc01f7e7Sbellard  *
13fc01f7e7Sbellard  * The above copyright notice and this permission notice shall be included in
14fc01f7e7Sbellard  * all copies or substantial portions of the Software.
15fc01f7e7Sbellard  *
16fc01f7e7Sbellard  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17fc01f7e7Sbellard  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18fc01f7e7Sbellard  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19fc01f7e7Sbellard  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20fc01f7e7Sbellard  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21fc01f7e7Sbellard  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22fc01f7e7Sbellard  * THE SOFTWARE.
23fc01f7e7Sbellard  */
243990d09aSblueswir1 #include "config-host.h"
25179a2c19Sblueswir1 #ifdef HOST_BSD
263990d09aSblueswir1 /* include native header before sys-queue.h */
273990d09aSblueswir1 #include <sys/queue.h>
283990d09aSblueswir1 #endif
293990d09aSblueswir1 
30faf07963Spbrook #include "qemu-common.h"
31376253ecSaliguori #include "monitor.h"
32ea2384d3Sbellard #include "block_int.h"
33fc01f7e7Sbellard 
34179a2c19Sblueswir1 #ifdef HOST_BSD
357674e7bfSbellard #include <sys/types.h>
367674e7bfSbellard #include <sys/stat.h>
377674e7bfSbellard #include <sys/ioctl.h>
38c5e97233Sblueswir1 #ifndef __DragonFly__
397674e7bfSbellard #include <sys/disk.h>
407674e7bfSbellard #endif
41c5e97233Sblueswir1 #endif
427674e7bfSbellard 
4349dc768dSaliguori #ifdef _WIN32
4449dc768dSaliguori #include <windows.h>
4549dc768dSaliguori #endif
4649dc768dSaliguori 
4783f64091Sbellard #define SECTOR_BITS 9
4883f64091Sbellard #define SECTOR_SIZE (1 << SECTOR_BITS)
493b0d4f61Sbellard 
5090765429Sbellard typedef struct BlockDriverAIOCBSync {
5190765429Sbellard     BlockDriverAIOCB common;
5290765429Sbellard     QEMUBH *bh;
5390765429Sbellard     int ret;
54f141eafeSaliguori     /* vector translation state */
55f141eafeSaliguori     QEMUIOVector *qiov;
56f141eafeSaliguori     uint8_t *bounce;
57f141eafeSaliguori     int is_write;
5890765429Sbellard } BlockDriverAIOCBSync;
5990765429Sbellard 
60f141eafeSaliguori static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
61f141eafeSaliguori         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
62c87c0672Saliguori         BlockDriverCompletionFunc *cb, void *opaque);
63f141eafeSaliguori static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
64f141eafeSaliguori         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
65ce1a14dcSpbrook         BlockDriverCompletionFunc *cb, void *opaque);
6683f64091Sbellard static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
6783f64091Sbellard static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
6883f64091Sbellard                         uint8_t *buf, int nb_sectors);
6983f64091Sbellard static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
7083f64091Sbellard                          const uint8_t *buf, int nb_sectors);
71ec530c81Sbellard 
727ee930d0Sblueswir1 BlockDriverState *bdrv_first;
737ee930d0Sblueswir1 
74ea2384d3Sbellard static BlockDriver *first_drv;
75ea2384d3Sbellard 
7683f64091Sbellard int path_is_absolute(const char *path)
7783f64091Sbellard {
7883f64091Sbellard     const char *p;
7921664424Sbellard #ifdef _WIN32
8021664424Sbellard     /* specific case for names like: "\\.\d:" */
8121664424Sbellard     if (*path == '/' || *path == '\\')
8221664424Sbellard         return 1;
8321664424Sbellard #endif
8483f64091Sbellard     p = strchr(path, ':');
8583f64091Sbellard     if (p)
8683f64091Sbellard         p++;
8783f64091Sbellard     else
8883f64091Sbellard         p = path;
893b9f94e1Sbellard #ifdef _WIN32
903b9f94e1Sbellard     return (*p == '/' || *p == '\\');
913b9f94e1Sbellard #else
923b9f94e1Sbellard     return (*p == '/');
933b9f94e1Sbellard #endif
9483f64091Sbellard }
9583f64091Sbellard 
9683f64091Sbellard /* if filename is absolute, just copy it to dest. Otherwise, build a
9783f64091Sbellard    path to it by considering it is relative to base_path. URL are
9883f64091Sbellard    supported. */
9983f64091Sbellard void path_combine(char *dest, int dest_size,
10083f64091Sbellard                   const char *base_path,
10183f64091Sbellard                   const char *filename)
10283f64091Sbellard {
10383f64091Sbellard     const char *p, *p1;
10483f64091Sbellard     int len;
10583f64091Sbellard 
10683f64091Sbellard     if (dest_size <= 0)
10783f64091Sbellard         return;
10883f64091Sbellard     if (path_is_absolute(filename)) {
10983f64091Sbellard         pstrcpy(dest, dest_size, filename);
11083f64091Sbellard     } else {
11183f64091Sbellard         p = strchr(base_path, ':');
11283f64091Sbellard         if (p)
11383f64091Sbellard             p++;
11483f64091Sbellard         else
11583f64091Sbellard             p = base_path;
1163b9f94e1Sbellard         p1 = strrchr(base_path, '/');
1173b9f94e1Sbellard #ifdef _WIN32
1183b9f94e1Sbellard         {
1193b9f94e1Sbellard             const char *p2;
1203b9f94e1Sbellard             p2 = strrchr(base_path, '\\');
1213b9f94e1Sbellard             if (!p1 || p2 > p1)
1223b9f94e1Sbellard                 p1 = p2;
1233b9f94e1Sbellard         }
1243b9f94e1Sbellard #endif
12583f64091Sbellard         if (p1)
12683f64091Sbellard             p1++;
12783f64091Sbellard         else
12883f64091Sbellard             p1 = base_path;
12983f64091Sbellard         if (p1 > p)
13083f64091Sbellard             p = p1;
13183f64091Sbellard         len = p - base_path;
13283f64091Sbellard         if (len > dest_size - 1)
13383f64091Sbellard             len = dest_size - 1;
13483f64091Sbellard         memcpy(dest, base_path, len);
13583f64091Sbellard         dest[len] = '\0';
13683f64091Sbellard         pstrcat(dest, dest_size, filename);
13783f64091Sbellard     }
13883f64091Sbellard }
13983f64091Sbellard 
14083f64091Sbellard 
1419596ebb7Spbrook static void bdrv_register(BlockDriver *bdrv)
142ea2384d3Sbellard {
143f141eafeSaliguori     if (!bdrv->bdrv_aio_readv) {
14483f64091Sbellard         /* add AIO emulation layer */
145f141eafeSaliguori         bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
146f141eafeSaliguori         bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
14783f64091Sbellard         bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
14890765429Sbellard         bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
149eda578e5Saliguori     } else if (!bdrv->bdrv_read) {
15083f64091Sbellard         /* add synchronous IO emulation layer */
15183f64091Sbellard         bdrv->bdrv_read = bdrv_read_em;
15283f64091Sbellard         bdrv->bdrv_write = bdrv_write_em;
15383f64091Sbellard     }
1546bbff9a0Saliguori     aio_pool_init(&bdrv->aio_pool, bdrv->aiocb_size, bdrv->bdrv_aio_cancel);
155ea2384d3Sbellard     bdrv->next = first_drv;
156ea2384d3Sbellard     first_drv = bdrv;
157ea2384d3Sbellard }
158b338082bSbellard 
159b338082bSbellard /* create a new block device (by default it is empty) */
160b338082bSbellard BlockDriverState *bdrv_new(const char *device_name)
161fc01f7e7Sbellard {
162b338082bSbellard     BlockDriverState **pbs, *bs;
163b338082bSbellard 
164b338082bSbellard     bs = qemu_mallocz(sizeof(BlockDriverState));
165b338082bSbellard     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
166ea2384d3Sbellard     if (device_name[0] != '\0') {
167b338082bSbellard         /* insert at the end */
168b338082bSbellard         pbs = &bdrv_first;
169b338082bSbellard         while (*pbs != NULL)
170b338082bSbellard             pbs = &(*pbs)->next;
171b338082bSbellard         *pbs = bs;
172ea2384d3Sbellard     }
173b338082bSbellard     return bs;
174b338082bSbellard }
175b338082bSbellard 
176ea2384d3Sbellard BlockDriver *bdrv_find_format(const char *format_name)
177ea2384d3Sbellard {
178ea2384d3Sbellard     BlockDriver *drv1;
179ea2384d3Sbellard     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
180ea2384d3Sbellard         if (!strcmp(drv1->format_name, format_name))
181ea2384d3Sbellard             return drv1;
182ea2384d3Sbellard     }
183ea2384d3Sbellard     return NULL;
184ea2384d3Sbellard }
185ea2384d3Sbellard 
1865eb45639Saliguori int bdrv_create2(BlockDriver *drv,
1875eb45639Saliguori                 const char *filename, int64_t size_in_sectors,
1885eb45639Saliguori                 const char *backing_file, const char *backing_format,
1895eb45639Saliguori                 int flags)
1905eb45639Saliguori {
1915eb45639Saliguori     if (drv->bdrv_create2)
1925eb45639Saliguori         return drv->bdrv_create2(filename, size_in_sectors, backing_file,
1935eb45639Saliguori                                  backing_format, flags);
1945eb45639Saliguori     if (drv->bdrv_create)
1955eb45639Saliguori         return drv->bdrv_create(filename, size_in_sectors, backing_file,
1965eb45639Saliguori                                 flags);
1975eb45639Saliguori     return -ENOTSUP;
1985eb45639Saliguori }
1995eb45639Saliguori 
200ea2384d3Sbellard int bdrv_create(BlockDriver *drv,
201ea2384d3Sbellard                 const char *filename, int64_t size_in_sectors,
202ea2384d3Sbellard                 const char *backing_file, int flags)
203ea2384d3Sbellard {
204ea2384d3Sbellard     if (!drv->bdrv_create)
205ea2384d3Sbellard         return -ENOTSUP;
206ea2384d3Sbellard     return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
207ea2384d3Sbellard }
208ea2384d3Sbellard 
209d5249393Sbellard #ifdef _WIN32
21095389c86Sbellard void get_tmp_filename(char *filename, int size)
211d5249393Sbellard {
2123b9f94e1Sbellard     char temp_dir[MAX_PATH];
2133b9f94e1Sbellard 
2143b9f94e1Sbellard     GetTempPath(MAX_PATH, temp_dir);
2153b9f94e1Sbellard     GetTempFileName(temp_dir, "qem", 0, filename);
216d5249393Sbellard }
217d5249393Sbellard #else
21895389c86Sbellard void get_tmp_filename(char *filename, int size)
219ea2384d3Sbellard {
220ea2384d3Sbellard     int fd;
2217ccfb2ebSblueswir1     const char *tmpdir;
222d5249393Sbellard     /* XXX: race condition possible */
2230badc1eeSaurel32     tmpdir = getenv("TMPDIR");
2240badc1eeSaurel32     if (!tmpdir)
2250badc1eeSaurel32         tmpdir = "/tmp";
2260badc1eeSaurel32     snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
227ea2384d3Sbellard     fd = mkstemp(filename);
228ea2384d3Sbellard     close(fd);
229ea2384d3Sbellard }
230d5249393Sbellard #endif
231ea2384d3Sbellard 
23219cb3738Sbellard #ifdef _WIN32
233f45512feSbellard static int is_windows_drive_prefix(const char *filename)
234f45512feSbellard {
235f45512feSbellard     return (((filename[0] >= 'a' && filename[0] <= 'z') ||
236f45512feSbellard              (filename[0] >= 'A' && filename[0] <= 'Z')) &&
237f45512feSbellard             filename[1] == ':');
238f45512feSbellard }
239f45512feSbellard 
24019cb3738Sbellard static int is_windows_drive(const char *filename)
24119cb3738Sbellard {
242f45512feSbellard     if (is_windows_drive_prefix(filename) &&
243f45512feSbellard         filename[2] == '\0')
24419cb3738Sbellard         return 1;
24519cb3738Sbellard     if (strstart(filename, "\\\\.\\", NULL) ||
24619cb3738Sbellard         strstart(filename, "//./", NULL))
24719cb3738Sbellard         return 1;
24819cb3738Sbellard     return 0;
24919cb3738Sbellard }
25019cb3738Sbellard #endif
25119cb3738Sbellard 
25283f64091Sbellard static BlockDriver *find_protocol(const char *filename)
25383f64091Sbellard {
25483f64091Sbellard     BlockDriver *drv1;
25583f64091Sbellard     char protocol[128];
25683f64091Sbellard     int len;
25783f64091Sbellard     const char *p;
25819cb3738Sbellard 
25919cb3738Sbellard #ifdef _WIN32
260f45512feSbellard     if (is_windows_drive(filename) ||
261f45512feSbellard         is_windows_drive_prefix(filename))
26219cb3738Sbellard         return &bdrv_raw;
26319cb3738Sbellard #endif
26483f64091Sbellard     p = strchr(filename, ':');
26583f64091Sbellard     if (!p)
26683f64091Sbellard         return &bdrv_raw;
26783f64091Sbellard     len = p - filename;
26883f64091Sbellard     if (len > sizeof(protocol) - 1)
26983f64091Sbellard         len = sizeof(protocol) - 1;
27083f64091Sbellard     memcpy(protocol, filename, len);
27183f64091Sbellard     protocol[len] = '\0';
27283f64091Sbellard     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
27383f64091Sbellard         if (drv1->protocol_name &&
27483f64091Sbellard             !strcmp(drv1->protocol_name, protocol))
27583f64091Sbellard             return drv1;
27683f64091Sbellard     }
27783f64091Sbellard     return NULL;
27883f64091Sbellard }
27983f64091Sbellard 
2807674e7bfSbellard /* XXX: force raw format if block or character device ? It would
2817674e7bfSbellard    simplify the BSD case */
282ea2384d3Sbellard static BlockDriver *find_image_format(const char *filename)
283ea2384d3Sbellard {
28483f64091Sbellard     int ret, score, score_max;
285ea2384d3Sbellard     BlockDriver *drv1, *drv;
28683f64091Sbellard     uint8_t buf[2048];
28783f64091Sbellard     BlockDriverState *bs;
288ea2384d3Sbellard 
28919cb3738Sbellard     /* detect host devices. By convention, /dev/cdrom[N] is always
29019cb3738Sbellard        recognized as a host CDROM */
29119cb3738Sbellard     if (strstart(filename, "/dev/cdrom", NULL))
29219cb3738Sbellard         return &bdrv_host_device;
29319cb3738Sbellard #ifdef _WIN32
29419cb3738Sbellard     if (is_windows_drive(filename))
29519cb3738Sbellard         return &bdrv_host_device;
29619cb3738Sbellard #else
29719cb3738Sbellard     {
29819cb3738Sbellard         struct stat st;
29919cb3738Sbellard         if (stat(filename, &st) >= 0 &&
30019cb3738Sbellard             (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
30119cb3738Sbellard             return &bdrv_host_device;
30219cb3738Sbellard         }
30319cb3738Sbellard     }
30419cb3738Sbellard #endif
30519cb3738Sbellard 
30683f64091Sbellard     drv = find_protocol(filename);
30719cb3738Sbellard     /* no need to test disk image formats for vvfat */
30883f64091Sbellard     if (drv == &bdrv_vvfat)
30983f64091Sbellard         return drv;
31083f64091Sbellard 
31183f64091Sbellard     ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
31283f64091Sbellard     if (ret < 0)
3137674e7bfSbellard         return NULL;
31483f64091Sbellard     ret = bdrv_pread(bs, 0, buf, sizeof(buf));
31583f64091Sbellard     bdrv_delete(bs);
316ea2384d3Sbellard     if (ret < 0) {
317ea2384d3Sbellard         return NULL;
318ea2384d3Sbellard     }
319ea2384d3Sbellard 
320ea2384d3Sbellard     score_max = 0;
321ea2384d3Sbellard     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
32283f64091Sbellard         if (drv1->bdrv_probe) {
323ea2384d3Sbellard             score = drv1->bdrv_probe(buf, ret, filename);
324ea2384d3Sbellard             if (score > score_max) {
325ea2384d3Sbellard                 score_max = score;
326ea2384d3Sbellard                 drv = drv1;
327ea2384d3Sbellard             }
328ea2384d3Sbellard         }
32983f64091Sbellard     }
330ea2384d3Sbellard     return drv;
331ea2384d3Sbellard }
332ea2384d3Sbellard 
33383f64091Sbellard int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
334b338082bSbellard {
33583f64091Sbellard     BlockDriverState *bs;
33683f64091Sbellard     int ret;
3373b0d4f61Sbellard 
33883f64091Sbellard     bs = bdrv_new("");
33983f64091Sbellard     ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
34083f64091Sbellard     if (ret < 0) {
34183f64091Sbellard         bdrv_delete(bs);
34283f64091Sbellard         return ret;
3433b0d4f61Sbellard     }
34471d0770cSaliguori     bs->growable = 1;
34583f64091Sbellard     *pbs = bs;
34683f64091Sbellard     return 0;
3473b0d4f61Sbellard }
3483b0d4f61Sbellard 
34983f64091Sbellard int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
35083f64091Sbellard {
35183f64091Sbellard     return bdrv_open2(bs, filename, flags, NULL);
352ea2384d3Sbellard }
353ea2384d3Sbellard 
35483f64091Sbellard int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
355ea2384d3Sbellard                BlockDriver *drv)
356ea2384d3Sbellard {
35783f64091Sbellard     int ret, open_flags;
358eb5c851fSths     char tmp_filename[PATH_MAX];
359eb5c851fSths     char backing_filename[PATH_MAX];
360fc01f7e7Sbellard 
3610849bf08Sbellard     bs->read_only = 0;
362ea2384d3Sbellard     bs->is_temporary = 0;
363ea2384d3Sbellard     bs->encrypted = 0;
364c0f4ce77Saliguori     bs->valid_key = 0;
36533e3963eSbellard 
36683f64091Sbellard     if (flags & BDRV_O_SNAPSHOT) {
367ea2384d3Sbellard         BlockDriverState *bs1;
368ea2384d3Sbellard         int64_t total_size;
3697c96d46eSaliguori         int is_protocol = 0;
37033e3963eSbellard 
371ea2384d3Sbellard         /* if snapshot, we create a temporary backing file and open it
372ea2384d3Sbellard            instead of opening 'filename' directly */
373ea2384d3Sbellard 
374ea2384d3Sbellard         /* if there is a backing file, use it */
375ea2384d3Sbellard         bs1 = bdrv_new("");
3765eb45639Saliguori         ret = bdrv_open2(bs1, filename, 0, drv);
37751d7c00cSaliguori         if (ret < 0) {
378ea2384d3Sbellard             bdrv_delete(bs1);
37951d7c00cSaliguori             return ret;
380ea2384d3Sbellard         }
38183f64091Sbellard         total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
3827c96d46eSaliguori 
3837c96d46eSaliguori         if (bs1->drv && bs1->drv->protocol_name)
3847c96d46eSaliguori             is_protocol = 1;
3857c96d46eSaliguori 
386ea2384d3Sbellard         bdrv_delete(bs1);
387ea2384d3Sbellard 
388ea2384d3Sbellard         get_tmp_filename(tmp_filename, sizeof(tmp_filename));
3897c96d46eSaliguori 
3907c96d46eSaliguori         /* Real path is meaningless for protocols */
3917c96d46eSaliguori         if (is_protocol)
3927c96d46eSaliguori             snprintf(backing_filename, sizeof(backing_filename),
3937c96d46eSaliguori                      "%s", filename);
3947c96d46eSaliguori         else
395a817d936Sbellard             realpath(filename, backing_filename);
3967c96d46eSaliguori 
3975eb45639Saliguori         ret = bdrv_create2(&bdrv_qcow2, tmp_filename,
3985eb45639Saliguori                            total_size, backing_filename,
3995eb45639Saliguori                            (drv ? drv->format_name : NULL), 0);
40051d7c00cSaliguori         if (ret < 0) {
40151d7c00cSaliguori             return ret;
402ea2384d3Sbellard         }
403ea2384d3Sbellard         filename = tmp_filename;
4045eb45639Saliguori         drv = &bdrv_qcow2;
405ea2384d3Sbellard         bs->is_temporary = 1;
406ea2384d3Sbellard     }
407ea2384d3Sbellard 
408ea2384d3Sbellard     pstrcpy(bs->filename, sizeof(bs->filename), filename);
40983f64091Sbellard     if (flags & BDRV_O_FILE) {
41083f64091Sbellard         drv = find_protocol(filename);
41151d7c00cSaliguori     } else if (!drv) {
412ea2384d3Sbellard         drv = find_image_format(filename);
413ea2384d3Sbellard     }
41451d7c00cSaliguori     if (!drv) {
41551d7c00cSaliguori         ret = -ENOENT;
41651d7c00cSaliguori         goto unlink_and_fail;
41783f64091Sbellard     }
418ea2384d3Sbellard     bs->drv = drv;
419ea2384d3Sbellard     bs->opaque = qemu_mallocz(drv->instance_size);
42083f64091Sbellard     /* Note: for compatibility, we open disk image files as RDWR, and
42183f64091Sbellard        RDONLY as fallback */
42283f64091Sbellard     if (!(flags & BDRV_O_FILE))
4239f7965c7Saliguori         open_flags = BDRV_O_RDWR | (flags & BDRV_O_CACHE_MASK);
42483f64091Sbellard     else
42583f64091Sbellard         open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
42683f64091Sbellard     ret = drv->bdrv_open(bs, filename, open_flags);
427a0a83536Saurel32     if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) {
4289f7965c7Saliguori         ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR);
42983f64091Sbellard         bs->read_only = 1;
43083f64091Sbellard     }
431ea2384d3Sbellard     if (ret < 0) {
432ea2384d3Sbellard         qemu_free(bs->opaque);
4336b21b973Sbellard         bs->opaque = NULL;
4346b21b973Sbellard         bs->drv = NULL;
43551d7c00cSaliguori     unlink_and_fail:
43651d7c00cSaliguori         if (bs->is_temporary)
43751d7c00cSaliguori             unlink(filename);
43883f64091Sbellard         return ret;
439ea2384d3Sbellard     }
440d15a771dSbellard     if (drv->bdrv_getlength) {
441d15a771dSbellard         bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
442d15a771dSbellard     }
443ea2384d3Sbellard #ifndef _WIN32
444ea2384d3Sbellard     if (bs->is_temporary) {
445ea2384d3Sbellard         unlink(filename);
44633e3963eSbellard     }
44767b915a5Sbellard #endif
44883f64091Sbellard     if (bs->backing_file[0] != '\0') {
449ea2384d3Sbellard         /* if there is a backing file, use it */
4505eb45639Saliguori         BlockDriver *back_drv = NULL;
451ea2384d3Sbellard         bs->backing_hd = bdrv_new("");
45283f64091Sbellard         path_combine(backing_filename, sizeof(backing_filename),
45383f64091Sbellard                      filename, bs->backing_file);
4545eb45639Saliguori         if (bs->backing_format[0] != '\0')
4555eb45639Saliguori             back_drv = bdrv_find_format(bs->backing_format);
4565eb45639Saliguori         ret = bdrv_open2(bs->backing_hd, backing_filename, open_flags,
4575eb45639Saliguori                          back_drv);
45851d7c00cSaliguori         if (ret < 0) {
45951d7c00cSaliguori             bdrv_close(bs);
46051d7c00cSaliguori             return ret;
46151d7c00cSaliguori         }
462ea2384d3Sbellard     }
46333e3963eSbellard 
464bb5fc20fSaliguori     if (!bdrv_key_required(bs)) {
465b338082bSbellard         /* call the change callback */
46619cb3738Sbellard         bs->media_changed = 1;
467b338082bSbellard         if (bs->change_cb)
468b338082bSbellard             bs->change_cb(bs->change_opaque);
469bb5fc20fSaliguori     }
470b338082bSbellard     return 0;
471fc01f7e7Sbellard }
472fc01f7e7Sbellard 
473fc01f7e7Sbellard void bdrv_close(BlockDriverState *bs)
474fc01f7e7Sbellard {
47519cb3738Sbellard     if (bs->drv) {
476ea2384d3Sbellard         if (bs->backing_hd)
477ea2384d3Sbellard             bdrv_delete(bs->backing_hd);
478ea2384d3Sbellard         bs->drv->bdrv_close(bs);
479ea2384d3Sbellard         qemu_free(bs->opaque);
480ea2384d3Sbellard #ifdef _WIN32
481ea2384d3Sbellard         if (bs->is_temporary) {
482ea2384d3Sbellard             unlink(bs->filename);
483ea2384d3Sbellard         }
48467b915a5Sbellard #endif
485ea2384d3Sbellard         bs->opaque = NULL;
486ea2384d3Sbellard         bs->drv = NULL;
487b338082bSbellard 
488b338082bSbellard         /* call the change callback */
48919cb3738Sbellard         bs->media_changed = 1;
490b338082bSbellard         if (bs->change_cb)
491b338082bSbellard             bs->change_cb(bs->change_opaque);
492b338082bSbellard     }
493b338082bSbellard }
494b338082bSbellard 
495b338082bSbellard void bdrv_delete(BlockDriverState *bs)
496b338082bSbellard {
49734c6f050Saurel32     BlockDriverState **pbs;
49834c6f050Saurel32 
49934c6f050Saurel32     pbs = &bdrv_first;
50034c6f050Saurel32     while (*pbs != bs && *pbs != NULL)
50134c6f050Saurel32         pbs = &(*pbs)->next;
50234c6f050Saurel32     if (*pbs == bs)
50334c6f050Saurel32         *pbs = bs->next;
50434c6f050Saurel32 
505b338082bSbellard     bdrv_close(bs);
506b338082bSbellard     qemu_free(bs);
507fc01f7e7Sbellard }
508fc01f7e7Sbellard 
50933e3963eSbellard /* commit COW file into the raw image */
51033e3963eSbellard int bdrv_commit(BlockDriverState *bs)
51133e3963eSbellard {
51219cb3738Sbellard     BlockDriver *drv = bs->drv;
51383f64091Sbellard     int64_t i, total_sectors;
514ea2384d3Sbellard     int n, j;
515ea2384d3Sbellard     unsigned char sector[512];
51633e3963eSbellard 
51719cb3738Sbellard     if (!drv)
51819cb3738Sbellard         return -ENOMEDIUM;
51933e3963eSbellard 
52033e3963eSbellard     if (bs->read_only) {
521ea2384d3Sbellard 	return -EACCES;
52233e3963eSbellard     }
52333e3963eSbellard 
524ea2384d3Sbellard     if (!bs->backing_hd) {
525ea2384d3Sbellard 	return -ENOTSUP;
526ea2384d3Sbellard     }
527ea2384d3Sbellard 
52883f64091Sbellard     total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
52983f64091Sbellard     for (i = 0; i < total_sectors;) {
53019cb3738Sbellard         if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
531ea2384d3Sbellard             for(j = 0; j < n; j++) {
53233e3963eSbellard                 if (bdrv_read(bs, i, sector, 1) != 0) {
533ea2384d3Sbellard                     return -EIO;
53433e3963eSbellard                 }
53533e3963eSbellard 
536ea2384d3Sbellard                 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
537ea2384d3Sbellard                     return -EIO;
53833e3963eSbellard                 }
539ea2384d3Sbellard                 i++;
540ea2384d3Sbellard 	    }
541ea2384d3Sbellard 	} else {
542ea2384d3Sbellard             i += n;
54333e3963eSbellard         }
54433e3963eSbellard     }
54595389c86Sbellard 
54619cb3738Sbellard     if (drv->bdrv_make_empty)
54719cb3738Sbellard 	return drv->bdrv_make_empty(bs);
54895389c86Sbellard 
54933e3963eSbellard     return 0;
55033e3963eSbellard }
55133e3963eSbellard 
55271d0770cSaliguori static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
55371d0770cSaliguori                                    size_t size)
55471d0770cSaliguori {
55571d0770cSaliguori     int64_t len;
55671d0770cSaliguori 
55771d0770cSaliguori     if (!bdrv_is_inserted(bs))
55871d0770cSaliguori         return -ENOMEDIUM;
55971d0770cSaliguori 
56071d0770cSaliguori     if (bs->growable)
56171d0770cSaliguori         return 0;
56271d0770cSaliguori 
56371d0770cSaliguori     len = bdrv_getlength(bs);
56471d0770cSaliguori 
56571d0770cSaliguori     if ((offset + size) > len)
56671d0770cSaliguori         return -EIO;
56771d0770cSaliguori 
56871d0770cSaliguori     return 0;
56971d0770cSaliguori }
57071d0770cSaliguori 
57171d0770cSaliguori static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
57271d0770cSaliguori                               int nb_sectors)
57371d0770cSaliguori {
574999dec57Saliguori     return bdrv_check_byte_request(bs, sector_num * 512, nb_sectors * 512);
57571d0770cSaliguori }
57671d0770cSaliguori 
57719cb3738Sbellard /* return < 0 if error. See bdrv_write() for the return codes */
578fc01f7e7Sbellard int bdrv_read(BlockDriverState *bs, int64_t sector_num,
579fc01f7e7Sbellard               uint8_t *buf, int nb_sectors)
580fc01f7e7Sbellard {
581ea2384d3Sbellard     BlockDriver *drv = bs->drv;
582fc01f7e7Sbellard 
58319cb3738Sbellard     if (!drv)
58419cb3738Sbellard         return -ENOMEDIUM;
58571d0770cSaliguori     if (bdrv_check_request(bs, sector_num, nb_sectors))
58671d0770cSaliguori         return -EIO;
587b338082bSbellard 
58883f64091Sbellard     return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
58983f64091Sbellard }
590fc01f7e7Sbellard 
59119cb3738Sbellard /* Return < 0 if error. Important errors are:
59219cb3738Sbellard   -EIO         generic I/O error (may happen for all errors)
59319cb3738Sbellard   -ENOMEDIUM   No media inserted.
59419cb3738Sbellard   -EINVAL      Invalid sector number or nb_sectors
59519cb3738Sbellard   -EACCES      Trying to write a read-only device
59619cb3738Sbellard */
597fc01f7e7Sbellard int bdrv_write(BlockDriverState *bs, int64_t sector_num,
598fc01f7e7Sbellard                const uint8_t *buf, int nb_sectors)
599fc01f7e7Sbellard {
60083f64091Sbellard     BlockDriver *drv = bs->drv;
60119cb3738Sbellard     if (!bs->drv)
60219cb3738Sbellard         return -ENOMEDIUM;
6030849bf08Sbellard     if (bs->read_only)
60419cb3738Sbellard         return -EACCES;
60571d0770cSaliguori     if (bdrv_check_request(bs, sector_num, nb_sectors))
60671d0770cSaliguori         return -EIO;
60771d0770cSaliguori 
60883f64091Sbellard     return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
60983f64091Sbellard }
61083f64091Sbellard 
611eda578e5Saliguori int bdrv_pread(BlockDriverState *bs, int64_t offset,
612eda578e5Saliguori                void *buf, int count1)
61383f64091Sbellard {
61483f64091Sbellard     uint8_t tmp_buf[SECTOR_SIZE];
61583f64091Sbellard     int len, nb_sectors, count;
61683f64091Sbellard     int64_t sector_num;
61783f64091Sbellard 
61883f64091Sbellard     count = count1;
61983f64091Sbellard     /* first read to align to sector start */
62083f64091Sbellard     len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
62183f64091Sbellard     if (len > count)
62283f64091Sbellard         len = count;
62383f64091Sbellard     sector_num = offset >> SECTOR_BITS;
62483f64091Sbellard     if (len > 0) {
62583f64091Sbellard         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
62683f64091Sbellard             return -EIO;
62783f64091Sbellard         memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
62883f64091Sbellard         count -= len;
62983f64091Sbellard         if (count == 0)
63083f64091Sbellard             return count1;
63183f64091Sbellard         sector_num++;
63283f64091Sbellard         buf += len;
63383f64091Sbellard     }
63483f64091Sbellard 
63583f64091Sbellard     /* read the sectors "in place" */
63683f64091Sbellard     nb_sectors = count >> SECTOR_BITS;
63783f64091Sbellard     if (nb_sectors > 0) {
63883f64091Sbellard         if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
63983f64091Sbellard             return -EIO;
64083f64091Sbellard         sector_num += nb_sectors;
64183f64091Sbellard         len = nb_sectors << SECTOR_BITS;
64283f64091Sbellard         buf += len;
64383f64091Sbellard         count -= len;
64483f64091Sbellard     }
64583f64091Sbellard 
64683f64091Sbellard     /* add data from the last sector */
64783f64091Sbellard     if (count > 0) {
64883f64091Sbellard         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
64983f64091Sbellard             return -EIO;
65083f64091Sbellard         memcpy(buf, tmp_buf, count);
65183f64091Sbellard     }
65283f64091Sbellard     return count1;
65383f64091Sbellard }
65483f64091Sbellard 
655eda578e5Saliguori int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
656eda578e5Saliguori                 const void *buf, int count1)
65783f64091Sbellard {
65883f64091Sbellard     uint8_t tmp_buf[SECTOR_SIZE];
65983f64091Sbellard     int len, nb_sectors, count;
66083f64091Sbellard     int64_t sector_num;
66183f64091Sbellard 
66283f64091Sbellard     count = count1;
66383f64091Sbellard     /* first write to align to sector start */
66483f64091Sbellard     len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
66583f64091Sbellard     if (len > count)
66683f64091Sbellard         len = count;
66783f64091Sbellard     sector_num = offset >> SECTOR_BITS;
66883f64091Sbellard     if (len > 0) {
66983f64091Sbellard         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
67083f64091Sbellard             return -EIO;
67183f64091Sbellard         memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
67283f64091Sbellard         if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
67383f64091Sbellard             return -EIO;
67483f64091Sbellard         count -= len;
67583f64091Sbellard         if (count == 0)
67683f64091Sbellard             return count1;
67783f64091Sbellard         sector_num++;
67883f64091Sbellard         buf += len;
67983f64091Sbellard     }
68083f64091Sbellard 
68183f64091Sbellard     /* write the sectors "in place" */
68283f64091Sbellard     nb_sectors = count >> SECTOR_BITS;
68383f64091Sbellard     if (nb_sectors > 0) {
68483f64091Sbellard         if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
68583f64091Sbellard             return -EIO;
68683f64091Sbellard         sector_num += nb_sectors;
68783f64091Sbellard         len = nb_sectors << SECTOR_BITS;
68883f64091Sbellard         buf += len;
68983f64091Sbellard         count -= len;
69083f64091Sbellard     }
69183f64091Sbellard 
69283f64091Sbellard     /* add data from the last sector */
69383f64091Sbellard     if (count > 0) {
69483f64091Sbellard         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
69583f64091Sbellard             return -EIO;
69683f64091Sbellard         memcpy(tmp_buf, buf, count);
69783f64091Sbellard         if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
69883f64091Sbellard             return -EIO;
69983f64091Sbellard     }
70083f64091Sbellard     return count1;
70183f64091Sbellard }
70283f64091Sbellard 
70383f64091Sbellard /**
70483f64091Sbellard  * Truncate file to 'offset' bytes (needed only for file protocols)
70583f64091Sbellard  */
70683f64091Sbellard int bdrv_truncate(BlockDriverState *bs, int64_t offset)
70783f64091Sbellard {
70883f64091Sbellard     BlockDriver *drv = bs->drv;
70983f64091Sbellard     if (!drv)
71019cb3738Sbellard         return -ENOMEDIUM;
71183f64091Sbellard     if (!drv->bdrv_truncate)
71283f64091Sbellard         return -ENOTSUP;
71383f64091Sbellard     return drv->bdrv_truncate(bs, offset);
71483f64091Sbellard }
71583f64091Sbellard 
71683f64091Sbellard /**
71783f64091Sbellard  * Length of a file in bytes. Return < 0 if error or unknown.
71883f64091Sbellard  */
71983f64091Sbellard int64_t bdrv_getlength(BlockDriverState *bs)
72083f64091Sbellard {
72183f64091Sbellard     BlockDriver *drv = bs->drv;
72283f64091Sbellard     if (!drv)
72319cb3738Sbellard         return -ENOMEDIUM;
72483f64091Sbellard     if (!drv->bdrv_getlength) {
72583f64091Sbellard         /* legacy mode */
72683f64091Sbellard         return bs->total_sectors * SECTOR_SIZE;
72783f64091Sbellard     }
72883f64091Sbellard     return drv->bdrv_getlength(bs);
729fc01f7e7Sbellard }
730fc01f7e7Sbellard 
73119cb3738Sbellard /* return 0 as number of sectors if no device present or error */
73296b8f136Sths void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
733fc01f7e7Sbellard {
73419cb3738Sbellard     int64_t length;
73519cb3738Sbellard     length = bdrv_getlength(bs);
73619cb3738Sbellard     if (length < 0)
73719cb3738Sbellard         length = 0;
73819cb3738Sbellard     else
73919cb3738Sbellard         length = length >> SECTOR_BITS;
74019cb3738Sbellard     *nb_sectors_ptr = length;
741fc01f7e7Sbellard }
742cf98951bSbellard 
743f3d54fc4Saliguori struct partition {
744f3d54fc4Saliguori         uint8_t boot_ind;           /* 0x80 - active */
745f3d54fc4Saliguori         uint8_t head;               /* starting head */
746f3d54fc4Saliguori         uint8_t sector;             /* starting sector */
747f3d54fc4Saliguori         uint8_t cyl;                /* starting cylinder */
748f3d54fc4Saliguori         uint8_t sys_ind;            /* What partition type */
749f3d54fc4Saliguori         uint8_t end_head;           /* end head */
750f3d54fc4Saliguori         uint8_t end_sector;         /* end sector */
751f3d54fc4Saliguori         uint8_t end_cyl;            /* end cylinder */
752f3d54fc4Saliguori         uint32_t start_sect;        /* starting sector counting from 0 */
753f3d54fc4Saliguori         uint32_t nr_sects;          /* nr of sectors in partition */
754f3d54fc4Saliguori } __attribute__((packed));
755f3d54fc4Saliguori 
756f3d54fc4Saliguori /* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */
757f3d54fc4Saliguori static int guess_disk_lchs(BlockDriverState *bs,
758f3d54fc4Saliguori                            int *pcylinders, int *pheads, int *psectors)
759f3d54fc4Saliguori {
760f3d54fc4Saliguori     uint8_t buf[512];
761f3d54fc4Saliguori     int ret, i, heads, sectors, cylinders;
762f3d54fc4Saliguori     struct partition *p;
763f3d54fc4Saliguori     uint32_t nr_sects;
764a38131b6Sblueswir1     uint64_t nb_sectors;
765f3d54fc4Saliguori 
766f3d54fc4Saliguori     bdrv_get_geometry(bs, &nb_sectors);
767f3d54fc4Saliguori 
768f3d54fc4Saliguori     ret = bdrv_read(bs, 0, buf, 1);
769f3d54fc4Saliguori     if (ret < 0)
770f3d54fc4Saliguori         return -1;
771f3d54fc4Saliguori     /* test msdos magic */
772f3d54fc4Saliguori     if (buf[510] != 0x55 || buf[511] != 0xaa)
773f3d54fc4Saliguori         return -1;
774f3d54fc4Saliguori     for(i = 0; i < 4; i++) {
775f3d54fc4Saliguori         p = ((struct partition *)(buf + 0x1be)) + i;
776f3d54fc4Saliguori         nr_sects = le32_to_cpu(p->nr_sects);
777f3d54fc4Saliguori         if (nr_sects && p->end_head) {
778f3d54fc4Saliguori             /* We make the assumption that the partition terminates on
779f3d54fc4Saliguori                a cylinder boundary */
780f3d54fc4Saliguori             heads = p->end_head + 1;
781f3d54fc4Saliguori             sectors = p->end_sector & 63;
782f3d54fc4Saliguori             if (sectors == 0)
783f3d54fc4Saliguori                 continue;
784f3d54fc4Saliguori             cylinders = nb_sectors / (heads * sectors);
785f3d54fc4Saliguori             if (cylinders < 1 || cylinders > 16383)
786f3d54fc4Saliguori                 continue;
787f3d54fc4Saliguori             *pheads = heads;
788f3d54fc4Saliguori             *psectors = sectors;
789f3d54fc4Saliguori             *pcylinders = cylinders;
790f3d54fc4Saliguori #if 0
791f3d54fc4Saliguori             printf("guessed geometry: LCHS=%d %d %d\n",
792f3d54fc4Saliguori                    cylinders, heads, sectors);
793f3d54fc4Saliguori #endif
794f3d54fc4Saliguori             return 0;
795f3d54fc4Saliguori         }
796f3d54fc4Saliguori     }
797f3d54fc4Saliguori     return -1;
798f3d54fc4Saliguori }
799f3d54fc4Saliguori 
800f3d54fc4Saliguori void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs)
801f3d54fc4Saliguori {
802f3d54fc4Saliguori     int translation, lba_detected = 0;
803f3d54fc4Saliguori     int cylinders, heads, secs;
804a38131b6Sblueswir1     uint64_t nb_sectors;
805f3d54fc4Saliguori 
806f3d54fc4Saliguori     /* if a geometry hint is available, use it */
807f3d54fc4Saliguori     bdrv_get_geometry(bs, &nb_sectors);
808f3d54fc4Saliguori     bdrv_get_geometry_hint(bs, &cylinders, &heads, &secs);
809f3d54fc4Saliguori     translation = bdrv_get_translation_hint(bs);
810f3d54fc4Saliguori     if (cylinders != 0) {
811f3d54fc4Saliguori         *pcyls = cylinders;
812f3d54fc4Saliguori         *pheads = heads;
813f3d54fc4Saliguori         *psecs = secs;
814f3d54fc4Saliguori     } else {
815f3d54fc4Saliguori         if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) {
816f3d54fc4Saliguori             if (heads > 16) {
817f3d54fc4Saliguori                 /* if heads > 16, it means that a BIOS LBA
818f3d54fc4Saliguori                    translation was active, so the default
819f3d54fc4Saliguori                    hardware geometry is OK */
820f3d54fc4Saliguori                 lba_detected = 1;
821f3d54fc4Saliguori                 goto default_geometry;
822f3d54fc4Saliguori             } else {
823f3d54fc4Saliguori                 *pcyls = cylinders;
824f3d54fc4Saliguori                 *pheads = heads;
825f3d54fc4Saliguori                 *psecs = secs;
826f3d54fc4Saliguori                 /* disable any translation to be in sync with
827f3d54fc4Saliguori                    the logical geometry */
828f3d54fc4Saliguori                 if (translation == BIOS_ATA_TRANSLATION_AUTO) {
829f3d54fc4Saliguori                     bdrv_set_translation_hint(bs,
830f3d54fc4Saliguori                                               BIOS_ATA_TRANSLATION_NONE);
831f3d54fc4Saliguori                 }
832f3d54fc4Saliguori             }
833f3d54fc4Saliguori         } else {
834f3d54fc4Saliguori         default_geometry:
835f3d54fc4Saliguori             /* if no geometry, use a standard physical disk geometry */
836f3d54fc4Saliguori             cylinders = nb_sectors / (16 * 63);
837f3d54fc4Saliguori 
838f3d54fc4Saliguori             if (cylinders > 16383)
839f3d54fc4Saliguori                 cylinders = 16383;
840f3d54fc4Saliguori             else if (cylinders < 2)
841f3d54fc4Saliguori                 cylinders = 2;
842f3d54fc4Saliguori             *pcyls = cylinders;
843f3d54fc4Saliguori             *pheads = 16;
844f3d54fc4Saliguori             *psecs = 63;
845f3d54fc4Saliguori             if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) {
846f3d54fc4Saliguori                 if ((*pcyls * *pheads) <= 131072) {
847f3d54fc4Saliguori                     bdrv_set_translation_hint(bs,
848f3d54fc4Saliguori                                               BIOS_ATA_TRANSLATION_LARGE);
849f3d54fc4Saliguori                 } else {
850f3d54fc4Saliguori                     bdrv_set_translation_hint(bs,
851f3d54fc4Saliguori                                               BIOS_ATA_TRANSLATION_LBA);
852f3d54fc4Saliguori                 }
853f3d54fc4Saliguori             }
854f3d54fc4Saliguori         }
855f3d54fc4Saliguori         bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
856f3d54fc4Saliguori     }
857f3d54fc4Saliguori }
858f3d54fc4Saliguori 
859b338082bSbellard void bdrv_set_geometry_hint(BlockDriverState *bs,
860b338082bSbellard                             int cyls, int heads, int secs)
861b338082bSbellard {
862b338082bSbellard     bs->cyls = cyls;
863b338082bSbellard     bs->heads = heads;
864b338082bSbellard     bs->secs = secs;
865b338082bSbellard }
866b338082bSbellard 
867b338082bSbellard void bdrv_set_type_hint(BlockDriverState *bs, int type)
868b338082bSbellard {
869b338082bSbellard     bs->type = type;
870b338082bSbellard     bs->removable = ((type == BDRV_TYPE_CDROM ||
871b338082bSbellard                       type == BDRV_TYPE_FLOPPY));
872b338082bSbellard }
873b338082bSbellard 
87446d4767dSbellard void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
87546d4767dSbellard {
87646d4767dSbellard     bs->translation = translation;
87746d4767dSbellard }
87846d4767dSbellard 
879b338082bSbellard void bdrv_get_geometry_hint(BlockDriverState *bs,
880b338082bSbellard                             int *pcyls, int *pheads, int *psecs)
881b338082bSbellard {
882b338082bSbellard     *pcyls = bs->cyls;
883b338082bSbellard     *pheads = bs->heads;
884b338082bSbellard     *psecs = bs->secs;
885b338082bSbellard }
886b338082bSbellard 
887b338082bSbellard int bdrv_get_type_hint(BlockDriverState *bs)
888b338082bSbellard {
889b338082bSbellard     return bs->type;
890b338082bSbellard }
891b338082bSbellard 
89246d4767dSbellard int bdrv_get_translation_hint(BlockDriverState *bs)
89346d4767dSbellard {
89446d4767dSbellard     return bs->translation;
89546d4767dSbellard }
89646d4767dSbellard 
897b338082bSbellard int bdrv_is_removable(BlockDriverState *bs)
898b338082bSbellard {
899b338082bSbellard     return bs->removable;
900b338082bSbellard }
901b338082bSbellard 
902b338082bSbellard int bdrv_is_read_only(BlockDriverState *bs)
903b338082bSbellard {
904b338082bSbellard     return bs->read_only;
905b338082bSbellard }
906b338082bSbellard 
907985a03b0Sths int bdrv_is_sg(BlockDriverState *bs)
908985a03b0Sths {
909985a03b0Sths     return bs->sg;
910985a03b0Sths }
911985a03b0Sths 
91219cb3738Sbellard /* XXX: no longer used */
913b338082bSbellard void bdrv_set_change_cb(BlockDriverState *bs,
914b338082bSbellard                         void (*change_cb)(void *opaque), void *opaque)
915b338082bSbellard {
916b338082bSbellard     bs->change_cb = change_cb;
917b338082bSbellard     bs->change_opaque = opaque;
918b338082bSbellard }
919b338082bSbellard 
920ea2384d3Sbellard int bdrv_is_encrypted(BlockDriverState *bs)
921ea2384d3Sbellard {
922ea2384d3Sbellard     if (bs->backing_hd && bs->backing_hd->encrypted)
923ea2384d3Sbellard         return 1;
924ea2384d3Sbellard     return bs->encrypted;
925ea2384d3Sbellard }
926ea2384d3Sbellard 
927c0f4ce77Saliguori int bdrv_key_required(BlockDriverState *bs)
928c0f4ce77Saliguori {
929c0f4ce77Saliguori     BlockDriverState *backing_hd = bs->backing_hd;
930c0f4ce77Saliguori 
931c0f4ce77Saliguori     if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
932c0f4ce77Saliguori         return 1;
933c0f4ce77Saliguori     return (bs->encrypted && !bs->valid_key);
934c0f4ce77Saliguori }
935c0f4ce77Saliguori 
936ea2384d3Sbellard int bdrv_set_key(BlockDriverState *bs, const char *key)
937ea2384d3Sbellard {
938ea2384d3Sbellard     int ret;
939ea2384d3Sbellard     if (bs->backing_hd && bs->backing_hd->encrypted) {
940ea2384d3Sbellard         ret = bdrv_set_key(bs->backing_hd, key);
941ea2384d3Sbellard         if (ret < 0)
942ea2384d3Sbellard             return ret;
943ea2384d3Sbellard         if (!bs->encrypted)
944ea2384d3Sbellard             return 0;
945ea2384d3Sbellard     }
946ea2384d3Sbellard     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
947ea2384d3Sbellard         return -1;
948c0f4ce77Saliguori     ret = bs->drv->bdrv_set_key(bs, key);
949bb5fc20fSaliguori     if (ret < 0) {
950bb5fc20fSaliguori         bs->valid_key = 0;
951bb5fc20fSaliguori     } else if (!bs->valid_key) {
952bb5fc20fSaliguori         bs->valid_key = 1;
953bb5fc20fSaliguori         /* call the change callback now, we skipped it on open */
954bb5fc20fSaliguori         bs->media_changed = 1;
955bb5fc20fSaliguori         if (bs->change_cb)
956bb5fc20fSaliguori             bs->change_cb(bs->change_opaque);
957bb5fc20fSaliguori     }
958c0f4ce77Saliguori     return ret;
959ea2384d3Sbellard }
960ea2384d3Sbellard 
961ea2384d3Sbellard void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
962ea2384d3Sbellard {
96319cb3738Sbellard     if (!bs->drv) {
964ea2384d3Sbellard         buf[0] = '\0';
965ea2384d3Sbellard     } else {
966ea2384d3Sbellard         pstrcpy(buf, buf_size, bs->drv->format_name);
967ea2384d3Sbellard     }
968ea2384d3Sbellard }
969ea2384d3Sbellard 
970ea2384d3Sbellard void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
971ea2384d3Sbellard                          void *opaque)
972ea2384d3Sbellard {
973ea2384d3Sbellard     BlockDriver *drv;
974ea2384d3Sbellard 
975ea2384d3Sbellard     for (drv = first_drv; drv != NULL; drv = drv->next) {
976ea2384d3Sbellard         it(opaque, drv->format_name);
977ea2384d3Sbellard     }
978ea2384d3Sbellard }
979ea2384d3Sbellard 
980b338082bSbellard BlockDriverState *bdrv_find(const char *name)
981b338082bSbellard {
982b338082bSbellard     BlockDriverState *bs;
983b338082bSbellard 
984b338082bSbellard     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
985b338082bSbellard         if (!strcmp(name, bs->device_name))
986b338082bSbellard             return bs;
987b338082bSbellard     }
988b338082bSbellard     return NULL;
989b338082bSbellard }
990b338082bSbellard 
99151de9760Saliguori void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
99281d0912dSbellard {
99381d0912dSbellard     BlockDriverState *bs;
99481d0912dSbellard 
99581d0912dSbellard     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
99651de9760Saliguori         it(opaque, bs);
99781d0912dSbellard     }
99881d0912dSbellard }
99981d0912dSbellard 
1000ea2384d3Sbellard const char *bdrv_get_device_name(BlockDriverState *bs)
1001ea2384d3Sbellard {
1002ea2384d3Sbellard     return bs->device_name;
1003ea2384d3Sbellard }
1004ea2384d3Sbellard 
10057a6cba61Spbrook void bdrv_flush(BlockDriverState *bs)
10067a6cba61Spbrook {
1007081501daSaliguori     if (!bs->drv)
1008081501daSaliguori         return;
10097a6cba61Spbrook     if (bs->drv->bdrv_flush)
10107a6cba61Spbrook         bs->drv->bdrv_flush(bs);
10117a6cba61Spbrook     if (bs->backing_hd)
10127a6cba61Spbrook         bdrv_flush(bs->backing_hd);
10137a6cba61Spbrook }
10147a6cba61Spbrook 
1015c6ca28d6Saliguori void bdrv_flush_all(void)
1016c6ca28d6Saliguori {
1017c6ca28d6Saliguori     BlockDriverState *bs;
1018c6ca28d6Saliguori 
1019c6ca28d6Saliguori     for (bs = bdrv_first; bs != NULL; bs = bs->next)
1020c6ca28d6Saliguori         if (bs->drv && !bdrv_is_read_only(bs) &&
1021c6ca28d6Saliguori             (!bdrv_is_removable(bs) || bdrv_is_inserted(bs)))
1022c6ca28d6Saliguori             bdrv_flush(bs);
1023c6ca28d6Saliguori }
1024c6ca28d6Saliguori 
1025f58c7b35Sths /*
1026f58c7b35Sths  * Returns true iff the specified sector is present in the disk image. Drivers
1027f58c7b35Sths  * not implementing the functionality are assumed to not support backing files,
1028f58c7b35Sths  * hence all their sectors are reported as allocated.
1029f58c7b35Sths  *
1030f58c7b35Sths  * 'pnum' is set to the number of sectors (including and immediately following
1031f58c7b35Sths  * the specified sector) that are known to be in the same
1032f58c7b35Sths  * allocated/unallocated state.
1033f58c7b35Sths  *
1034f58c7b35Sths  * 'nb_sectors' is the max value 'pnum' should be set to.
1035f58c7b35Sths  */
1036f58c7b35Sths int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
1037f58c7b35Sths 	int *pnum)
1038f58c7b35Sths {
1039f58c7b35Sths     int64_t n;
1040f58c7b35Sths     if (!bs->drv->bdrv_is_allocated) {
1041f58c7b35Sths         if (sector_num >= bs->total_sectors) {
1042f58c7b35Sths             *pnum = 0;
1043f58c7b35Sths             return 0;
1044f58c7b35Sths         }
1045f58c7b35Sths         n = bs->total_sectors - sector_num;
1046f58c7b35Sths         *pnum = (n < nb_sectors) ? (n) : (nb_sectors);
1047f58c7b35Sths         return 1;
1048f58c7b35Sths     }
1049f58c7b35Sths     return bs->drv->bdrv_is_allocated(bs, sector_num, nb_sectors, pnum);
1050f58c7b35Sths }
1051f58c7b35Sths 
1052376253ecSaliguori void bdrv_info(Monitor *mon)
1053b338082bSbellard {
1054b338082bSbellard     BlockDriverState *bs;
1055b338082bSbellard 
1056b338082bSbellard     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
1057376253ecSaliguori         monitor_printf(mon, "%s:", bs->device_name);
1058376253ecSaliguori         monitor_printf(mon, " type=");
1059b338082bSbellard         switch(bs->type) {
1060b338082bSbellard         case BDRV_TYPE_HD:
1061376253ecSaliguori             monitor_printf(mon, "hd");
1062b338082bSbellard             break;
1063b338082bSbellard         case BDRV_TYPE_CDROM:
1064376253ecSaliguori             monitor_printf(mon, "cdrom");
1065b338082bSbellard             break;
1066b338082bSbellard         case BDRV_TYPE_FLOPPY:
1067376253ecSaliguori             monitor_printf(mon, "floppy");
1068b338082bSbellard             break;
1069b338082bSbellard         }
1070376253ecSaliguori         monitor_printf(mon, " removable=%d", bs->removable);
1071b338082bSbellard         if (bs->removable) {
1072376253ecSaliguori             monitor_printf(mon, " locked=%d", bs->locked);
1073b338082bSbellard         }
107419cb3738Sbellard         if (bs->drv) {
1075376253ecSaliguori             monitor_printf(mon, " file=");
1076376253ecSaliguori             monitor_print_filename(mon, bs->filename);
1077fef30743Sths             if (bs->backing_file[0] != '\0') {
1078376253ecSaliguori                 monitor_printf(mon, " backing_file=");
1079376253ecSaliguori                 monitor_print_filename(mon, bs->backing_file);
1080fef30743Sths             }
1081376253ecSaliguori             monitor_printf(mon, " ro=%d", bs->read_only);
1082376253ecSaliguori             monitor_printf(mon, " drv=%s", bs->drv->format_name);
1083376253ecSaliguori             monitor_printf(mon, " encrypted=%d", bdrv_is_encrypted(bs));
1084b338082bSbellard         } else {
1085376253ecSaliguori             monitor_printf(mon, " [not inserted]");
1086b338082bSbellard         }
1087376253ecSaliguori         monitor_printf(mon, "\n");
1088b338082bSbellard     }
1089b338082bSbellard }
1090a36e69ddSths 
1091a36e69ddSths /* The "info blockstats" command. */
1092376253ecSaliguori void bdrv_info_stats(Monitor *mon)
1093a36e69ddSths {
1094a36e69ddSths     BlockDriverState *bs;
1095a36e69ddSths 
1096a36e69ddSths     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
1097376253ecSaliguori         monitor_printf(mon, "%s:"
1098a36e69ddSths                        " rd_bytes=%" PRIu64
1099a36e69ddSths                        " wr_bytes=%" PRIu64
1100a36e69ddSths                        " rd_operations=%" PRIu64
1101a36e69ddSths                        " wr_operations=%" PRIu64
1102ebf53fcdSaliguori                        "\n",
1103a36e69ddSths                        bs->device_name,
1104a36e69ddSths                        bs->rd_bytes, bs->wr_bytes,
1105a36e69ddSths                        bs->rd_ops, bs->wr_ops);
1106a36e69ddSths     }
1107a36e69ddSths }
1108ea2384d3Sbellard 
1109045df330Saliguori const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
1110045df330Saliguori {
1111045df330Saliguori     if (bs->backing_hd && bs->backing_hd->encrypted)
1112045df330Saliguori         return bs->backing_file;
1113045df330Saliguori     else if (bs->encrypted)
1114045df330Saliguori         return bs->filename;
1115045df330Saliguori     else
1116045df330Saliguori         return NULL;
1117045df330Saliguori }
1118045df330Saliguori 
111983f64091Sbellard void bdrv_get_backing_filename(BlockDriverState *bs,
112083f64091Sbellard                                char *filename, int filename_size)
112183f64091Sbellard {
112283f64091Sbellard     if (!bs->backing_hd) {
112383f64091Sbellard         pstrcpy(filename, filename_size, "");
112483f64091Sbellard     } else {
112583f64091Sbellard         pstrcpy(filename, filename_size, bs->backing_file);
112683f64091Sbellard     }
112783f64091Sbellard }
112883f64091Sbellard 
1129faea38e7Sbellard int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
1130faea38e7Sbellard                           const uint8_t *buf, int nb_sectors)
1131faea38e7Sbellard {
1132faea38e7Sbellard     BlockDriver *drv = bs->drv;
1133faea38e7Sbellard     if (!drv)
113419cb3738Sbellard         return -ENOMEDIUM;
1135faea38e7Sbellard     if (!drv->bdrv_write_compressed)
1136faea38e7Sbellard         return -ENOTSUP;
1137faea38e7Sbellard     return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
1138faea38e7Sbellard }
1139faea38e7Sbellard 
1140faea38e7Sbellard int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
1141faea38e7Sbellard {
1142faea38e7Sbellard     BlockDriver *drv = bs->drv;
1143faea38e7Sbellard     if (!drv)
114419cb3738Sbellard         return -ENOMEDIUM;
1145faea38e7Sbellard     if (!drv->bdrv_get_info)
1146faea38e7Sbellard         return -ENOTSUP;
1147faea38e7Sbellard     memset(bdi, 0, sizeof(*bdi));
1148faea38e7Sbellard     return drv->bdrv_get_info(bs, bdi);
1149faea38e7Sbellard }
1150faea38e7Sbellard 
1151178e08a5Saliguori int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size)
1152178e08a5Saliguori {
1153178e08a5Saliguori     BlockDriver *drv = bs->drv;
1154178e08a5Saliguori     if (!drv)
1155178e08a5Saliguori         return -ENOMEDIUM;
1156178e08a5Saliguori     if (!drv->bdrv_put_buffer)
1157178e08a5Saliguori         return -ENOTSUP;
1158178e08a5Saliguori     return drv->bdrv_put_buffer(bs, buf, pos, size);
1159178e08a5Saliguori }
1160178e08a5Saliguori 
1161178e08a5Saliguori int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size)
1162178e08a5Saliguori {
1163178e08a5Saliguori     BlockDriver *drv = bs->drv;
1164178e08a5Saliguori     if (!drv)
1165178e08a5Saliguori         return -ENOMEDIUM;
1166178e08a5Saliguori     if (!drv->bdrv_get_buffer)
1167178e08a5Saliguori         return -ENOTSUP;
1168178e08a5Saliguori     return drv->bdrv_get_buffer(bs, buf, pos, size);
1169178e08a5Saliguori }
1170178e08a5Saliguori 
1171faea38e7Sbellard /**************************************************************/
1172faea38e7Sbellard /* handling of snapshots */
1173faea38e7Sbellard 
1174faea38e7Sbellard int bdrv_snapshot_create(BlockDriverState *bs,
1175faea38e7Sbellard                          QEMUSnapshotInfo *sn_info)
1176faea38e7Sbellard {
1177faea38e7Sbellard     BlockDriver *drv = bs->drv;
1178faea38e7Sbellard     if (!drv)
117919cb3738Sbellard         return -ENOMEDIUM;
1180faea38e7Sbellard     if (!drv->bdrv_snapshot_create)
1181faea38e7Sbellard         return -ENOTSUP;
1182faea38e7Sbellard     return drv->bdrv_snapshot_create(bs, sn_info);
1183faea38e7Sbellard }
1184faea38e7Sbellard 
1185faea38e7Sbellard int bdrv_snapshot_goto(BlockDriverState *bs,
1186faea38e7Sbellard                        const char *snapshot_id)
1187faea38e7Sbellard {
1188faea38e7Sbellard     BlockDriver *drv = bs->drv;
1189faea38e7Sbellard     if (!drv)
119019cb3738Sbellard         return -ENOMEDIUM;
1191faea38e7Sbellard     if (!drv->bdrv_snapshot_goto)
1192faea38e7Sbellard         return -ENOTSUP;
1193faea38e7Sbellard     return drv->bdrv_snapshot_goto(bs, snapshot_id);
1194faea38e7Sbellard }
1195faea38e7Sbellard 
1196faea38e7Sbellard int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
1197faea38e7Sbellard {
1198faea38e7Sbellard     BlockDriver *drv = bs->drv;
1199faea38e7Sbellard     if (!drv)
120019cb3738Sbellard         return -ENOMEDIUM;
1201faea38e7Sbellard     if (!drv->bdrv_snapshot_delete)
1202faea38e7Sbellard         return -ENOTSUP;
1203faea38e7Sbellard     return drv->bdrv_snapshot_delete(bs, snapshot_id);
1204faea38e7Sbellard }
1205faea38e7Sbellard 
1206faea38e7Sbellard int bdrv_snapshot_list(BlockDriverState *bs,
1207faea38e7Sbellard                        QEMUSnapshotInfo **psn_info)
1208faea38e7Sbellard {
1209faea38e7Sbellard     BlockDriver *drv = bs->drv;
1210faea38e7Sbellard     if (!drv)
121119cb3738Sbellard         return -ENOMEDIUM;
1212faea38e7Sbellard     if (!drv->bdrv_snapshot_list)
1213faea38e7Sbellard         return -ENOTSUP;
1214faea38e7Sbellard     return drv->bdrv_snapshot_list(bs, psn_info);
1215faea38e7Sbellard }
1216faea38e7Sbellard 
1217faea38e7Sbellard #define NB_SUFFIXES 4
1218faea38e7Sbellard 
1219faea38e7Sbellard char *get_human_readable_size(char *buf, int buf_size, int64_t size)
1220faea38e7Sbellard {
1221faea38e7Sbellard     static const char suffixes[NB_SUFFIXES] = "KMGT";
1222faea38e7Sbellard     int64_t base;
1223faea38e7Sbellard     int i;
1224faea38e7Sbellard 
1225faea38e7Sbellard     if (size <= 999) {
1226faea38e7Sbellard         snprintf(buf, buf_size, "%" PRId64, size);
1227faea38e7Sbellard     } else {
1228faea38e7Sbellard         base = 1024;
1229faea38e7Sbellard         for(i = 0; i < NB_SUFFIXES; i++) {
1230faea38e7Sbellard             if (size < (10 * base)) {
1231faea38e7Sbellard                 snprintf(buf, buf_size, "%0.1f%c",
1232faea38e7Sbellard                          (double)size / base,
1233faea38e7Sbellard                          suffixes[i]);
1234faea38e7Sbellard                 break;
1235faea38e7Sbellard             } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
1236faea38e7Sbellard                 snprintf(buf, buf_size, "%" PRId64 "%c",
1237faea38e7Sbellard                          ((size + (base >> 1)) / base),
1238faea38e7Sbellard                          suffixes[i]);
1239faea38e7Sbellard                 break;
1240faea38e7Sbellard             }
1241faea38e7Sbellard             base = base * 1024;
1242faea38e7Sbellard         }
1243faea38e7Sbellard     }
1244faea38e7Sbellard     return buf;
1245faea38e7Sbellard }
1246faea38e7Sbellard 
1247faea38e7Sbellard char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
1248faea38e7Sbellard {
1249faea38e7Sbellard     char buf1[128], date_buf[128], clock_buf[128];
12503b9f94e1Sbellard #ifdef _WIN32
12513b9f94e1Sbellard     struct tm *ptm;
12523b9f94e1Sbellard #else
1253faea38e7Sbellard     struct tm tm;
12543b9f94e1Sbellard #endif
1255faea38e7Sbellard     time_t ti;
1256faea38e7Sbellard     int64_t secs;
1257faea38e7Sbellard 
1258faea38e7Sbellard     if (!sn) {
1259faea38e7Sbellard         snprintf(buf, buf_size,
1260faea38e7Sbellard                  "%-10s%-20s%7s%20s%15s",
1261faea38e7Sbellard                  "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
1262faea38e7Sbellard     } else {
1263faea38e7Sbellard         ti = sn->date_sec;
12643b9f94e1Sbellard #ifdef _WIN32
12653b9f94e1Sbellard         ptm = localtime(&ti);
12663b9f94e1Sbellard         strftime(date_buf, sizeof(date_buf),
12673b9f94e1Sbellard                  "%Y-%m-%d %H:%M:%S", ptm);
12683b9f94e1Sbellard #else
1269faea38e7Sbellard         localtime_r(&ti, &tm);
1270faea38e7Sbellard         strftime(date_buf, sizeof(date_buf),
1271faea38e7Sbellard                  "%Y-%m-%d %H:%M:%S", &tm);
12723b9f94e1Sbellard #endif
1273faea38e7Sbellard         secs = sn->vm_clock_nsec / 1000000000;
1274faea38e7Sbellard         snprintf(clock_buf, sizeof(clock_buf),
1275faea38e7Sbellard                  "%02d:%02d:%02d.%03d",
1276faea38e7Sbellard                  (int)(secs / 3600),
1277faea38e7Sbellard                  (int)((secs / 60) % 60),
1278faea38e7Sbellard                  (int)(secs % 60),
1279faea38e7Sbellard                  (int)((sn->vm_clock_nsec / 1000000) % 1000));
1280faea38e7Sbellard         snprintf(buf, buf_size,
1281faea38e7Sbellard                  "%-10s%-20s%7s%20s%15s",
1282faea38e7Sbellard                  sn->id_str, sn->name,
1283faea38e7Sbellard                  get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
1284faea38e7Sbellard                  date_buf,
1285faea38e7Sbellard                  clock_buf);
1286faea38e7Sbellard     }
1287faea38e7Sbellard     return buf;
1288faea38e7Sbellard }
1289faea38e7Sbellard 
129083f64091Sbellard 
1291ea2384d3Sbellard /**************************************************************/
129283f64091Sbellard /* async I/Os */
1293ea2384d3Sbellard 
12943b69e4b9Saliguori BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
1295f141eafeSaliguori                                  QEMUIOVector *qiov, int nb_sectors,
129683f64091Sbellard                                  BlockDriverCompletionFunc *cb, void *opaque)
1297ea2384d3Sbellard {
129883f64091Sbellard     BlockDriver *drv = bs->drv;
1299a36e69ddSths     BlockDriverAIOCB *ret;
1300ea2384d3Sbellard 
130119cb3738Sbellard     if (!drv)
1302ce1a14dcSpbrook         return NULL;
130371d0770cSaliguori     if (bdrv_check_request(bs, sector_num, nb_sectors))
130471d0770cSaliguori         return NULL;
130583f64091Sbellard 
1306f141eafeSaliguori     ret = drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors,
1307f141eafeSaliguori                               cb, opaque);
1308a36e69ddSths 
1309a36e69ddSths     if (ret) {
1310a36e69ddSths 	/* Update stats even though technically transfer has not happened. */
1311a36e69ddSths 	bs->rd_bytes += (unsigned) nb_sectors * SECTOR_SIZE;
1312a36e69ddSths 	bs->rd_ops ++;
1313a36e69ddSths     }
1314a36e69ddSths 
1315a36e69ddSths     return ret;
131683f64091Sbellard }
131783f64091Sbellard 
1318f141eafeSaliguori BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
1319f141eafeSaliguori                                   QEMUIOVector *qiov, int nb_sectors,
132083f64091Sbellard                                   BlockDriverCompletionFunc *cb, void *opaque)
13217674e7bfSbellard {
132283f64091Sbellard     BlockDriver *drv = bs->drv;
1323a36e69ddSths     BlockDriverAIOCB *ret;
132483f64091Sbellard 
132519cb3738Sbellard     if (!drv)
1326ce1a14dcSpbrook         return NULL;
132783f64091Sbellard     if (bs->read_only)
1328ce1a14dcSpbrook         return NULL;
132971d0770cSaliguori     if (bdrv_check_request(bs, sector_num, nb_sectors))
133071d0770cSaliguori         return NULL;
133183f64091Sbellard 
1332f141eafeSaliguori     ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
1333f141eafeSaliguori                                cb, opaque);
1334a36e69ddSths 
1335a36e69ddSths     if (ret) {
1336a36e69ddSths 	/* Update stats even though technically transfer has not happened. */
1337a36e69ddSths 	bs->wr_bytes += (unsigned) nb_sectors * SECTOR_SIZE;
1338a36e69ddSths 	bs->wr_ops ++;
1339a36e69ddSths     }
1340a36e69ddSths 
1341a36e69ddSths     return ret;
134283f64091Sbellard }
134383f64091Sbellard 
134483f64091Sbellard void bdrv_aio_cancel(BlockDriverAIOCB *acb)
134583f64091Sbellard {
13466bbff9a0Saliguori     acb->pool->cancel(acb);
134783f64091Sbellard }
134883f64091Sbellard 
134983f64091Sbellard 
135083f64091Sbellard /**************************************************************/
135183f64091Sbellard /* async block device emulation */
135283f64091Sbellard 
135383f64091Sbellard static void bdrv_aio_bh_cb(void *opaque)
1354beac80cdSbellard {
1355ce1a14dcSpbrook     BlockDriverAIOCBSync *acb = opaque;
1356f141eafeSaliguori 
1357f141eafeSaliguori     if (!acb->is_write)
1358f141eafeSaliguori         qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size);
1359ceb42de8Saliguori     qemu_vfree(acb->bounce);
1360ce1a14dcSpbrook     acb->common.cb(acb->common.opaque, acb->ret);
1361f141eafeSaliguori 
1362ce1a14dcSpbrook     qemu_aio_release(acb);
1363beac80cdSbellard }
1364beac80cdSbellard 
1365f141eafeSaliguori static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
1366f141eafeSaliguori                                             int64_t sector_num,
1367f141eafeSaliguori                                             QEMUIOVector *qiov,
1368f141eafeSaliguori                                             int nb_sectors,
1369f141eafeSaliguori                                             BlockDriverCompletionFunc *cb,
1370f141eafeSaliguori                                             void *opaque,
1371f141eafeSaliguori                                             int is_write)
1372f141eafeSaliguori 
1373ea2384d3Sbellard {
1374ce1a14dcSpbrook     BlockDriverAIOCBSync *acb;
137583f64091Sbellard 
1376ce1a14dcSpbrook     acb = qemu_aio_get(bs, cb, opaque);
1377f141eafeSaliguori     acb->is_write = is_write;
1378f141eafeSaliguori     acb->qiov = qiov;
1379f141eafeSaliguori     acb->bounce = qemu_memalign(512, qiov->size);
1380f141eafeSaliguori 
1381ce1a14dcSpbrook     if (!acb->bh)
1382ce1a14dcSpbrook         acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
1383f141eafeSaliguori 
1384f141eafeSaliguori     if (is_write) {
1385f141eafeSaliguori         qemu_iovec_to_buffer(acb->qiov, acb->bounce);
1386f141eafeSaliguori         acb->ret = bdrv_write(bs, sector_num, acb->bounce, nb_sectors);
1387f141eafeSaliguori     } else {
1388f141eafeSaliguori         acb->ret = bdrv_read(bs, sector_num, acb->bounce, nb_sectors);
1389f141eafeSaliguori     }
1390f141eafeSaliguori 
1391ce1a14dcSpbrook     qemu_bh_schedule(acb->bh);
1392f141eafeSaliguori 
1393ce1a14dcSpbrook     return &acb->common;
13947a6cba61Spbrook }
13957a6cba61Spbrook 
1396f141eafeSaliguori static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
1397f141eafeSaliguori         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
1398ce1a14dcSpbrook         BlockDriverCompletionFunc *cb, void *opaque)
139983f64091Sbellard {
1400f141eafeSaliguori     return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
140183f64091Sbellard }
140283f64091Sbellard 
1403f141eafeSaliguori static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
1404f141eafeSaliguori         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
1405f141eafeSaliguori         BlockDriverCompletionFunc *cb, void *opaque)
1406f141eafeSaliguori {
1407f141eafeSaliguori     return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
1408f141eafeSaliguori }
1409f141eafeSaliguori 
1410f141eafeSaliguori 
1411ce1a14dcSpbrook static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
141283f64091Sbellard {
1413ce1a14dcSpbrook     BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
1414ce1a14dcSpbrook     qemu_bh_cancel(acb->bh);
1415ce1a14dcSpbrook     qemu_aio_release(acb);
141683f64091Sbellard }
141783f64091Sbellard 
141883f64091Sbellard /**************************************************************/
141983f64091Sbellard /* sync block device emulation */
142083f64091Sbellard 
142183f64091Sbellard static void bdrv_rw_em_cb(void *opaque, int ret)
142283f64091Sbellard {
142383f64091Sbellard     *(int *)opaque = ret;
142483f64091Sbellard }
142583f64091Sbellard 
142683f64091Sbellard #define NOT_DONE 0x7fffffff
142783f64091Sbellard 
142883f64091Sbellard static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
142983f64091Sbellard                         uint8_t *buf, int nb_sectors)
143083f64091Sbellard {
1431ce1a14dcSpbrook     int async_ret;
1432ce1a14dcSpbrook     BlockDriverAIOCB *acb;
1433f141eafeSaliguori     struct iovec iov;
1434f141eafeSaliguori     QEMUIOVector qiov;
143583f64091Sbellard 
143683f64091Sbellard     async_ret = NOT_DONE;
1437*3f4cb3d3Sblueswir1     iov.iov_base = (void *)buf;
1438f141eafeSaliguori     iov.iov_len = nb_sectors * 512;
1439f141eafeSaliguori     qemu_iovec_init_external(&qiov, &iov, 1);
1440f141eafeSaliguori     acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors,
144183f64091Sbellard         bdrv_rw_em_cb, &async_ret);
1442baf35cb9Saliguori     if (acb == NULL)
1443ce1a14dcSpbrook         return -1;
1444baf35cb9Saliguori 
144583f64091Sbellard     while (async_ret == NOT_DONE) {
144683f64091Sbellard         qemu_aio_wait();
144783f64091Sbellard     }
1448baf35cb9Saliguori 
144983f64091Sbellard     return async_ret;
145083f64091Sbellard }
145183f64091Sbellard 
145283f64091Sbellard static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
145383f64091Sbellard                          const uint8_t *buf, int nb_sectors)
145483f64091Sbellard {
1455ce1a14dcSpbrook     int async_ret;
1456ce1a14dcSpbrook     BlockDriverAIOCB *acb;
1457f141eafeSaliguori     struct iovec iov;
1458f141eafeSaliguori     QEMUIOVector qiov;
145983f64091Sbellard 
146083f64091Sbellard     async_ret = NOT_DONE;
1461f141eafeSaliguori     iov.iov_base = (void *)buf;
1462f141eafeSaliguori     iov.iov_len = nb_sectors * 512;
1463f141eafeSaliguori     qemu_iovec_init_external(&qiov, &iov, 1);
1464f141eafeSaliguori     acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors,
146583f64091Sbellard         bdrv_rw_em_cb, &async_ret);
1466baf35cb9Saliguori     if (acb == NULL)
1467ce1a14dcSpbrook         return -1;
146883f64091Sbellard     while (async_ret == NOT_DONE) {
146983f64091Sbellard         qemu_aio_wait();
147083f64091Sbellard     }
147183f64091Sbellard     return async_ret;
147283f64091Sbellard }
1473ea2384d3Sbellard 
1474ea2384d3Sbellard void bdrv_init(void)
1475ea2384d3Sbellard {
1476ea2384d3Sbellard     bdrv_register(&bdrv_raw);
147719cb3738Sbellard     bdrv_register(&bdrv_host_device);
1478ea2384d3Sbellard #ifndef _WIN32
1479ea2384d3Sbellard     bdrv_register(&bdrv_cow);
1480ea2384d3Sbellard #endif
1481ea2384d3Sbellard     bdrv_register(&bdrv_qcow);
1482ea2384d3Sbellard     bdrv_register(&bdrv_vmdk);
14833c56521bSbellard     bdrv_register(&bdrv_cloop);
1484585d0ed9Sbellard     bdrv_register(&bdrv_dmg);
1485a8753c34Sbellard     bdrv_register(&bdrv_bochs);
14866a0f9e82Sbellard     bdrv_register(&bdrv_vpc);
1487712e7874Sbellard     bdrv_register(&bdrv_vvfat);
1488faea38e7Sbellard     bdrv_register(&bdrv_qcow2);
14896ada7453Sths     bdrv_register(&bdrv_parallels);
149075818250Sths     bdrv_register(&bdrv_nbd);
1491ea2384d3Sbellard }
1492ce1a14dcSpbrook 
14936bbff9a0Saliguori void aio_pool_init(AIOPool *pool, int aiocb_size,
14946bbff9a0Saliguori                    void (*cancel)(BlockDriverAIOCB *acb))
1495ce1a14dcSpbrook {
14966bbff9a0Saliguori     pool->aiocb_size = aiocb_size;
14976bbff9a0Saliguori     pool->cancel = cancel;
14986bbff9a0Saliguori     pool->free_aiocb = NULL;
14996bbff9a0Saliguori }
15006bbff9a0Saliguori 
15016bbff9a0Saliguori void *qemu_aio_get_pool(AIOPool *pool, BlockDriverState *bs,
15026bbff9a0Saliguori                         BlockDriverCompletionFunc *cb, void *opaque)
15036bbff9a0Saliguori {
1504ce1a14dcSpbrook     BlockDriverAIOCB *acb;
1505ce1a14dcSpbrook 
15066bbff9a0Saliguori     if (pool->free_aiocb) {
15076bbff9a0Saliguori         acb = pool->free_aiocb;
15086bbff9a0Saliguori         pool->free_aiocb = acb->next;
1509ce1a14dcSpbrook     } else {
15106bbff9a0Saliguori         acb = qemu_mallocz(pool->aiocb_size);
15116bbff9a0Saliguori         acb->pool = pool;
1512ce1a14dcSpbrook     }
1513ce1a14dcSpbrook     acb->bs = bs;
1514ce1a14dcSpbrook     acb->cb = cb;
1515ce1a14dcSpbrook     acb->opaque = opaque;
1516ce1a14dcSpbrook     return acb;
1517ce1a14dcSpbrook }
1518ce1a14dcSpbrook 
15196bbff9a0Saliguori void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
15206bbff9a0Saliguori                    void *opaque)
15216bbff9a0Saliguori {
15226bbff9a0Saliguori     return qemu_aio_get_pool(&bs->drv->aio_pool, bs, cb, opaque);
15236bbff9a0Saliguori }
15246bbff9a0Saliguori 
1525ce1a14dcSpbrook void qemu_aio_release(void *p)
1526ce1a14dcSpbrook {
15276bbff9a0Saliguori     BlockDriverAIOCB *acb = (BlockDriverAIOCB *)p;
15286bbff9a0Saliguori     AIOPool *pool = acb->pool;
15296bbff9a0Saliguori     acb->next = pool->free_aiocb;
15306bbff9a0Saliguori     pool->free_aiocb = acb;
1531ce1a14dcSpbrook }
153219cb3738Sbellard 
153319cb3738Sbellard /**************************************************************/
153419cb3738Sbellard /* removable device support */
153519cb3738Sbellard 
153619cb3738Sbellard /**
153719cb3738Sbellard  * Return TRUE if the media is present
153819cb3738Sbellard  */
153919cb3738Sbellard int bdrv_is_inserted(BlockDriverState *bs)
154019cb3738Sbellard {
154119cb3738Sbellard     BlockDriver *drv = bs->drv;
154219cb3738Sbellard     int ret;
154319cb3738Sbellard     if (!drv)
154419cb3738Sbellard         return 0;
154519cb3738Sbellard     if (!drv->bdrv_is_inserted)
154619cb3738Sbellard         return 1;
154719cb3738Sbellard     ret = drv->bdrv_is_inserted(bs);
154819cb3738Sbellard     return ret;
154919cb3738Sbellard }
155019cb3738Sbellard 
155119cb3738Sbellard /**
155219cb3738Sbellard  * Return TRUE if the media changed since the last call to this
155319cb3738Sbellard  * function. It is currently only used for floppy disks
155419cb3738Sbellard  */
155519cb3738Sbellard int bdrv_media_changed(BlockDriverState *bs)
155619cb3738Sbellard {
155719cb3738Sbellard     BlockDriver *drv = bs->drv;
155819cb3738Sbellard     int ret;
155919cb3738Sbellard 
156019cb3738Sbellard     if (!drv || !drv->bdrv_media_changed)
156119cb3738Sbellard         ret = -ENOTSUP;
156219cb3738Sbellard     else
156319cb3738Sbellard         ret = drv->bdrv_media_changed(bs);
156419cb3738Sbellard     if (ret == -ENOTSUP)
156519cb3738Sbellard         ret = bs->media_changed;
156619cb3738Sbellard     bs->media_changed = 0;
156719cb3738Sbellard     return ret;
156819cb3738Sbellard }
156919cb3738Sbellard 
157019cb3738Sbellard /**
157119cb3738Sbellard  * If eject_flag is TRUE, eject the media. Otherwise, close the tray
157219cb3738Sbellard  */
157319cb3738Sbellard void bdrv_eject(BlockDriverState *bs, int eject_flag)
157419cb3738Sbellard {
157519cb3738Sbellard     BlockDriver *drv = bs->drv;
157619cb3738Sbellard     int ret;
157719cb3738Sbellard 
157819cb3738Sbellard     if (!drv || !drv->bdrv_eject) {
157919cb3738Sbellard         ret = -ENOTSUP;
158019cb3738Sbellard     } else {
158119cb3738Sbellard         ret = drv->bdrv_eject(bs, eject_flag);
158219cb3738Sbellard     }
158319cb3738Sbellard     if (ret == -ENOTSUP) {
158419cb3738Sbellard         if (eject_flag)
158519cb3738Sbellard             bdrv_close(bs);
158619cb3738Sbellard     }
158719cb3738Sbellard }
158819cb3738Sbellard 
158919cb3738Sbellard int bdrv_is_locked(BlockDriverState *bs)
159019cb3738Sbellard {
159119cb3738Sbellard     return bs->locked;
159219cb3738Sbellard }
159319cb3738Sbellard 
159419cb3738Sbellard /**
159519cb3738Sbellard  * Lock or unlock the media (if it is locked, the user won't be able
159619cb3738Sbellard  * to eject it manually).
159719cb3738Sbellard  */
159819cb3738Sbellard void bdrv_set_locked(BlockDriverState *bs, int locked)
159919cb3738Sbellard {
160019cb3738Sbellard     BlockDriver *drv = bs->drv;
160119cb3738Sbellard 
160219cb3738Sbellard     bs->locked = locked;
160319cb3738Sbellard     if (drv && drv->bdrv_set_locked) {
160419cb3738Sbellard         drv->bdrv_set_locked(bs, locked);
160519cb3738Sbellard     }
160619cb3738Sbellard }
1607985a03b0Sths 
1608985a03b0Sths /* needed for generic scsi interface */
1609985a03b0Sths 
1610985a03b0Sths int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1611985a03b0Sths {
1612985a03b0Sths     BlockDriver *drv = bs->drv;
1613985a03b0Sths 
1614985a03b0Sths     if (drv && drv->bdrv_ioctl)
1615985a03b0Sths         return drv->bdrv_ioctl(bs, req, buf);
1616985a03b0Sths     return -ENOTSUP;
1617985a03b0Sths }
16187d780669Saliguori 
1619221f715dSaliguori BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
1620221f715dSaliguori         unsigned long int req, void *buf,
16217d780669Saliguori         BlockDriverCompletionFunc *cb, void *opaque)
16227d780669Saliguori {
1623221f715dSaliguori     BlockDriver *drv = bs->drv;
16247d780669Saliguori 
1625221f715dSaliguori     if (drv && drv->bdrv_aio_ioctl)
1626221f715dSaliguori         return drv->bdrv_aio_ioctl(bs, req, buf, cb, opaque);
1627221f715dSaliguori     return NULL;
16287d780669Saliguori }
1629