From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55417) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f95WM-0001fq-De for qemu-devel@nongnu.org; Thu, 19 Apr 2018 05:06:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f95WG-0001Hx-32 for qemu-devel@nongnu.org; Thu, 19 Apr 2018 05:06:26 -0400 Date: Thu, 19 Apr 2018 10:05:47 +0100 From: "Dr. David Alan Gilbert" Message-ID: <20180419090546.GA2730@work-vm> References: <20180419075232.31407-1-stefanha@redhat.com> <20180419075232.31407-3-stefanha@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20180419075232.31407-3-stefanha@redhat.com> Subject: Re: [Qemu-devel] [RFC 2/2] block/file-posix: verify page cache is not used List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Stefan Hajnoczi Cc: qemu-devel@nongnu.org, Max Reitz , Kevin Wolf , Sergio Lopez , qemu-block@nongnu.org * Stefan Hajnoczi (stefanha@redhat.com) wrote: > This commit is for debugging only. Do not merge it. > > mincore(2) checks whether pages are resident. Use it to verify that > page cache has been dropped. > > You can trigger a verification failure by mmapping the image file from > another process and loading a byte from a page so that it becomes > resident. bdrv_co_invalidate_cache() will fail while the process is > alive. It doesn't seem a bad diagnostic to keep in (with a switch to activate) for when we're faced with some weird corruption on some weird storage system. Dave > Signed-off-by: Stefan Hajnoczi > --- > block/file-posix.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 71 insertions(+) > > diff --git a/block/file-posix.c b/block/file-posix.c > index df4f52919f..d3105269c6 100644 > --- a/block/file-posix.c > +++ b/block/file-posix.c > @@ -2236,6 +2236,75 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, > return ret | BDRV_BLOCK_OFFSET_VALID; > } > > +static bool is_mincore(void *addr, size_t length) > +{ > + size_t vec_len = DIV_ROUND_UP(length, sysconf(_SC_PAGESIZE)); > + unsigned char *vec; > + size_t i; > + int ret; > + bool incore = false; > + > + vec = g_malloc(vec_len); > + ret = mincore(addr, length, vec); > + if (ret < 0) { > + incore = true; > + goto out; > + } > + > + for (i = 0; i < vec_len; i++) { > + if (vec[i] & 0x1) { > + incore = true; > + break; > + } > + } > + > +out: > + g_free(vec); > + return incore; > +} > + > +static void check_not_in_page_cache(BlockDriverState *bs, Error **errp) > +{ > + const size_t WINDOW_SIZE = 128 * 1024 * 1024; > + BDRVRawState *s = bs->opaque; > + void *window = NULL; > + size_t length = 0; > + off_t end; > + off_t offset; > + > + end = raw_getlength(bs); > + > + for (offset = 0; offset < end; offset += WINDOW_SIZE) { > + void *new_window; > + size_t new_length = MIN(end - offset, WINDOW_SIZE); > + > + if (new_length != length) { > + munmap(window, length); > + window = NULL; > + length = 0; > + } > + > + new_window = mmap(window, new_length, PROT_NONE, MAP_PRIVATE, > + s->fd, offset); > + if (new_window == MAP_FAILED) { > + error_setg_errno(errp, errno, "mmap failed"); > + break; > + } > + > + window = new_window; > + length = new_length; > + > + if (is_mincore(window, length)) { > + error_setg(errp, "page cache still in use!"); > + break; > + } > + } > + > + if (window) { > + munmap(window, length); > + } > +} > + > static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs, > Error **errp) > { > @@ -2270,6 +2339,8 @@ static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs, > return; > } > #endif /* __linux__ */ > + > + check_not_in_page_cache(bs, errp); > } > > static coroutine_fn BlockAIOCB *raw_aio_pdiscard(BlockDriverState *bs, > -- > 2.14.3 > -- Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK