From: Xu Wang <gesaint@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, famz@redhat.com, stefanha@gmail.com,
wdongxu@linux.vnet.ibm.com, Xu Wang <cngesaint@gmail.com>,
xiawenc@linux.vnet.ibm.com
Subject: [Qemu-devel] [PATCH V5 1/6] block/qemu-img: Refine and export infinite loop checking in collect_image_info_list()
Date: Fri, 2 Aug 2013 05:02:12 -0400 [thread overview]
Message-ID: <1375434137-4452-2-git-send-email-gesaint@linux.vnet.ibm.com> (raw)
In-Reply-To: <1375434137-4452-1-git-send-email-gesaint@linux.vnet.ibm.com>
From: Xu Wang <cngesaint@gmail.com>
If there is a loop exists in the backing file chain, many problems
could be caused by it, such as no response and segment fault during
system boot. Hence stopping backing file loop appear is very necessary.
This patch refine and export loop checking function from collect_image_
info_list() to block.c and build a independent function named bdrv_
backing_file_loop_check().
Signed-off-by: Xu Wang <cngesaint@gmail.com>
---
block.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++
include/block/block.h | 4 +++
qemu-img.c | 44 ++++++++++-------------
3 files changed, 118 insertions(+), 26 deletions(-)
diff --git a/block.c b/block.c
index 183fec8..aea653d 100644
--- a/block.c
+++ b/block.c
@@ -4433,6 +4433,102 @@ bdrv_acct_done(BlockDriverState *bs, BlockAcctCookie *cookie)
bs->total_time_ns[cookie->type] += get_clock() - cookie->start_time_ns;
}
+static gboolean str_equal_func(gconstpointer a, gconstpointer b)
+{
+ return strcmp(a, b) == 0;
+}
+
+/**
+ * Check backing file chain if there is a loop in it.
+ *
+ * @filename: topmost image filename, absolute or relative path is OK.
+ * @fmt: topmost image format (may be NULL to autodetect)
+ * @backing_file: if this value is set, @filename inode (-1 if it doesn't
+ * exist) will insert into hash table directly. Loop check
+ * starts from it. Absolute or relative path is OK for it.
+ * @backing_format: format of backing file
+ *
+ * Returns: true for backing file loop or error happened, false for no loop.
+ */
+bool bdrv_backing_file_loop_check(const char *filename, const char *fmt,
+ const char *backing_file,
+ const char *backing_format) {
+ GHashTable *inodes;
+ BlockDriverState *bs;
+ BlockDriver *drv;
+ struct stat sbuf;
+ long inode = 0;
+ int ret;
+ char fbuf[1024];
+
+ inodes = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
+
+ if (backing_file) {
+ /* Check if file exists. */
+ if (access(filename, F_OK)) {
+ inode = -1;
+ } else {
+ if (stat(filename, &sbuf) == -1) {
+ error_report("Get file %s stat failed.", filename);
+ goto err;
+ }
+ inode = (long)sbuf.st_ino;
+ }
+
+ filename = backing_file;
+ fmt = backing_format;
+ g_hash_table_insert(inodes, (gpointer)&inode, NULL);
+ }
+
+ while (filename && (filename[0] != '\0')) {
+ if (stat(filename, &sbuf) == -1) {
+ error_report("Get file %s stat failed.", filename);
+ goto err;
+ }
+ inode = (long)sbuf.st_ino;
+
+ if (g_hash_table_lookup_extended(inodes, &inode, NULL, NULL)) {
+ error_report("Backing file '%s' creates an infinite loop.",
+ filename);
+ goto err;
+ }
+ g_hash_table_insert(inodes, (gpointer)&inode, NULL);
+
+ bs = bdrv_new("image");
+
+ if (fmt) {
+ drv = bdrv_find_format(fmt);
+ if (!drv) {
+ error_report("Unknown file format '%s'", fmt);
+ bdrv_delete(bs);
+ goto err;
+ }
+ } else {
+ drv = NULL;
+ }
+
+ ret = bdrv_open(bs, filename, NULL,
+ BDRV_O_CACHE_WB | BDRV_O_NO_BACKING, drv);
+ if (ret < 0) {
+ error_report("Could not open '%s': %s", filename, strerror(-ret));
+ bdrv_delete(bs);
+ goto err;
+ }
+
+ bdrv_get_backing_filename(bs, fbuf, sizeof(fbuf));
+ filename = fbuf;
+ fmt = NULL;
+
+ bdrv_delete(bs);
+ }
+ g_hash_table_destroy(inodes);
+ return false;
+
+err:
+ g_hash_table_destroy(inodes);
+ return true;
+}
+
void bdrv_img_create(const char *filename, const char *fmt,
const char *base_filename, const char *base_fmt,
char *options, uint64_t img_size, int flags,
diff --git a/include/block/block.h b/include/block/block.h
index dd8eca1..3dc29bb 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -333,6 +333,10 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
int64_t pos, int size);
+bool bdrv_backing_file_loop_check(const char *filename, const char *fmt,
+ const char *backing_file,
+ const char *backing_format);
+
void bdrv_img_create(const char *filename, const char *fmt,
const char *base_filename, const char *base_fmt,
char *options, uint64_t img_size, int flags,
diff --git a/qemu-img.c b/qemu-img.c
index f8c97d3..4f01b0a 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1620,11 +1620,6 @@ static void dump_human_image_info_list(ImageInfoList *list)
}
}
-static gboolean str_equal_func(gconstpointer a, gconstpointer b)
-{
- return strcmp(a, b) == 0;
-}
-
/**
* Open an image file chain and return an ImageInfoList
*
@@ -1642,30 +1637,24 @@ static ImageInfoList *collect_image_info_list(const char *filename,
bool chain)
{
ImageInfoList *head = NULL;
+ BlockDriverState *bs;
+ ImageInfoList *elem;
ImageInfoList **last = &head;
- GHashTable *filenames;
+ ImageInfo *info;
Error *err = NULL;
+ int flags = BDRV_O_FLAGS;
- filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
-
- while (filename) {
- BlockDriverState *bs;
- ImageInfo *info;
- ImageInfoList *elem;
-
- if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) {
- error_report("Backing file '%s' creates an infinite loop.",
- filename);
- goto err;
- }
- g_hash_table_insert(filenames, (gpointer)filename, NULL);
+ if (!chain) {
+ flags |= BDRV_O_NO_BACKING;
+ }
- bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING,
- false, false);
- if (!bs) {
- goto err;
- }
+ bs = bdrv_new_open(filename, fmt, flags,
+ false, false);
+ if (!bs) {
+ goto err;
+ }
+ while (filename) {
bdrv_query_image_info(bs, &info, &err);
if (error_is_set(&err)) {
error_report("%s", error_get_pretty(err));
@@ -1690,14 +1679,17 @@ static ImageInfoList *collect_image_info_list(const char *filename,
if (info->has_backing_filename_format) {
fmt = info->backing_filename_format;
}
+
+ if (filename) {
+ bs = bdrv_find_backing_image(bs, filename);
+ }
}
}
- g_hash_table_destroy(filenames);
+
return head;
err:
qapi_free_ImageInfoList(head);
- g_hash_table_destroy(filenames);
return NULL;
}
--
1.8.1.4
next prev parent reply other threads:[~2013-08-02 9:13 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-02 9:02 [Qemu-devel] [PATCH V5 0/6] Refine and export backing file loop check Xu Wang
2013-08-02 9:02 ` Xu Wang [this message]
2013-08-02 22:09 ` [Qemu-devel] [PATCH V5 1/6] block/qemu-img: Refine and export infinite loop checking in collect_image_info_list() Eric Blake
2013-10-11 8:27 ` Xu Wang
2013-08-02 9:02 ` [Qemu-devel] [PATCH V5 2/6] qemu-img: Add infinite loop checking in bdrv_new_open() Xu Wang
2013-08-02 22:16 ` Eric Blake
2013-08-02 9:02 ` [Qemu-devel] [PATCH V5 3/6] block: Add WIN32 platform support for backing_file_loop_check() Xu Wang
2013-08-02 22:27 ` Eric Blake
2013-08-02 9:02 ` [Qemu-devel] [PATCH V5 4/6] block: Check infinite loop in bdrv_img_create() Xu Wang
2013-08-02 22:29 ` Eric Blake
2013-08-02 9:02 ` [Qemu-devel] [PATCH V5 5/6] block: Add backing file loop check in change_backing_file() Xu Wang
2013-08-02 22:31 ` Eric Blake
2013-08-02 9:02 ` [Qemu-devel] [PATCH V5 6/6] block: Add infinite loop check in drive_init() Xu Wang
2013-08-02 22:33 ` Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1375434137-4452-2-git-send-email-gesaint@linux.vnet.ibm.com \
--to=gesaint@linux.vnet.ibm.com \
--cc=cngesaint@gmail.com \
--cc=famz@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@gmail.com \
--cc=wdongxu@linux.vnet.ibm.com \
--cc=xiawenc@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).