raw-win32 driver changes for bdrv_reopen_xx functions to
safely reopen image files. Reopening of image files while
changing hostcache dynamically is handled here.

Signed-off-by: Supriya Kannery <supri...@linux.vnet.ibm.com>
Signed-off-by: Shrinidhi Joshi <spjosh...@gmail.com>

---
Index: qemu/block/raw-win32.c
===================================================================
--- qemu.orig/block/raw-win32.c
+++ qemu/block/raw-win32.c
@@ -26,18 +26,27 @@
 #include "block_int.h"
 #include "module.h"
 #include <windows.h>
+#include <winbase.h>
 #include <winioctl.h>
 
 #define FTYPE_FILE 0
 #define FTYPE_CD     1
 #define FTYPE_HARDDISK 2
+#define WINDOWS_VISTA 6
 
 typedef struct BDRVRawState {
     HANDLE hfile;
     int type;
     char drive_path[16]; /* format: "d:\" */
+    DWORD overlapped;
 } BDRVRawState;
 
+typedef struct BDRVRawReopenState {
+    BDRVReopenState reopen_state;
+    HANDLE stash_hfile;
+    DWORD  stash_overlapped;
+} BDRVRawReopenState;
+
 int qemu_ftruncate64(int fd, int64_t length)
 {
     LARGE_INTEGER li;
@@ -106,9 +115,96 @@ static int raw_open(BlockDriverState *bs
             return -EACCES;
         return -1;
     }
+    s->overlapped = overlapped;
     return 0;
 }
 
+static int raw_reopen_prepare(BlockDriverState *bs, BDRVReopenState **prs,
+                              int flags)
+{
+    BDRVRawReopenState *raw_rs = g_malloc0(sizeof(BDRVRawReopenState));
+    BDRVRawState *s = bs->opaque;
+    int ret = 0;
+    OSVERSIONINFO osvi;
+    BOOL bIsWindowsVistaorLater;
+
+    raw_rs->bs = bs;
+    raw_rs->stash_hfile = s->hfile;
+    raw_rs->stash_overlapped = s->overlapped;
+    *prs = raw_rs;
+
+    if (flags & BDRV_O_NOCACHE) {
+        s->overlapped |= FILE_FLAG_NO_BUFFERING;
+    } else {
+        s->overlapped &= ~FILE_FLAG_NO_BUFFERING;
+    }
+
+    if (!(flags & BDRV_O_CACHE_WB)) {
+        s->overlapped |= FILE_FLAG_WRITE_THROUGH;
+    } else {
+        s->overlapped &= ~FILE_FLAG_WRITE_THROUGH;
+    }
+
+    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+    GetVersionEx(&osvi);
+
+    if (osvi.dwMajorVersion >= WINDOWS_VISTA) {
+        s->hfile = ReOpenFile(raw_rs->stash_hfile, 0, FILE_SHARE_READ,
+                              overlapped);
+        if (s->hfile == INVALID_HANDLE_VALUE) {
+            int err = GetLastError();
+            if (err == ERROR_ACCESS_DENIED) {
+                ret = -EACCES;
+            } else {
+                ret = -1;
+            }
+        }
+    } else {
+
+        DuplicateHandle(GetCurrentProcess(),
+                    raw_rs->stash_hfile,
+                    GetCurrentProcess(),
+                    &s->hfile,
+                    0,
+                    FALSE,
+                    DUPLICATE_SAME_ACCESS);
+        bs->drv->bdrv_close(bs);
+        ret = bs->drv->bdrv_open(bs, bs->filename, flags);
+    }
+    return ret;
+}
+
+
+static void raw_reopen_commit(BlockDriverState *bs, BDRVReopenState *rs)
+{
+    BDRVRawReopenState *raw_rs;
+
+    raw_rs = container_of(rs, BDRVRawReopenState, reopen_state);
+
+    /* clean up stashed handle */
+    CloseHandle(raw_rs->stash_hfile);
+    g_free(raw_rs);
+
+}
+
+static void raw_reopen_abort(BlockDriverState *bs, BDRVReopenState *rs)
+{
+
+    BDRVRawReopenState *raw_rs;
+    BDRVRawState *s = bs->opaque;
+
+    raw_rs = container_of(rs, BDRVRawReopenState, reopen_state);
+
+    if (s->hfile && (s->hfile != INVALID_HANDLE_VALUE)) {
+        CloseHandle(s->hfile);
+    }
+    s->hfile = raw_rs->stash_hfile;
+    s->overlapped = raw_rs->stash_overlapped;
+    g_free(raw_rs);
+}
+
 static int raw_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {


Reply via email to