debuggers.hg

view tools/fs-back/fs-ops.c @ 19810:aaab04808ee7

Introduce mechanism to check standard conformance of headers

While pretty simplistic, it appears to serve the purpose at the moment
(i.e. it spotted two places where a GNU extension was used withou
proper preprocessor conditionals). The "simplistic" here includes that
the checking gets only done for native builds, and ia64 gets excluded
due to its arch-specific header intentionally (for whatever reason)
checking that anonymous struct/unions can be used.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 17 07:21:03 2009 +0100 (2009-06-17)
parents fe4b23bd3a95
children 53b3857e5705
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 "fs-backend.h"
17 #include "fs-debug.h"
19 /* For debugging only */
20 #include <sys/time.h>
21 #include <time.h>
24 #define BUFFER_SIZE 1024
26 static unsigned short get_request(struct fs_mount *mount, struct fsif_request *req)
27 {
28 unsigned short id = get_id_from_freelist(mount->freelist);
30 FS_DEBUG("Private Request id: %d\n", id);
31 memcpy(&mount->requests[id].req_shadow, req, sizeof(struct fsif_request));
32 mount->requests[id].active = 1;
34 return id;
35 }
37 static int get_fd(struct fs_mount *mount)
38 {
39 int i;
41 for (i = 0; i < MAX_FDS; i++)
42 if (mount->fds[i] == -1)
43 return i;
44 return -1;
45 }
48 static void dispatch_file_open(struct fs_mount *mount, struct fsif_request *req)
49 {
50 char *file_name, full_path[BUFFER_SIZE];
51 int fd;
52 RING_IDX rsp_idx;
53 fsif_response_t *rsp;
54 uint16_t req_id;
56 FS_DEBUG("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref);
57 /* Read the request, and open file */
58 file_name = xc_gnttab_map_grant_ref(mount->gnth,
59 mount->dom_id,
60 req->u.fopen.gref,
61 PROT_READ);
63 req_id = req->id;
64 FS_DEBUG("File open issued for %s\n", file_name);
65 assert(BUFFER_SIZE >
66 strlen(file_name) + strlen(mount->export->export_path) + 1);
67 snprintf(full_path, sizeof(full_path), "%s/%s",
68 mount->export->export_path, file_name);
69 assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
70 FS_DEBUG("Issuing open for %s\n", full_path);
71 fd = get_fd(mount);
72 if (fd >= 0) {
73 int real_fd = open(full_path, O_RDWR);
74 if (real_fd < 0)
75 fd = -1;
76 else
77 {
78 mount->fds[fd] = real_fd;
79 FS_DEBUG("Got FD: %d for real %d\n", fd, real_fd);
80 }
81 }
82 /* We can advance the request consumer index, from here on, the request
83 * should not be used (it may be overrinden by a response) */
84 mount->ring.req_cons++;
87 /* Get a response from the ring */
88 rsp_idx = mount->ring.rsp_prod_pvt++;
89 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
90 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
91 rsp->id = req_id;
92 rsp->u.ret_val = (uint64_t)fd;
93 }
95 static void dispatch_file_close(struct fs_mount *mount, struct fsif_request *req)
96 {
97 int ret;
98 RING_IDX rsp_idx;
99 fsif_response_t *rsp;
100 uint16_t req_id;
102 FS_DEBUG("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
104 req_id = req->id;
105 if (req->u.fclose.fd < MAX_FDS) {
106 int fd = mount->fds[req->u.fclose.fd];
107 ret = close(fd);
108 mount->fds[req->u.fclose.fd] = -1;
109 } else
110 ret = -1;
111 FS_DEBUG("Got ret: %d\n", ret);
112 /* We can advance the request consumer index, from here on, the request
113 * should not be used (it may be overrinden by a response) */
114 mount->ring.req_cons++;
117 /* Get a response from the ring */
118 rsp_idx = mount->ring.rsp_prod_pvt++;
119 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
120 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
121 rsp->id = req_id;
122 rsp->u.ret_val = (uint64_t)ret;
123 }
125 #define MAX_GNTS 16
126 static void dispatch_file_read(struct fs_mount *mount, struct fsif_request *req)
127 {
128 void *buf;
129 int fd, count;
130 uint16_t req_id;
131 unsigned short priv_id;
132 struct fs_request *priv_req;
134 /* Read the request */
135 assert(req->u.fread.len > 0);
136 count = (req->u.fread.len - 1) / XC_PAGE_SIZE + 1;
137 assert(count <= FSIF_NR_READ_GNTS);
138 buf = xc_gnttab_map_domain_grant_refs(mount->gnth,
139 count,
140 mount->dom_id,
141 req->u.fread.grefs,
142 PROT_WRITE);
144 req_id = req->id;
145 FS_DEBUG("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n",
146 req->u.fread.fd, req->u.fread.len, req->u.fread.offset);
148 if (req->u.fread.fd < MAX_FDS)
149 fd = mount->fds[req->u.fread.fd];
150 else
151 fd = -1;
153 priv_id = get_request(mount, req);
154 FS_DEBUG("Private id is: %d\n", priv_id);
155 priv_req = &mount->requests[priv_id];
156 priv_req->page = buf;
157 priv_req->count = count;
158 priv_req->id = priv_id;
160 /* Dispatch AIO read request */
161 bzero(&priv_req->aiocb, sizeof(struct aiocb));
162 priv_req->aiocb.aio_fildes = fd;
163 priv_req->aiocb.aio_nbytes = req->u.fread.len;
164 priv_req->aiocb.aio_offset = req->u.fread.offset;
165 priv_req->aiocb.aio_buf = buf;
166 priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
167 priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
168 priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
169 assert(aio_read(&priv_req->aiocb) >= 0);
171 /* We can advance the request consumer index, from here on, the request
172 * should not be used (it may be overrinden by a response) */
173 mount->ring.req_cons++;
174 }
176 static void end_file_read(struct fs_mount *mount, struct fs_request *priv_req)
177 {
178 RING_IDX rsp_idx;
179 fsif_response_t *rsp;
180 uint16_t req_id;
182 /* Release the grant */
183 assert(xc_gnttab_munmap(mount->gnth,
184 priv_req->page,
185 priv_req->count) == 0);
187 /* Get a response from the ring */
188 rsp_idx = mount->ring.rsp_prod_pvt++;
189 req_id = priv_req->req_shadow.id;
190 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
191 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
192 rsp->id = req_id;
193 rsp->u.ret_val = (uint64_t)aio_return(&priv_req->aiocb);
194 }
196 static void dispatch_file_write(struct fs_mount *mount, struct fsif_request *req)
197 {
198 void *buf;
199 int fd, count;
200 uint16_t req_id;
201 unsigned short priv_id;
202 struct fs_request *priv_req;
204 /* Read the request */
205 assert(req->u.fwrite.len > 0);
206 count = (req->u.fwrite.len - 1) / XC_PAGE_SIZE + 1;
207 assert(count <= FSIF_NR_WRITE_GNTS);
208 buf = xc_gnttab_map_domain_grant_refs(mount->gnth,
209 count,
210 mount->dom_id,
211 req->u.fwrite.grefs,
212 PROT_READ);
214 req_id = req->id;
215 FS_DEBUG("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n",
216 req->u.fwrite.fd, req->u.fwrite.len, req->u.fwrite.offset);
218 if (req->u.fwrite.fd < MAX_FDS)
219 fd = mount->fds[req->u.fwrite.fd];
220 else
221 fd = -1;
223 priv_id = get_request(mount, req);
224 FS_DEBUG("Private id is: %d\n", priv_id);
225 priv_req = &mount->requests[priv_id];
226 priv_req->page = buf;
227 priv_req->count = count;
228 priv_req->id = priv_id;
230 /* Dispatch AIO write request */
231 bzero(&priv_req->aiocb, sizeof(struct aiocb));
232 priv_req->aiocb.aio_fildes = fd;
233 priv_req->aiocb.aio_nbytes = req->u.fwrite.len;
234 priv_req->aiocb.aio_offset = req->u.fwrite.offset;
235 priv_req->aiocb.aio_buf = buf;
236 priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
237 priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
238 priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
239 assert(aio_write(&priv_req->aiocb) >= 0);
242 /* We can advance the request consumer index, from here on, the request
243 * should not be used (it may be overrinden by a response) */
244 mount->ring.req_cons++;
245 }
247 static void end_file_write(struct fs_mount *mount, struct fs_request *priv_req)
248 {
249 RING_IDX rsp_idx;
250 fsif_response_t *rsp;
251 uint16_t req_id;
253 /* Release the grant */
254 assert(xc_gnttab_munmap(mount->gnth,
255 priv_req->page,
256 priv_req->count) == 0);
258 /* Get a response from the ring */
259 rsp_idx = mount->ring.rsp_prod_pvt++;
260 req_id = priv_req->req_shadow.id;
261 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
262 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
263 rsp->id = req_id;
264 rsp->u.ret_val = (uint64_t)aio_return(&priv_req->aiocb);
265 }
267 static void dispatch_stat(struct fs_mount *mount, struct fsif_request *req)
268 {
269 struct stat stat;
270 int fd, ret;
271 uint16_t req_id;
272 RING_IDX rsp_idx;
273 fsif_response_t *rsp;
275 req_id = req->id;
276 if (req->u.fstat.fd < MAX_FDS)
277 fd = mount->fds[req->u.fstat.fd];
278 else
279 fd = -1;
281 FS_DEBUG("File stat issued for FD=%d\n", req->u.fstat.fd);
283 /* We can advance the request consumer index, from here on, the request
284 * should not be used (it may be overrinden by a response) */
285 mount->ring.req_cons++;
287 /* Stat, and create the response */
288 ret = fstat(fd, &stat);
289 FS_DEBUG("Mode=%o, uid=%d, a_time=%ld\n",
290 stat.st_mode, stat.st_uid, (long)stat.st_atime);
292 /* Get a response from the ring */
293 rsp_idx = mount->ring.rsp_prod_pvt++;
294 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
295 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
296 rsp->id = req_id;
297 rsp->u.fstat.stat_ret = (uint32_t)ret;
298 rsp->u.fstat.stat_mode = stat.st_mode;
299 rsp->u.fstat.stat_uid = stat.st_uid;
300 rsp->u.fstat.stat_gid = stat.st_gid;
301 #ifdef BLKGETSIZE
302 if (S_ISBLK(stat.st_mode)) {
303 unsigned long sectors;
304 if (ioctl(fd, BLKGETSIZE, &sectors)) {
305 perror("getting device size\n");
306 rsp->u.fstat.stat_size = 0;
307 } else
308 rsp->u.fstat.stat_size = sectors << 9;
309 } else
310 #endif
311 rsp->u.fstat.stat_size = stat.st_size;
312 rsp->u.fstat.stat_atime = stat.st_atime;
313 rsp->u.fstat.stat_mtime = stat.st_mtime;
314 rsp->u.fstat.stat_ctime = stat.st_ctime;
315 }
318 static void dispatch_truncate(struct fs_mount *mount, struct fsif_request *req)
319 {
320 int fd, ret;
321 uint16_t req_id;
322 RING_IDX rsp_idx;
323 fsif_response_t *rsp;
324 int64_t length;
326 req_id = req->id;
327 length = req->u.ftruncate.length;
328 FS_DEBUG("File truncate issued for FD=%d, length=%"PRId64"\n", req->u.ftruncate.fd, length);
330 if (req->u.ftruncate.fd < MAX_FDS)
331 fd = mount->fds[req->u.ftruncate.fd];
332 else
333 fd = -1;
335 /* We can advance the request consumer index, from here on, the request
336 * should not be used (it may be overrinden by a response) */
337 mount->ring.req_cons++;
339 /* Stat, and create the response */
340 ret = ftruncate(fd, length);
342 /* Get a response from the ring */
343 rsp_idx = mount->ring.rsp_prod_pvt++;
344 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
345 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
346 rsp->id = req_id;
347 rsp->u.ret_val = (uint64_t)ret;
348 }
350 static void dispatch_remove(struct fs_mount *mount, struct fsif_request *req)
351 {
352 char *file_name, full_path[BUFFER_SIZE];
353 int ret;
354 RING_IDX rsp_idx;
355 fsif_response_t *rsp;
356 uint16_t req_id;
358 FS_DEBUG("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
359 /* Read the request, and open file */
360 file_name = xc_gnttab_map_grant_ref(mount->gnth,
361 mount->dom_id,
362 req->u.fremove.gref,
363 PROT_READ);
365 req_id = req->id;
366 FS_DEBUG("File remove issued for %s\n", file_name);
367 assert(BUFFER_SIZE >
368 strlen(file_name) + strlen(mount->export->export_path) + 1);
369 snprintf(full_path, sizeof(full_path), "%s/%s",
370 mount->export->export_path, file_name);
371 assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
372 FS_DEBUG("Issuing remove for %s\n", full_path);
373 ret = remove(full_path);
374 FS_DEBUG("Got ret: %d\n", ret);
375 /* We can advance the request consumer index, from here on, the request
376 * should not be used (it may be overrinden by a response) */
377 mount->ring.req_cons++;
380 /* Get a response from the ring */
381 rsp_idx = mount->ring.rsp_prod_pvt++;
382 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
383 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
384 rsp->id = req_id;
385 rsp->u.ret_val = (uint64_t)ret;
386 }
389 static void dispatch_rename(struct fs_mount *mount, struct fsif_request *req)
390 {
391 char *buf, *old_file_name, *new_file_name;
392 char old_full_path[BUFFER_SIZE], new_full_path[BUFFER_SIZE];
393 int ret;
394 RING_IDX rsp_idx;
395 fsif_response_t *rsp;
396 uint16_t req_id;
398 FS_DEBUG("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
399 /* Read the request, and open file */
400 buf = xc_gnttab_map_grant_ref(mount->gnth,
401 mount->dom_id,
402 req->u.frename.gref,
403 PROT_READ);
405 req_id = req->id;
406 old_file_name = buf + req->u.frename.old_name_offset;
407 new_file_name = buf + req->u.frename.new_name_offset;
408 FS_DEBUG("File rename issued for %s -> %s (buf=%s)\n",
409 old_file_name, new_file_name, buf);
410 assert(BUFFER_SIZE >
411 strlen(old_file_name) + strlen(mount->export->export_path) + 1);
412 assert(BUFFER_SIZE >
413 strlen(new_file_name) + strlen(mount->export->export_path) + 1);
414 snprintf(old_full_path, sizeof(old_full_path), "%s/%s",
415 mount->export->export_path, old_file_name);
416 snprintf(new_full_path, sizeof(new_full_path), "%s/%s",
417 mount->export->export_path, new_file_name);
418 assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
419 FS_DEBUG("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
420 ret = rename(old_full_path, new_full_path);
421 FS_DEBUG("Got ret: %d\n", ret);
422 /* We can advance the request consumer index, from here on, the request
423 * should not be used (it may be overrinden by a response) */
424 mount->ring.req_cons++;
427 /* Get a response from the ring */
428 rsp_idx = mount->ring.rsp_prod_pvt++;
429 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
430 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
431 rsp->id = req_id;
432 rsp->u.ret_val = (uint64_t)ret;
433 }
436 static void dispatch_create(struct fs_mount *mount, struct fsif_request *req)
437 {
438 char *file_name, full_path[BUFFER_SIZE];
439 int ret;
440 int8_t directory;
441 int32_t mode;
442 RING_IDX rsp_idx;
443 fsif_response_t *rsp;
444 uint16_t req_id;
446 FS_DEBUG("Dispatching file create operation (gref=%d).\n", req->u.fcreate.gref);
447 /* Read the request, and create file/directory */
448 mode = req->u.fcreate.mode;
449 directory = req->u.fcreate.directory;
450 file_name = xc_gnttab_map_grant_ref(mount->gnth,
451 mount->dom_id,
452 req->u.fcreate.gref,
453 PROT_READ);
455 req_id = req->id;
456 FS_DEBUG("File create issued for %s\n", file_name);
457 assert(BUFFER_SIZE >
458 strlen(file_name) + strlen(mount->export->export_path) + 1);
459 snprintf(full_path, sizeof(full_path), "%s/%s",
460 mount->export->export_path, file_name);
461 assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
462 /* We can advance the request consumer index, from here on, the request
463 * should not be used (it may be overrinden by a response) */
464 mount->ring.req_cons++;
466 if(directory)
467 {
468 FS_DEBUG("Issuing create for directory: %s\n", full_path);
469 ret = mkdir(full_path, mode);
470 }
471 else
472 {
473 FS_DEBUG("Issuing create for file: %s\n", full_path);
474 ret = get_fd(mount);
475 if (ret >= 0) {
476 int real_fd = creat(full_path, mode);
477 if (real_fd < 0)
478 ret = -1;
479 else
480 {
481 mount->fds[ret] = real_fd;
482 FS_DEBUG("Got FD: %d for real %d\n", ret, real_fd);
483 }
484 }
485 }
486 FS_DEBUG("Got ret %d (errno=%d)\n", ret, errno);
488 /* Get a response from the ring */
489 rsp_idx = mount->ring.rsp_prod_pvt++;
490 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
491 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
492 rsp->id = req_id;
493 rsp->u.ret_val = (uint64_t)ret;
494 }
496 static void dispatch_list(struct fs_mount *mount, struct fsif_request *req)
497 {
498 char *file_name, *buf, full_path[BUFFER_SIZE];
499 uint32_t offset, nr_files, error_code;
500 uint64_t ret_val;
501 RING_IDX rsp_idx;
502 fsif_response_t *rsp;
503 uint16_t req_id;
504 DIR *dir;
505 struct dirent *dirent = NULL;
507 FS_DEBUG("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
508 /* Read the request, and list directory */
509 offset = req->u.flist.offset;
510 buf = file_name = xc_gnttab_map_grant_ref(mount->gnth,
511 mount->dom_id,
512 req->u.flist.gref,
513 PROT_READ | PROT_WRITE);
515 req_id = req->id;
516 FS_DEBUG("Dir list issued for %s\n", file_name);
517 assert(BUFFER_SIZE >
518 strlen(file_name) + strlen(mount->export->export_path) + 1);
519 snprintf(full_path, sizeof(full_path), "%s/%s",
520 mount->export->export_path, file_name);
521 /* We can advance the request consumer index, from here on, the request
522 * should not be used (it may be overrinden by a response) */
523 mount->ring.req_cons++;
525 ret_val = 0;
526 nr_files = 0;
527 dir = opendir(full_path);
528 if(dir == NULL)
529 {
530 error_code = errno;
531 goto error_out;
532 }
533 /* Skip offset dirs */
534 dirent = readdir(dir);
535 while(offset-- > 0 && dirent != NULL)
536 dirent = readdir(dir);
537 /* If there was any error with reading the directory, errno will be set */
538 error_code = errno;
539 /* Copy file names of the remaining non-NULL dirents into buf */
540 assert(NAME_MAX < XC_PAGE_SIZE >> 1);
541 while(dirent != NULL &&
542 (XC_PAGE_SIZE - ((unsigned long)buf & XC_PAGE_MASK) > NAME_MAX))
543 {
544 int curr_length = strlen(dirent->d_name) + 1;
546 memcpy(buf, dirent->d_name, curr_length);
547 buf += curr_length;
548 dirent = readdir(dir);
549 error_code = errno;
550 nr_files++;
551 }
552 error_out:
553 ret_val = ((nr_files << NR_FILES_SHIFT) & NR_FILES_MASK) |
554 ((error_code << ERROR_SHIFT) & ERROR_MASK) |
555 (dirent != NULL ? HAS_MORE_FLAG : 0);
556 assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
558 /* Get a response from the ring */
559 rsp_idx = mount->ring.rsp_prod_pvt++;
560 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
561 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
562 rsp->id = req_id;
563 rsp->u.ret_val = ret_val;
564 }
566 static void dispatch_chmod(struct fs_mount *mount, struct fsif_request *req)
567 {
568 int fd, ret;
569 RING_IDX rsp_idx;
570 fsif_response_t *rsp;
571 uint16_t req_id;
572 int32_t mode;
574 FS_DEBUG("Dispatching file chmod operation (fd=%d, mode=%o).\n",
575 req->u.fchmod.fd, req->u.fchmod.mode);
576 req_id = req->id;
577 if (req->u.fchmod.fd < MAX_FDS)
578 fd = mount->fds[req->u.fchmod.fd];
579 else
580 fd = -1;
582 mode = req->u.fchmod.mode;
583 /* We can advance the request consumer index, from here on, the request
584 * should not be used (it may be overrinden by a response) */
585 mount->ring.req_cons++;
587 ret = fchmod(fd, mode);
589 /* Get a response from the ring */
590 rsp_idx = mount->ring.rsp_prod_pvt++;
591 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
592 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
593 rsp->id = req_id;
594 rsp->u.ret_val = (uint64_t)ret;
595 }
597 static void dispatch_fs_space(struct fs_mount *mount, struct fsif_request *req)
598 {
599 char *file_name, full_path[BUFFER_SIZE];
600 RING_IDX rsp_idx;
601 fsif_response_t *rsp;
602 uint16_t req_id;
603 struct statvfs stat;
604 int64_t ret;
606 FS_DEBUG("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref);
607 /* Read the request, and open file */
608 file_name = xc_gnttab_map_grant_ref(mount->gnth,
609 mount->dom_id,
610 req->u.fspace.gref,
611 PROT_READ);
613 req_id = req->id;
614 FS_DEBUG("Fs space issued for %s\n", file_name);
615 assert(BUFFER_SIZE >
616 strlen(file_name) + strlen(mount->export->export_path) + 1);
617 snprintf(full_path, sizeof(full_path), "%s/%s",
618 mount->export->export_path, file_name);
619 assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
620 FS_DEBUG("Issuing fs space for %s\n", full_path);
621 ret = statvfs(full_path, &stat);
622 if(ret >= 0)
623 ret = stat.f_bsize * stat.f_bfree;
625 /* We can advance the request consumer index, from here on, the request
626 * should not be used (it may be overrinden by a response) */
627 mount->ring.req_cons++;
630 /* Get a response from the ring */
631 rsp_idx = mount->ring.rsp_prod_pvt++;
632 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
633 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
634 rsp->id = req_id;
635 rsp->u.ret_val = (uint64_t)ret;
636 }
638 static void dispatch_file_sync(struct fs_mount *mount, struct fsif_request *req)
639 {
640 int fd;
641 uint16_t req_id;
642 unsigned short priv_id;
643 struct fs_request *priv_req;
645 req_id = req->id;
646 if (req->u.fsync.fd < MAX_FDS)
647 fd = mount->fds[req->u.fsync.fd];
648 else
649 fd = -1;
651 FS_DEBUG("File sync issued for FD=%d\n", req->u.fsync.fd);
653 priv_id = get_request(mount, req);
654 FS_DEBUG("Private id is: %d\n", priv_id);
655 priv_req = &mount->requests[priv_id];
656 priv_req->id = priv_id;
658 /* Dispatch AIO read request */
659 bzero(&priv_req->aiocb, sizeof(struct aiocb));
660 priv_req->aiocb.aio_fildes = fd;
661 priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
662 priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
663 priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
664 assert(aio_fsync(O_SYNC, &priv_req->aiocb) >= 0);
667 /* We can advance the request consumer index, from here on, the request
668 * should not be used (it may be overrinden by a response) */
669 mount->ring.req_cons++;
670 }
672 static void end_file_sync(struct fs_mount *mount, struct fs_request *priv_req)
673 {
674 RING_IDX rsp_idx;
675 fsif_response_t *rsp;
676 uint16_t req_id;
678 /* Get a response from the ring */
679 rsp_idx = mount->ring.rsp_prod_pvt++;
680 req_id = priv_req->req_shadow.id;
681 FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
682 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
683 rsp->id = req_id;
684 rsp->u.ret_val = (uint64_t)aio_return(&priv_req->aiocb);
685 }
687 struct fs_op fopen_op = {.type = REQ_FILE_OPEN,
688 .dispatch_handler = dispatch_file_open,
689 .response_handler = NULL};
690 struct fs_op fclose_op = {.type = REQ_FILE_CLOSE,
691 .dispatch_handler = dispatch_file_close,
692 .response_handler = NULL};
693 struct fs_op fread_op = {.type = REQ_FILE_READ,
694 .dispatch_handler = dispatch_file_read,
695 .response_handler = end_file_read};
696 struct fs_op fwrite_op = {.type = REQ_FILE_WRITE,
697 .dispatch_handler = dispatch_file_write,
698 .response_handler = end_file_write};
699 struct fs_op fstat_op = {.type = REQ_STAT,
700 .dispatch_handler = dispatch_stat,
701 .response_handler = NULL};
702 struct fs_op ftruncate_op = {.type = REQ_FILE_TRUNCATE,
703 .dispatch_handler = dispatch_truncate,
704 .response_handler = NULL};
705 struct fs_op fremove_op = {.type = REQ_REMOVE,
706 .dispatch_handler = dispatch_remove,
707 .response_handler = NULL};
708 struct fs_op frename_op = {.type = REQ_RENAME,
709 .dispatch_handler = dispatch_rename,
710 .response_handler = NULL};
711 struct fs_op fcreate_op = {.type = REQ_CREATE,
712 .dispatch_handler = dispatch_create,
713 .response_handler = NULL};
714 struct fs_op flist_op = {.type = REQ_DIR_LIST,
715 .dispatch_handler = dispatch_list,
716 .response_handler = NULL};
717 struct fs_op fchmod_op = {.type = REQ_CHMOD,
718 .dispatch_handler = dispatch_chmod,
719 .response_handler = NULL};
720 struct fs_op fspace_op = {.type = REQ_FS_SPACE,
721 .dispatch_handler = dispatch_fs_space,
722 .response_handler = NULL};
723 struct fs_op fsync_op = {.type = REQ_FILE_SYNC,
724 .dispatch_handler = dispatch_file_sync,
725 .response_handler = end_file_sync};
728 struct fs_op *fsops[] = {&fopen_op,
729 &fclose_op,
730 &fread_op,
731 &fwrite_op,
732 &fstat_op,
733 &ftruncate_op,
734 &fremove_op,
735 &frename_op,
736 &fcreate_op,
737 &flist_op,
738 &fchmod_op,
739 &fspace_op,
740 &fsync_op,
741 NULL};