1 /******************************************************************************
2 *
3 * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <string.h>
19 #include <inttypes.h>
20
21 #include "memshr.h"
22 #include "memshr-priv.h"
23 #include "bidir-hash.h"
24 #include "shm.h"
25 #include "bidir-daemon.h"
26
27 typedef struct {
28 int enabled;
29 domid_t domid;
30 xc_interface *xc_handle;
31 } memshr_vbd_info_t;
32
33 memshr_vbd_info_t vbd_info = {0, DOMID_INVALID};
34
35
36 typedef struct {
37 struct shared_memshr_info *shared_info;
38 struct fgprtshr_hash *fgprts;
39 struct blockshr_hash *blks;
40 } private_memshr_info_t;
41
42 private_memshr_info_t memshr;
43
44 #define SHARED_INFO (memshr.shared_info)
45
memshr_set_domid(int domid)46 void memshr_set_domid(int domid)
47 {
48 vbd_info.domid = domid;
49 }
50
memshr_daemon_initialize(void)51 void memshr_daemon_initialize(void)
52 {
53 void *shm_base_addr;
54 struct fgprtshr_hash *h;
55
56 memset(&memshr, 0, sizeof(private_memshr_info_t));
57
58 if((SHARED_INFO = shm_shared_info_open(1)) == NULL)
59 {
60 DPRINTF("Failed to init shared info.\n");
61 return;
62 }
63
64 if((memshr.fgprts = shm_fgprtshr_hash_open(1)) == NULL)
65 {
66 DPRINTF("Failed to init fgprtshr hash.\n");
67 return;
68 }
69 memshr.shared_info->fgprtshr_hash_inited = 1;
70
71 if((memshr.blks = shm_blockshr_hash_open(1)) == NULL)
72 {
73 DPRINTF("Failed to init blockshr hash.\n");
74 return;
75 }
76 memshr.shared_info->blockshr_hash_inited = 1;
77
78 bidir_daemon_initialize(memshr.blks);
79 }
80
81
memshr_vbd_initialize(void)82 void memshr_vbd_initialize(void)
83 {
84 xc_interface *xc_handle;
85
86 memset(&memshr, 0, sizeof(private_memshr_info_t));
87
88 if((SHARED_INFO = shm_shared_info_open(0)) == NULL)
89 {
90 DPRINTF("Failed to open shared info.\n");
91 return;
92 }
93
94 if(!SHARED_INFO->fgprtshr_hash_inited)
95 {
96 DPRINTF("fgprtshr hash not inited.\n");
97 return;
98 }
99
100 if((memshr.fgprts = shm_fgprtshr_hash_open(0)) == NULL)
101 {
102 DPRINTF("Failed to open fgprtshr_hash.\n");
103 return;
104 }
105
106 if((memshr.blks = shm_blockshr_hash_open(0)) == NULL)
107 {
108 DPRINTF("Failed to open blockshr_hash.\n");
109 return;
110 }
111
112 if(vbd_info.domid == DOMID_INVALID)
113 return;
114
115 if((xc_handle = xc_interface_open(0,0,0)) == 0)
116 {
117 DPRINTF("Failed to open XC interface.\n");
118 return;
119 }
120
121 vbd_info.xc_handle = xc_handle;
122 vbd_info.enabled = 1;
123 }
124
memshr_vbd_image_get(const char * file)125 uint16_t memshr_vbd_image_get(const char* file)
126 {
127 uint16_t id;
128
129 if(pthread_mutex_lock(&SHARED_INFO->lock)) goto error_out;
130 id = shm_vbd_image_get(file, SHARED_INFO->vbd_images);
131 if(pthread_mutex_unlock(&SHARED_INFO->lock)) goto error_out;
132
133 return id;
134 error_out:
135 return 0;
136 }
137
memshr_vbd_image_put(uint16_t memshr_id)138 void memshr_vbd_image_put(uint16_t memshr_id)
139 {
140 if(pthread_mutex_lock(&SHARED_INFO->lock)) return;
141 shm_vbd_image_put(memshr_id, SHARED_INFO->vbd_images);
142 if(pthread_mutex_unlock(&SHARED_INFO->lock)) return;
143 }
144
memshr_vbd_issue_ro_request(char * buf,grant_ref_t gref,uint16_t file_id,uint64_t sec,int secs,share_tuple_t * hnd)145 int memshr_vbd_issue_ro_request(char *buf,
146 grant_ref_t gref,
147 uint16_t file_id,
148 uint64_t sec,
149 int secs,
150 share_tuple_t *hnd)
151 {
152 vbdblk_t blk;
153 share_tuple_t source_st, client_st;
154 uint64_t c_hnd;
155 int ret;
156
157 *hnd = (share_tuple_t){ 0, 0, 0 };
158 if(!vbd_info.enabled)
159 return -1;
160
161 if(secs != 8)
162 return -2;
163
164 /* Nominate the granted page for sharing */
165 ret = xc_memshr_nominate_gref(vbd_info.xc_handle,
166 vbd_info.domid,
167 gref,
168 &c_hnd);
169 /* If page couldn't be made sharable, we cannot do anything about it */
170 if(ret != 0)
171 return -3;
172
173 client_st = (share_tuple_t){ vbd_info.domid, gref, c_hnd };
174 *hnd = client_st;
175
176 /* Check if we've read matching disk block previously */
177 blk.sec = sec;
178 blk.disk_id = file_id;
179 if(blockshr_block_lookup(memshr.blks, blk, &source_st) > 0)
180 {
181 ret = xc_memshr_share_grefs(vbd_info.xc_handle, source_st.domain, source_st.frame,
182 source_st.handle, vbd_info.domid, gref, c_hnd);
183 if(!ret) return 0;
184 /* Handles failed to be shared => at least one of them must be invalid,
185 remove the relevant ones from the map */
186 switch(ret)
187 {
188 case XENMEM_SHARING_OP_S_HANDLE_INVALID:
189 ret = blockshr_shrhnd_remove(memshr.blks, source_st, NULL);
190 if(ret) DPRINTF("Could not rm invl s_hnd: %u %"PRId64" %"PRId64"\n",
191 source_st.domain, source_st.frame, source_st.handle);
192 break;
193 case XENMEM_SHARING_OP_C_HANDLE_INVALID:
194 ret = blockshr_shrhnd_remove(memshr.blks, client_st, NULL);
195 if(ret) DPRINTF("Could not rm invl c_hnd: %u %"PRId64" %"PRId64"\n",
196 client_st.domain, client_st.frame, client_st.handle);
197 break;
198 default:
199 break;
200 }
201 return -5;
202 }
203
204 return -4;
205 }
206
memshr_vbd_complete_ro_request(share_tuple_t hnd,uint16_t file_id,uint64_t sec,int secs)207 void memshr_vbd_complete_ro_request(share_tuple_t hnd,
208 uint16_t file_id,
209 uint64_t sec,
210 int secs)
211 {
212 vbdblk_t blk;
213
214 if(!vbd_info.enabled)
215 return;
216
217 if(secs != 8)
218 return;
219
220 blk.sec = sec;
221 blk.disk_id = file_id;
222 if(blockshr_insert(memshr.blks, blk, hnd) < 0)
223 DPRINTF("Could not insert block hint into hash.\n");
224 }
225