# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1261031277 0
# Node ID 617071a8c6387a5414e22869cce585811ae27e77
# Parent d3b569b2a2b9ba13d458acf58ef4e953808074c4
Reads from read only parent disk images are intercepted, and are used to detect
potentially sharable memory pages.
Signed-off-by: Grzegorz Milos <Grzegorz.Milos@xxxxxxxxxx>
---
tools/blktap2/drivers/Makefile | 3 -
tools/blktap2/drivers/tapdisk-vbd.c | 52 +++++++++++++++++++-
tools/blktap2/drivers/tapdisk.h | 2
tools/memshr/interface.c | 91 +++++++++++++++++++++++++++++++++++-
tools/memshr/memshr.h | 13 +++++
5 files changed, 156 insertions(+), 5 deletions(-)
diff -r d3b569b2a2b9 -r 617071a8c638 tools/blktap2/drivers/Makefile
--- a/tools/blktap2/drivers/Makefile Thu Dec 17 06:27:57 2009 +0000
+++ b/tools/blktap2/drivers/Makefile Thu Dec 17 06:27:57 2009 +0000
@@ -14,6 +14,7 @@ CFLAGS += -fno-strict-aliasing
CFLAGS += -fno-strict-aliasing
CFLAGS += -I../lib -I../../libxc
CFLAGS += -I../include -I../../include
+CFLAGS += $(CFLAGS_libxenctrl)
CFLAGS += -I $(LIBAIO_DIR)
CFLAGS += -I $(MEMSHR_DIR)
CFLAGS += -D_GNU_SOURCE
@@ -37,7 +38,7 @@ CRYPT_LIB += -lcrypto
CRYPT_LIB += -lcrypto
endif
-LDFLAGS_img := $(CRYPT_LIB) -lpthread -lz -lm
+LDFLAGS_img := $(LDFLAGS_libxenctrl) $(CRYPT_LIB) -lpthread -lz -lm
LIBS += -L$(LIBVHDDIR) -lvhd
diff -r d3b569b2a2b9 -r 617071a8c638 tools/blktap2/drivers/tapdisk-vbd.c
--- a/tools/blktap2/drivers/tapdisk-vbd.c Thu Dec 17 06:27:57 2009 +0000
+++ b/tools/blktap2/drivers/tapdisk-vbd.c Thu Dec 17 06:27:57 2009 +0000
@@ -1418,11 +1418,26 @@ tapdisk_vbd_complete_vbd_request(td_vbd_
}
}
+static uint64_t
+tapdisk_vbd_breq_get_sector(blkif_request_t *breq, td_request_t treq)
+{
+ int seg, nsects;
+ uint64_t sector_nr = breq->sector_number;
+
+ for(seg=0; seg < treq.sidx; seg++) {
+ nsects = breq->seg[seg].last_sect - breq->seg[seg].first_sect + 1;
+ sector_nr += nsects;
+ }
+
+ return sector_nr;
+}
+
static void
__tapdisk_vbd_complete_td_request(td_vbd_t *vbd, td_vbd_request_t *vreq,
td_request_t treq, int res)
{
int err;
+ td_image_t *image = treq.image;
err = (res <= 0 ? res : -res);
vbd->secs_pending -= treq.secs;
@@ -1440,7 +1455,18 @@ __tapdisk_vbd_complete_td_request(td_vbd
(treq.op == TD_OP_WRITE ? "write" : "read"),
treq.secs, treq.sec);
}
- }
+ } else
+ if(treq.op == TD_OP_READ && td_flag_test(image->flags, TD_OPEN_RDONLY)) {
+ uint64_t hnd = treq.memshr_hnd;
+ uint16_t uid = image->memshr_id;
+ blkif_request_t *breq = &vreq->req;
+ uint64_t sec = tapdisk_vbd_breq_get_sector(breq, treq);
+ int secs = breq->seg[treq.sidx].last_sect -
+ breq->seg[treq.sidx].first_sect + 1;
+
+ if(hnd != 0)
+ memshr_vbd_complete_ro_request(hnd, uid, sec, secs);
+ }
tapdisk_vbd_complete_vbd_request(vbd, vreq);
}
@@ -1492,7 +1518,29 @@ __tapdisk_vbd_reissue_td_request(td_vbd_
break;
case TD_OP_READ:
- td_queue_read(parent, treq);
+ if(td_flag_test(parent->flags, TD_OPEN_RDONLY))
+ {
+ int ret, seg = treq.sidx;
+ blkif_request_t *breq = &vreq->req;
+
+ ret = memshr_vbd_issue_ro_request(treq.buf,
+ breq->seg[seg].gref,
+ parent->memshr_id,
+ treq.sec,
+ treq.secs,
+ &treq.memshr_hnd);
+ if(ret == 0)
+ {
+ /* Reset memshr handle. This'll prevent
+ * memshr_vbd_complete_ro_request being called */
+ treq.memshr_hnd = 0;
+ td_complete_request(treq, 0);
+ }
+ else
+ td_queue_read(parent, treq);
+ }
+ else
+ td_queue_read(parent, treq);
break;
}
diff -r d3b569b2a2b9 -r 617071a8c638 tools/blktap2/drivers/tapdisk.h
--- a/tools/blktap2/drivers/tapdisk.h Thu Dec 17 06:27:57 2009 +0000
+++ b/tools/blktap2/drivers/tapdisk.h Thu Dec 17 06:27:57 2009 +0000
@@ -131,6 +131,8 @@ struct td_request {
uint64_t id;
int sidx;
void *private;
+
+ uint64_t memshr_hnd;
};
/*
diff -r d3b569b2a2b9 -r 617071a8c638 tools/memshr/interface.c
--- a/tools/memshr/interface.c Thu Dec 17 06:27:57 2009 +0000
+++ b/tools/memshr/interface.c Thu Dec 17 06:27:57 2009 +0000
@@ -17,13 +17,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
-
+#include <inttypes.h>
+
+#include "memshr.h"
#include "memshr-priv.h"
+#include "bidir-hash.h"
#include "shm.h"
typedef struct {
int enabled;
domid_t domid;
+ int xc_handle;
} memshr_vbd_info_t;
memshr_vbd_info_t vbd_info = {0, DOMID_INVALID};
@@ -74,6 +78,8 @@ void memshr_daemon_initialize(void)
void memshr_vbd_initialize(void)
{
+ int xc_handle;
+
memset(&memshr, 0, sizeof(private_memshr_info_t));
if((SHARED_INFO = shm_shared_info_open(0)) == NULL)
@@ -103,6 +109,13 @@ void memshr_vbd_initialize(void)
if(vbd_info.domid == DOMID_INVALID)
return;
+ if((xc_handle = xc_interface_open()) < 0)
+ {
+ DPRINTF("Failed to open XC interface.\n");
+ return;
+ }
+
+ vbd_info.xc_handle = xc_handle;
vbd_info.enabled = 1;
}
@@ -125,4 +138,78 @@ void memshr_vbd_image_put(uint16_t memsh
shm_vbd_image_put(memshr_id, SHARED_INFO->vbd_images);
if(pthread_mutex_unlock(&SHARED_INFO->lock)) return;
}
-
+
+int memshr_vbd_issue_ro_request(char *buf,
+ grant_ref_t gref,
+ uint16_t file_id,
+ uint64_t sec,
+ int secs,
+ uint64_t *hnd)
+{
+ vbdblk_t blk;
+ uint64_t s_hnd, c_hnd;
+ int ret;
+
+ *hnd = 0;
+ if(!vbd_info.enabled)
+ return -1;
+
+ if(secs != 8)
+ return -2;
+
+ /* Nominate the granted page for sharing */
+ ret = xc_memshr_nominate_gref(vbd_info.xc_handle,
+ vbd_info.domid,
+ gref,
+ &c_hnd);
+ /* If page couldn't be made sharable, we cannot do anything about it */
+ if(ret != 0)
+ return -3;
+ *hnd = c_hnd;
+
+ /* Check if we've read matching disk block previously */
+ blk.sec = sec;
+ blk.disk_id = file_id;
+ if(blockshr_block_lookup(memshr.blks, blk, &s_hnd) > 0)
+ {
+ ret = xc_memshr_share(vbd_info.xc_handle, s_hnd, c_hnd);
+ if(!ret) return 0;
+ /* Handles failed to be shared => at least one of them must be invalid,
+ remove the relevant ones from the map */
+ switch(ret)
+ {
+ case XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID:
+ ret = blockshr_shrhnd_remove(memshr.blks, s_hnd, NULL);
+ if(ret) DPRINTF("Could not rm invl s_hnd: %"PRId64"\n", s_hnd);
+ break;
+ case XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID:
+ ret = blockshr_shrhnd_remove(memshr.blks, c_hnd, NULL);
+ if(ret) DPRINTF("Could not rm invl c_hnd: %"PRId64"\n", c_hnd);
+ break;
+ default:
+ break;
+ }
+ return -5;
+ }
+
+ return -4;
+}
+
+void memshr_vbd_complete_ro_request(uint64_t hnd,
+ uint16_t file_id,
+ uint64_t sec,
+ int secs)
+{
+ vbdblk_t blk;
+
+ if(!vbd_info.enabled)
+ return;
+
+ if(secs != 8)
+ return;
+
+ blk.sec = sec;
+ blk.disk_id = file_id;
+ if(blockshr_insert(memshr.blks, blk, hnd) < 0)
+ DPRINTF("Could not insert block hint into hash.\n");
+}
diff -r d3b569b2a2b9 -r 617071a8c638 tools/memshr/memshr.h
--- a/tools/memshr/memshr.h Thu Dec 17 06:27:57 2009 +0000
+++ b/tools/memshr/memshr.h Thu Dec 17 06:27:57 2009 +0000
@@ -20,6 +20,8 @@
#define __MEMSHR_H__
#include <stdint.h>
+#include <xen/xen.h>
+#include <xen/grant_table.h>
typedef uint64_t xen_mfn_t;
@@ -28,5 +30,16 @@ extern void memshr_vbd_initialize(void);
extern void memshr_vbd_initialize(void);
extern uint16_t memshr_vbd_image_get(char* file);
extern void memshr_vbd_image_put(uint16_t memshr_id);
+extern int memshr_vbd_issue_ro_request(char *buf,
+ grant_ref_t gref,
+ uint16_t file_id,
+ uint64_t sec,
+ int secs,
+ uint64_t *hnd);
+extern void memshr_vbd_complete_ro_request(
+ uint64_t hnd,
+ uint16_t file_id,
+ uint64_t sec,
+ int secs);
#endif /* __MEMSHR_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|