debuggers.hg

view tools/fs-back/fs-ops.c @ 21067:b4a1832a916f

Update Xen version to 4.0.0-rc6
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 09 18:18:05 2010 +0000 (2010-03-09)
parents 5c40f649a6a4
children 3ffdb094c2c0
line source
1 #undef NDEBUG
2 #include <stdio.h>
3 #include <aio.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <fcntl.h>
7 #include <dirent.h>
8 #include <inttypes.h>
9 #include <xenctrl.h>
10 #include <sys/mman.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/statvfs.h>
14 #include <sys/mount.h>
15 #include <unistd.h>
16 #include <ctype.h>
17 #include "fs-backend.h"
18 #include "fs-debug.h"
20 /* For debugging only */
21 #include <sys/time.h>
22 #include <time.h>
25 #define BUFFER_SIZE 1024
27 static int check_export_path(const char *export_path, const char *path)
28 {
29 int i;
30 if (!export_path || !path)
31 return -1;
32 if (strlen(path) < strlen(export_path))
33 return -1;
34 if (strstr(path, "..") != NULL)
35 return -1;
36 for (i = 0; i < strlen(path); i++) {
37 if (!isascii(path[i]))
38 return -1;
39 }
40 if (strncmp(export_path, path, strlen(export_path)))
41 return -1;
42 else
43 return 0;
44 }
46 static unsigned short get_request(struct fs_mount *mount, struct fsif_request *req)
47 {
48 unsigned short id = get_id_from_freelist(mount->freelist);
50 FS_DEBUG("Private Request id: %d\n", id);
51 memcpy(&mount->requests[id].req_shadow, req, sizeof(struct fsif_request));
52 mount->requests[id].active = 1;
54 return id;
55 }
57 static int get_fd(struct fs_mount *mount)
58 {
59 int i;
61 for (i = 0; i < MAX_FDS; i++)
62 if (mount->fds[i] == -1)
63 return i;
64 return -1;
65 }
68 static void dispatch_file_open(struct fs_mount *mount, struct fsif_request *req)
69 {
70 char *file_name;
71 int fd;
72 RING_IDX rsp_idx;
73 fsif_response_t *rsp;
74 uint16_t req_id;
76 FS_DEBUG("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref);
77 /* Read the request, and open file */
78 file_name = xc_gnttab_map_grant_ref(mount->gnth,
79 mount->dom_id,
80 req->u.fopen.gref,
81 PROT_READ);
83 req_id = req->id;
84 FS_DEBUG("File open issued for %s\n", file_name);
85 if (check_export_path(mount->export->export_path, file_name) < 0) {
86 FS_DEBUG("Filename check failed\n");
87 fd = -1;
88 goto out;
89 }
90 fd = get_fd(mount);
91 if (fd >= 0) {
92 int real_fd = open(file_name, O_RDWR);
93 if (real_fd < 0)
94 fd = -1;
95 else
96 {
97 mount->fds[fd] = real_fd;
98 FS_DEBUG("Got FD: %d for real %d\n", fd, real_fd);
99 }
100 }
101 out:
102 if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) {
103 FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
104 terminate_mount_request(mount);
105 }
106 /* We can advance the request consumer index, from here on, the request
107 * should not be used (it may be overrinden by a response) */
108 mount->ring.req_cons++;
111 /* Get a response from the ring */
112 rsp_idx = mount->ring.rsp_prod_pvt++;
113 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
114 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
115 rsp->id = req_id;
116 rsp->u.ret_val = (uint64_t)fd;
117 }
119 static void dispatch_file_close(struct fs_mount *mount, struct fsif_request *req)
120 {
121 int ret;
122 RING_IDX rsp_idx;
123 fsif_response_t *rsp;
124 uint16_t req_id;
126 FS_DEBUG("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
128 req_id = req->id;
129 if (req->u.fclose.fd < MAX_FDS) {
130 int fd = mount->fds[req->u.fclose.fd];
131 ret = close(fd);
132 mount->fds[req->u.fclose.fd] = -1;
133 } else
134 ret = -1;
135 FS_DEBUG("Got ret: %d\n", ret);
136 /* We can advance the request consumer index, from here on, the request
137 * should not be used (it may be overrinden by a response) */
138 mount->ring.req_cons++;
141 /* Get a response from the ring */
142 rsp_idx = mount->ring.rsp_prod_pvt++;
143 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
144 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
145 rsp->id = req_id;
146 rsp->u.ret_val = (uint64_t)ret;
147 }
149 #define MAX_GNTS 16
150 static void dispatch_file_read(struct fs_mount *mount, struct fsif_request *req)
151 {
152 void *buf;
153 int fd, count;
154 uint16_t req_id;
155 unsigned short priv_id;
156 struct fs_request *priv_req;
158 /* Read the request */
159 assert(req->u.fread.len > 0);
160 count = (req->u.fread.len - 1) / XC_PAGE_SIZE + 1;
161 assert(count <= FSIF_NR_READ_GNTS);
162 buf = xc_gnttab_map_domain_grant_refs(mount->gnth,
163 count,
164 mount->dom_id,
165 req->u.fread.grefs,
166 PROT_WRITE);
168 req_id = req->id;
169 FS_DEBUG("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n",
170 req->u.fread.fd, req->u.fread.len, req->u.fread.offset);
172 if (req->u.fread.fd < MAX_FDS)
173 fd = mount->fds[req->u.fread.fd];
174 else
175 fd = -1;
177 priv_id = get_request(mount, req);
178 FS_DEBUG("Private id is: %d\n", priv_id);
179 priv_req = &mount->requests[priv_id];
180 priv_req->page = buf;
181 priv_req->count = count;
182 priv_req->id = priv_id;
184 /* Dispatch AIO read request */
185 bzero(&priv_req->aiocb, sizeof(struct aiocb));
186 priv_req->aiocb.aio_fildes = fd;
187 priv_req->aiocb.aio_nbytes = req->u.fread.len;
188 priv_req->aiocb.aio_offset = req->u.fread.offset;
189 priv_req->aiocb.aio_buf = buf;
190 priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
191 priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
192 priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
193 if (aio_read(&priv_req->aiocb) < 0) {
194 FS_DEBUG("ERROR: aio_read failed errno=%d\n", errno);
195 xc_gnttab_munmap(mount->gnth, priv_req->page, priv_req->count);
196 terminate_mount_request(mount);
197 }
199 /* We can advance the request consumer index, from here on, the request
200 * should not be used (it may be overrinden by a response) */
201 mount->ring.req_cons++;
202 }
204 static void end_file_read(struct fs_mount *mount, struct fs_request *priv_req)
205 {
206 RING_IDX rsp_idx;
207 fsif_response_t *rsp;
208 uint16_t req_id;
210 /* Release the grant */
211 if (xc_gnttab_munmap(mount->gnth, priv_req->page, priv_req->count) != 0) {
212 FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
213 terminate_mount_request(mount);
214 }
216 /* Get a response from the ring */
217 rsp_idx = mount->ring.rsp_prod_pvt++;
218 req_id = priv_req->req_shadow.id;
219 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
220 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
221 rsp->id = req_id;
222 rsp->u.ret_val = (uint64_t)aio_return(&priv_req->aiocb);
223 }
225 static void dispatch_file_write(struct fs_mount *mount, struct fsif_request *req)
226 {
227 void *buf;
228 int fd, count;
229 uint16_t req_id;
230 unsigned short priv_id;
231 struct fs_request *priv_req;
233 /* Read the request */
234 assert(req->u.fwrite.len > 0);
235 count = (req->u.fwrite.len - 1) / XC_PAGE_SIZE + 1;
236 assert(count <= FSIF_NR_WRITE_GNTS);
237 buf = xc_gnttab_map_domain_grant_refs(mount->gnth,
238 count,
239 mount->dom_id,
240 req->u.fwrite.grefs,
241 PROT_READ);
243 req_id = req->id;
244 FS_DEBUG("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n",
245 req->u.fwrite.fd, req->u.fwrite.len, req->u.fwrite.offset);
247 if (req->u.fwrite.fd < MAX_FDS)
248 fd = mount->fds[req->u.fwrite.fd];
249 else
250 fd = -1;
252 priv_id = get_request(mount, req);
253 FS_DEBUG("Private id is: %d\n", priv_id);
254 priv_req = &mount->requests[priv_id];
255 priv_req->page = buf;
256 priv_req->count = count;
257 priv_req->id = priv_id;
259 /* Dispatch AIO write request */
260 bzero(&priv_req->aiocb, sizeof(struct aiocb));
261 priv_req->aiocb.aio_fildes = fd;
262 priv_req->aiocb.aio_nbytes = req->u.fwrite.len;
263 priv_req->aiocb.aio_offset = req->u.fwrite.offset;
264 priv_req->aiocb.aio_buf = buf;
265 priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
266 priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
267 priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
268 if (aio_write(&priv_req->aiocb) < 0) {
269 FS_DEBUG("ERROR: aio_write failed errno=%d\n", errno);
270 xc_gnttab_munmap(mount->gnth, priv_req->page, priv_req->count);
271 terminate_mount_request(mount);
272 }
275 /* We can advance the request consumer index, from here on, the request
276 * should not be used (it may be overrinden by a response) */
277 mount->ring.req_cons++;
278 }
280 static void end_file_write(struct fs_mount *mount, struct fs_request *priv_req)
281 {
282 RING_IDX rsp_idx;
283 fsif_response_t *rsp;
284 uint16_t req_id;
286 /* Release the grant */
287 if (xc_gnttab_munmap(mount->gnth, priv_req->page, priv_req->count) != 0) {
288 FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
289 terminate_mount_request(mount);
290 }
292 /* Get a response from the ring */
293 rsp_idx = mount->ring.rsp_prod_pvt++;
294 req_id = priv_req->req_shadow.id;
295 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
296 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
297 rsp->id = req_id;
298 rsp->u.ret_val = (uint64_t)aio_return(&priv_req->aiocb);
299 }
301 static void dispatch_stat(struct fs_mount *mount, struct fsif_request *req)
302 {
303 struct stat stat;
304 int fd, ret;
305 uint16_t req_id;
306 RING_IDX rsp_idx;
307 fsif_response_t *rsp;
309 req_id = req->id;
310 if (req->u.fstat.fd < MAX_FDS)
311 fd = mount->fds[req->u.fstat.fd];
312 else
313 fd = -1;
315 FS_DEBUG("File stat issued for FD=%d\n", req->u.fstat.fd);
317 /* We can advance the request consumer index, from here on, the request
318 * should not be used (it may be overrinden by a response) */
319 mount->ring.req_cons++;
321 /* Stat, and create the response */
322 ret = fstat(fd, &stat);
323 FS_DEBUG("Mode=%o, uid=%d, a_time=%ld\n",
324 stat.st_mode, stat.st_uid, (long)stat.st_atime);
326 /* Get a response from the ring */
327 rsp_idx = mount->ring.rsp_prod_pvt++;
328 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
329 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
330 rsp->id = req_id;
331 rsp->u.fstat.stat_ret = (uint32_t)ret;
332 rsp->u.fstat.stat_mode = stat.st_mode;
333 rsp->u.fstat.stat_uid = stat.st_uid;
334 rsp->u.fstat.stat_gid = stat.st_gid;
335 #ifdef BLKGETSIZE
336 if (S_ISBLK(stat.st_mode)) {
337 unsigned long sectors;
338 if (ioctl(fd, BLKGETSIZE, &sectors)) {
339 perror("getting device size\n");
340 rsp->u.fstat.stat_size = 0;
341 } else
342 rsp->u.fstat.stat_size = sectors << 9;
343 } else
344 #endif
345 rsp->u.fstat.stat_size = stat.st_size;
346 rsp->u.fstat.stat_atime = stat.st_atime;
347 rsp->u.fstat.stat_mtime = stat.st_mtime;
348 rsp->u.fstat.stat_ctime = stat.st_ctime;
349 }
352 static void dispatch_truncate(struct fs_mount *mount, struct fsif_request *req)
353 {
354 int fd, ret;
355 uint16_t req_id;
356 RING_IDX rsp_idx;
357 fsif_response_t *rsp;
358 int64_t length;
360 req_id = req->id;
361 length = req->u.ftruncate.length;
362 FS_DEBUG("File truncate issued for FD=%d, length=%"PRId64"\n", req->u.ftruncate.fd, length);
364 if (req->u.ftruncate.fd < MAX_FDS)
365 fd = mount->fds[req->u.ftruncate.fd];
366 else
367 fd = -1;
369 /* We can advance the request consumer index, from here on, the request
370 * should not be used (it may be overrinden by a response) */
371 mount->ring.req_cons++;
373 /* Stat, and create the response */
374 ret = ftruncate(fd, length);
376 /* Get a response from the ring */
377 rsp_idx = mount->ring.rsp_prod_pvt++;
378 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
379 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
380 rsp->id = req_id;
381 rsp->u.ret_val = (uint64_t)ret;
382 }
384 static void dispatch_remove(struct fs_mount *mount, struct fsif_request *req)
385 {
386 char *file_name;
387 int ret;
388 RING_IDX rsp_idx;
389 fsif_response_t *rsp;
390 uint16_t req_id;
392 FS_DEBUG("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
393 /* Read the request, and open file */
394 file_name = xc_gnttab_map_grant_ref(mount->gnth,
395 mount->dom_id,
396 req->u.fremove.gref,
397 PROT_READ);
399 req_id = req->id;
400 FS_DEBUG("File remove issued for %s\n", file_name);
401 if (check_export_path(mount->export->export_path, file_name) < 0) {
402 FS_DEBUG("Filename check failed\n");
403 ret = -1;
404 } else {
405 ret = remove(file_name);
406 }
407 FS_DEBUG("Got ret: %d\n", ret);
408 if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) {
409 FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
410 terminate_mount_request(mount);
411 }
412 /* We can advance the request consumer index, from here on, the request
413 * should not be used (it may be overrinden by a response) */
414 mount->ring.req_cons++;
417 /* Get a response from the ring */
418 rsp_idx = mount->ring.rsp_prod_pvt++;
419 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
420 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
421 rsp->id = req_id;
422 rsp->u.ret_val = (uint64_t)ret;
423 }
426 static void dispatch_rename(struct fs_mount *mount, struct fsif_request *req)
427 {
428 char *buf, *old_file_name, *new_file_name;
429 int ret;
430 RING_IDX rsp_idx;
431 fsif_response_t *rsp;
432 uint16_t req_id;
434 FS_DEBUG("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
435 /* Read the request, and open file */
436 buf = xc_gnttab_map_grant_ref(mount->gnth,
437 mount->dom_id,
438 req->u.frename.gref,
439 PROT_READ);
441 req_id = req->id;
442 old_file_name = buf + req->u.frename.old_name_offset;
443 new_file_name = buf + req->u.frename.new_name_offset;
444 FS_DEBUG("File rename issued for %s -> %s (buf=%s)\n",
445 old_file_name, new_file_name, buf);
446 if (check_export_path(mount->export->export_path, old_file_name) < 0 ||
447 check_export_path(mount->export->export_path, new_file_name) < 0) {
448 FS_DEBUG("Filename check failed\n");
449 ret = -1;
450 } else {
451 ret = rename(old_file_name, new_file_name);
452 }
453 FS_DEBUG("Got ret: %d\n", ret);
454 if (xc_gnttab_munmap(mount->gnth, buf, 1) != 0) {
455 FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
456 terminate_mount_request(mount);
457 }
458 /* We can advance the request consumer index, from here on, the request
459 * should not be used (it may be overrinden by a response) */
460 mount->ring.req_cons++;
463 /* Get a response from the ring */
464 rsp_idx = mount->ring.rsp_prod_pvt++;
465 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
466 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
467 rsp->id = req_id;
468 rsp->u.ret_val = (uint64_t)ret;
469 }
472 static void dispatch_create(struct fs_mount *mount, struct fsif_request *req)
473 {
474 char *file_name;
475 int ret;
476 int8_t directory;
477 int32_t mode;
478 RING_IDX rsp_idx;
479 fsif_response_t *rsp;
480 uint16_t req_id;
482 FS_DEBUG("Dispatching file create operation (gref=%d).\n", req->u.fcreate.gref);
483 /* Read the request, and create file/directory */
484 mode = req->u.fcreate.mode;
485 directory = req->u.fcreate.directory;
486 file_name = xc_gnttab_map_grant_ref(mount->gnth,
487 mount->dom_id,
488 req->u.fcreate.gref,
489 PROT_READ);
491 req_id = req->id;
492 if (check_export_path(mount->export->export_path, file_name) < 0) {
493 FS_DEBUG("Filename check failed\n");
494 ret = -1;
495 goto out;
496 }
497 /* We can advance the request consumer index, from here on, the request
498 * should not be used (it may be overrinden by a response) */
499 mount->ring.req_cons++;
501 if(directory)
502 {
503 FS_DEBUG("Issuing create for directory: %s\n", file_name);
504 ret = mkdir(file_name, mode);
505 }
506 else
507 {
508 FS_DEBUG("Issuing create for file: %s\n", file_name);
509 ret = get_fd(mount);
510 if (ret >= 0) {
511 int real_fd = creat(file_name, mode);
512 if (real_fd < 0)
513 ret = -1;
514 else
515 {
516 mount->fds[ret] = real_fd;
517 FS_DEBUG("Got FD: %d for real %d\n", ret, real_fd);
518 }
519 }
520 }
521 out:
522 if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) {
523 FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
524 terminate_mount_request(mount);
525 }
526 FS_DEBUG("Got ret %d (errno=%d)\n", ret, errno);
528 /* Get a response from the ring */
529 rsp_idx = mount->ring.rsp_prod_pvt++;
530 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
531 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
532 rsp->id = req_id;
533 rsp->u.ret_val = (uint64_t)ret;
534 }
536 static void dispatch_list(struct fs_mount *mount, struct fsif_request *req)
537 {
538 char *file_name, *buf;
539 uint32_t offset = 0, nr_files = 0, error_code = 0;
540 uint64_t ret_val;
541 RING_IDX rsp_idx;
542 fsif_response_t *rsp;
543 uint16_t req_id;
544 DIR *dir;
545 struct dirent *dirent = NULL;
547 FS_DEBUG("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
548 /* Read the request, and list directory */
549 offset = req->u.flist.offset;
550 buf = file_name = xc_gnttab_map_grant_ref(mount->gnth,
551 mount->dom_id,
552 req->u.flist.gref,
553 PROT_READ | PROT_WRITE);
555 req_id = req->id;
556 FS_DEBUG("Dir list issued for %s\n", file_name);
557 if (check_export_path(mount->export->export_path, file_name) < 0) {
558 FS_DEBUG("Filename check failed\n");
559 error_code = 1;
560 goto error_out;
561 }
562 /* We can advance the request consumer index, from here on, the request
563 * should not be used (it may be overrinden by a response) */
564 mount->ring.req_cons++;
566 ret_val = 0;
567 nr_files = 0;
568 dir = opendir(file_name);
569 if(dir == NULL)
570 {
571 error_code = errno;
572 goto error_out;
573 }
574 /* Skip offset dirs */
575 dirent = readdir(dir);
576 while(offset-- > 0 && dirent != NULL)
577 dirent = readdir(dir);
578 /* If there was any error with reading the directory, errno will be set */
579 error_code = errno;
580 /* Copy file names of the remaining non-NULL dirents into buf */
581 if (NAME_MAX >= XC_PAGE_SIZE >> 1)
582 goto error_out;
583 while(dirent != NULL &&
584 (XC_PAGE_SIZE - ((unsigned long)buf & XC_PAGE_MASK) > NAME_MAX))
585 {
586 int curr_length = strlen(dirent->d_name) + 1;
588 memcpy(buf, dirent->d_name, curr_length);
589 buf += curr_length;
590 dirent = readdir(dir);
591 error_code = errno;
592 nr_files++;
593 }
594 error_out:
595 ret_val = ((nr_files << NR_FILES_SHIFT) & NR_FILES_MASK) |
596 ((error_code << ERROR_SHIFT) & ERROR_MASK) |
597 (dirent != NULL ? HAS_MORE_FLAG : 0);
598 if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) {
599 FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
600 terminate_mount_request(mount);
601 }
603 /* Get a response from the ring */
604 rsp_idx = mount->ring.rsp_prod_pvt++;
605 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
606 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
607 rsp->id = req_id;
608 rsp->u.ret_val = ret_val;
609 }
611 static void dispatch_chmod(struct fs_mount *mount, struct fsif_request *req)
612 {
613 int fd, ret;
614 RING_IDX rsp_idx;
615 fsif_response_t *rsp;
616 uint16_t req_id;
617 int32_t mode;
619 FS_DEBUG("Dispatching file chmod operation (fd=%d, mode=%o).\n",
620 req->u.fchmod.fd, req->u.fchmod.mode);
621 req_id = req->id;
622 if (req->u.fchmod.fd < MAX_FDS)
623 fd = mount->fds[req->u.fchmod.fd];
624 else
625 fd = -1;
627 mode = req->u.fchmod.mode;
628 /* We can advance the request consumer index, from here on, the request
629 * should not be used (it may be overrinden by a response) */
630 mount->ring.req_cons++;
632 ret = fchmod(fd, mode);
634 /* Get a response from the ring */
635 rsp_idx = mount->ring.rsp_prod_pvt++;
636 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
637 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
638 rsp->id = req_id;
639 rsp->u.ret_val = (uint64_t)ret;
640 }
642 static void dispatch_fs_space(struct fs_mount *mount, struct fsif_request *req)
643 {
644 char *file_name;
645 RING_IDX rsp_idx;
646 fsif_response_t *rsp;
647 uint16_t req_id;
648 struct statvfs stat;
649 int64_t ret;
651 FS_DEBUG("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref);
652 /* Read the request, and open file */
653 file_name = xc_gnttab_map_grant_ref(mount->gnth,
654 mount->dom_id,
655 req->u.fspace.gref,
656 PROT_READ);
658 req_id = req->id;
659 FS_DEBUG("Fs space issued for %s\n", file_name);
660 if (check_export_path(mount->export->export_path, file_name) < 0) {
661 FS_DEBUG("Filename check failed\n");
662 ret = -1;
663 } else {
664 ret = statvfs(file_name, &stat);
665 }
666 if(ret >= 0)
667 ret = stat.f_bsize * stat.f_bfree;
669 if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) {
670 FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
671 terminate_mount_request(mount);
672 }
673 /* We can advance the request consumer index, from here on, the request
674 * should not be used (it may be overrinden by a response) */
675 mount->ring.req_cons++;
678 /* Get a response from the ring */
679 rsp_idx = mount->ring.rsp_prod_pvt++;
680 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
681 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
682 rsp->id = req_id;
683 rsp->u.ret_val = (uint64_t)ret;
684 }
686 static void dispatch_file_sync(struct fs_mount *mount, struct fsif_request *req)
687 {
688 int fd;
689 uint16_t req_id;
690 unsigned short priv_id;
691 struct fs_request *priv_req;
693 req_id = req->id;
694 if (req->u.fsync.fd < MAX_FDS)
695 fd = mount->fds[req->u.fsync.fd];
696 else
697 fd = -1;
699 FS_DEBUG("File sync issued for FD=%d\n", req->u.fsync.fd);
701 priv_id = get_request(mount, req);
702 FS_DEBUG("Private id is: %d\n", priv_id);
703 priv_req = &mount->requests[priv_id];
704 priv_req->id = priv_id;
706 /* Dispatch AIO read request */
707 bzero(&priv_req->aiocb, sizeof(struct aiocb));
708 priv_req->aiocb.aio_fildes = fd;
709 priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
710 priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
711 priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
712 if (aio_fsync(O_SYNC, &priv_req->aiocb) < 0) {
713 FS_DEBUG("ERROR: aio_fsync failed errno=%d\n", errno);
714 terminate_mount_request(mount);
715 }
717 /* We can advance the request consumer index, from here on, the request
718 * should not be used (it may be overrinden by a response) */
719 mount->ring.req_cons++;
720 }
722 static void end_file_sync(struct fs_mount *mount, struct fs_request *priv_req)
723 {
724 RING_IDX rsp_idx;
725 fsif_response_t *rsp;
726 uint16_t req_id;
728 /* Get a response from the ring */
729 rsp_idx = mount->ring.rsp_prod_pvt++;
730 req_id = priv_req->req_shadow.id;
731 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
732 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
733 rsp->id = req_id;
734 rsp->u.ret_val = (uint64_t)aio_return(&priv_req->aiocb);
735 }
737 struct fs_op fopen_op = {.type = REQ_FILE_OPEN,
738 .dispatch_handler = dispatch_file_open,
739 .response_handler = NULL};
740 struct fs_op fclose_op = {.type = REQ_FILE_CLOSE,
741 .dispatch_handler = dispatch_file_close,
742 .response_handler = NULL};
743 struct fs_op fread_op = {.type = REQ_FILE_READ,
744 .dispatch_handler = dispatch_file_read,
745 .response_handler = end_file_read};
746 struct fs_op fwrite_op = {.type = REQ_FILE_WRITE,
747 .dispatch_handler = dispatch_file_write,
748 .response_handler = end_file_write};
749 struct fs_op fstat_op = {.type = REQ_STAT,
750 .dispatch_handler = dispatch_stat,
751 .response_handler = NULL};
752 struct fs_op ftruncate_op = {.type = REQ_FILE_TRUNCATE,
753 .dispatch_handler = dispatch_truncate,
754 .response_handler = NULL};
755 struct fs_op fremove_op = {.type = REQ_REMOVE,
756 .dispatch_handler = dispatch_remove,
757 .response_handler = NULL};
758 struct fs_op frename_op = {.type = REQ_RENAME,
759 .dispatch_handler = dispatch_rename,
760 .response_handler = NULL};
761 struct fs_op fcreate_op = {.type = REQ_CREATE,
762 .dispatch_handler = dispatch_create,
763 .response_handler = NULL};
764 struct fs_op flist_op = {.type = REQ_DIR_LIST,
765 .dispatch_handler = dispatch_list,
766 .response_handler = NULL};
767 struct fs_op fchmod_op = {.type = REQ_CHMOD,
768 .dispatch_handler = dispatch_chmod,
769 .response_handler = NULL};
770 struct fs_op fspace_op = {.type = REQ_FS_SPACE,
771 .dispatch_handler = dispatch_fs_space,
772 .response_handler = NULL};
773 struct fs_op fsync_op = {.type = REQ_FILE_SYNC,
774 .dispatch_handler = dispatch_file_sync,
775 .response_handler = end_file_sync};
778 struct fs_op *fsops[] = {&fopen_op,
779 &fclose_op,
780 &fread_op,
781 &fwrite_op,
782 &fstat_op,
783 &ftruncate_op,
784 &fremove_op,
785 &frename_op,
786 &fcreate_op,
787 &flist_op,
788 &fchmod_op,
789 &fspace_op,
790 &fsync_op,
791 NULL};