From patchwork Thu Aug 30 18:47:09 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Cody X-Patchwork-Id: 180867 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D415C2C0201 for ; Fri, 31 Aug 2012 05:43:56 +1000 (EST) Received: from localhost ([::1]:43009 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T79mn-0005sy-EG for incoming@patchwork.ozlabs.org; Thu, 30 Aug 2012 14:48:13 -0400 Received: from eggs.gnu.org ([208.118.235.92]:40180) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T79mD-0004XI-I3 for qemu-devel@nongnu.org; Thu, 30 Aug 2012 14:47:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1T79mB-0005Ha-Bp for qemu-devel@nongnu.org; Thu, 30 Aug 2012 14:47:37 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44895) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T79mB-0005HF-4I for qemu-devel@nongnu.org; Thu, 30 Aug 2012 14:47:35 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q7UIlPN4022219 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 30 Aug 2012 14:47:25 -0400 Received: from localhost (ovpn-112-23.phx2.redhat.com [10.3.112.23]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q7UIlND3011021 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Thu, 30 Aug 2012 14:47:24 -0400 From: Jeff Cody To: qemu-devel@nongnu.org Date: Thu, 30 Aug 2012 14:47:09 -0400 Message-Id: <7ad1da59f3ef71e4c99c083a0675508ca9279c53.1346352124.git.jcody@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, pbonzini@redhat.com, stefanha@gmail.com, eblake@redhat.com, supriyak@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH 3/7] block: raw-posix image file reopen X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This is derived from the Supriya Kannery's reopen patches. This contains the raw-posix driver changes for the bdrv_reopen_* functions. All changes are staged into a temporary scratch buffer during the prepare() stage, and copied over to the live structure during commit(). Upon abort(), all changes are abandoned, and the live structures are unmodified. The _prepare() will create an extra fd - either by means of a dup, if possible, or opening a new fd if not (for instance, access control changes). Upon _commit(), the original fd is closed and the new fd is used. Upon _abort(), the duplicate/new fd is closed. Signed-off-by: Jeff Cody --- block/raw-posix.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 139 insertions(+), 14 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index 6be20b1..48086d7 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -140,6 +140,15 @@ typedef struct BDRVRawState { #endif } BDRVRawState; +typedef struct BDRVRawReopenState { + BDRVReopenState reopen_state; + int fd; + int open_flags; + uint8_t *aligned_buf; + unsigned aligned_buf_size; + BDRVRawState *stash_s; +} BDRVRawReopenState; + static int fd_open(BlockDriverState *bs); static int64_t raw_getlength(BlockDriverState *bs); @@ -185,6 +194,28 @@ static int raw_normalize_devicepath(const char **filename) } #endif +static void raw_parse_flags(int bdrv_flags, int *open_flags) +{ + assert(open_flags != NULL); + + *open_flags |= O_BINARY; + *open_flags &= ~O_ACCMODE; + if (bdrv_flags & BDRV_O_RDWR) { + *open_flags |= O_RDWR; + } else { + *open_flags |= O_RDONLY; + } + + /* Use O_DSYNC for write-through caching, no flags for write-back caching, + * and O_DIRECT for no caching. */ + if ((bdrv_flags & BDRV_O_NOCACHE)) { + *open_flags |= O_DIRECT; + } + if (!(bdrv_flags & BDRV_O_CACHE_WB)) { + *open_flags |= O_DSYNC; + } +} + static int raw_open_common(BlockDriverState *bs, const char *filename, int bdrv_flags, int open_flags) { @@ -196,20 +227,8 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, return ret; } - s->open_flags = open_flags | O_BINARY; - s->open_flags &= ~O_ACCMODE; - if (bdrv_flags & BDRV_O_RDWR) { - s->open_flags |= O_RDWR; - } else { - s->open_flags |= O_RDONLY; - } - - /* Use O_DSYNC for write-through caching, no flags for write-back caching, - * and O_DIRECT for no caching. */ - if ((bdrv_flags & BDRV_O_NOCACHE)) - s->open_flags |= O_DIRECT; - if (!(bdrv_flags & BDRV_O_CACHE_WB)) - s->open_flags |= O_DSYNC; + s->open_flags = open_flags; + raw_parse_flags(bdrv_flags, &s->open_flags); s->fd = -1; fd = qemu_open(filename, s->open_flags, 0644); @@ -283,6 +302,109 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) return raw_open_common(bs, filename, flags, 0); } +static int raw_reopen_prepare(BDRVReopenState *state, Error **errp) +{ + BDRVRawState *s; + BDRVRawReopenState *raw_s; + int ret = 0; + + assert(state != NULL); + assert(state->bs != NULL); + + s = state->bs->opaque; + + state->opaque = g_malloc0(sizeof(BDRVRawReopenState)); + raw_s = state->opaque; + + raw_parse_flags(state->flags, &raw_s->open_flags); + + /* + * If we didn't have BDRV_O_NOCACHE set before, we may not have allocated + * aligned_buf + */ + if ((state->flags & BDRV_O_NOCACHE)) { + /* + * Allocate a buffer for read/modify/write cycles. Choose the size + * pessimistically as we don't know the block size yet. + */ + raw_s->aligned_buf_size = 32 * MAX_BLOCKSIZE; + raw_s->aligned_buf = qemu_memalign(MAX_BLOCKSIZE, + raw_s->aligned_buf_size); + + if (raw_s->aligned_buf == NULL) { + ret = -1; + goto error; + } + } + + int fcntl_flags = O_APPEND | O_ASYNC | O_NONBLOCK; +#ifdef O_NOATIME + fcntl_flags |= O_NOATIME; +#endif + if ((raw_s->open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) { + /* dup the original fd */ + /* TODO: use qemu fcntl wrapper */ + raw_s->fd = fcntl(s->fd, F_DUPFD_CLOEXEC, 0); + if (raw_s->fd == -1) { + ret = -1; + goto error; + } + ret = fcntl_setfl(raw_s->fd, raw_s->open_flags); + } else { + raw_s->fd = qemu_open(state->bs->filename, raw_s->open_flags, 0644); + if (raw_s->fd == -1) { + ret = -1; + } + } +error: + return ret; +} + + +static void raw_reopen_commit(BDRVReopenState *state) +{ + BDRVRawReopenState *raw_s = state->opaque; + BDRVRawState *s = state->bs->opaque; + + if (raw_s->aligned_buf != NULL) { + if (s->aligned_buf) { + qemu_vfree(s->aligned_buf); + } + s->aligned_buf = raw_s->aligned_buf; + s->aligned_buf_size = raw_s->aligned_buf_size; + } + + s->open_flags = raw_s->open_flags; + + close(s->fd); + s->fd = raw_s->fd; + + g_free(state->opaque); + state->opaque = NULL; +} + + +static void raw_reopen_abort(BDRVReopenState *state) +{ + BDRVRawReopenState *raw_s = state->opaque; + + /* nothing to do if NULL, we didn't get far enough */ + if (raw_s == NULL) { + return; + } + + if (raw_s->fd >= 0) { + close(raw_s->fd); + raw_s->fd = -1; + if (raw_s->aligned_buf != NULL) { + qemu_vfree(raw_s->aligned_buf); + } + } + g_free(state->opaque); + state->opaque = NULL; +} + + /* XXX: use host sector size if necessary with: #ifdef DIOCGSECTORSIZE { @@ -735,6 +857,9 @@ static BlockDriver bdrv_file = { .instance_size = sizeof(BDRVRawState), .bdrv_probe = NULL, /* no probe for protocols */ .bdrv_file_open = raw_open, + .bdrv_reopen_prepare = raw_reopen_prepare, + .bdrv_reopen_commit = raw_reopen_commit, + .bdrv_reopen_abort = raw_reopen_abort, .bdrv_close = raw_close, .bdrv_create = raw_create, .bdrv_co_discard = raw_co_discard,