aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-12-17 06:27:57 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-12-17 06:27:57 +0000
commit4515e6d82b23366933055b0ad60d8ed89f5a2b92 (patch)
treec07557a5b58cadbd0de42669b2ed898b37626e76 /tools
parent06d2e6455f6333c7049f72d41f8c89a1a9884e51 (diff)
downloadxen-4515e6d82b23366933055b0ad60d8ed89f5a2b92.tar.gz
xen-4515e6d82b23366933055b0ad60d8ed89f5a2b92.tar.bz2
xen-4515e6d82b23366933055b0ad60d8ed89f5a2b92.zip
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@citrix.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/blktap2/drivers/Makefile3
-rw-r--r--tools/blktap2/drivers/tapdisk-vbd.c52
-rw-r--r--tools/blktap2/drivers/tapdisk.h2
-rw-r--r--tools/memshr/interface.c87
-rw-r--r--tools/memshr/memshr.h13
5 files changed, 154 insertions, 3 deletions
diff --git a/tools/blktap2/drivers/Makefile b/tools/blktap2/drivers/Makefile
index 97f27b56d3..b70ca7ddc0 100644
--- a/tools/blktap2/drivers/Makefile
+++ b/tools/blktap2/drivers/Makefile
@@ -14,6 +14,7 @@ CFLAGS += -Wno-unused
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 @@ else
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 --git a/tools/blktap2/drivers/tapdisk-vbd.c b/tools/blktap2/drivers/tapdisk-vbd.c
index 07504cf7da..14507b3830 100644
--- a/tools/blktap2/drivers/tapdisk-vbd.c
+++ b/tools/blktap2/drivers/tapdisk-vbd.c
@@ -1418,11 +1418,26 @@ tapdisk_vbd_complete_vbd_request(td_vbd_t *vbd, td_vbd_request_t *vreq)
}
}
+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_t *vbd, td_vbd_request_t *vreq,
(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_t *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 --git a/tools/blktap2/drivers/tapdisk.h b/tools/blktap2/drivers/tapdisk.h
index b1a91c77f2..bd6835e5e8 100644
--- a/tools/blktap2/drivers/tapdisk.h
+++ b/tools/blktap2/drivers/tapdisk.h
@@ -131,6 +131,8 @@ struct td_request {
uint64_t id;
int sidx;
void *private;
+
+ uint64_t memshr_hnd;
};
/*
diff --git a/tools/memshr/interface.c b/tools/memshr/interface.c
index ad14bbf2a0..73fb144bfe 100644
--- a/tools/memshr/interface.c
+++ b/tools/memshr/interface.c
@@ -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 memshr_id)
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 --git a/tools/memshr/memshr.h b/tools/memshr/memshr.h
index 1292d494f5..ae1449f091 100644
--- a/tools/memshr/memshr.h
+++ b/tools/memshr/memshr.h
@@ -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_daemon_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__ */