ia64/xen-unstable

view tools/fs-back/fs-ops.c @ 17838:e5c9c8e6e726

tools: replace sprintf with snprintf where applicable

Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 12 15:41:15 2008 +0100 (2008-06-12)
parents a1a3fe600ef3
children ea6a9793928d
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/vfs.h>
14 #include <sys/mount.h>
15 #include <unistd.h>
16 #include "fs-backend.h"
18 /* For debugging only */
19 #include <sys/time.h>
20 #include <time.h>
23 #define BUFFER_SIZE 1024
26 unsigned short get_request(struct mount *mount, struct fsif_request *req)
27 {
28 unsigned short id = get_id_from_freelist(mount->freelist);
30 printf("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 }
38 void dispatch_file_open(struct mount *mount, struct fsif_request *req)
39 {
40 char *file_name, full_path[BUFFER_SIZE];
41 int fd;
42 struct timeval tv1, tv2;
43 RING_IDX rsp_idx;
44 fsif_response_t *rsp;
45 uint16_t req_id;
47 printf("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref);
48 /* Read the request, and open file */
49 file_name = xc_gnttab_map_grant_ref(mount->gnth,
50 mount->dom_id,
51 req->u.fopen.gref,
52 PROT_READ);
54 req_id = req->id;
55 printf("File open issued for %s\n", file_name);
56 assert(BUFFER_SIZE >
57 strlen(file_name) + strlen(mount->export->export_path) + 1);
58 snprintf(full_path, sizeof(full_path), "%s/%s",
59 mount->export->export_path, file_name);
60 assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
61 printf("Issuing open for %s\n", full_path);
62 fd = open(full_path, O_RDWR);
63 printf("Got FD: %d\n", fd);
64 /* We can advance the request consumer index, from here on, the request
65 * should not be used (it may be overrinden by a response) */
66 mount->ring.req_cons++;
69 /* Get a response from the ring */
70 rsp_idx = mount->ring.rsp_prod_pvt++;
71 printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
72 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
73 rsp->id = req_id;
74 rsp->ret_val = (uint64_t)fd;
75 }
77 void dispatch_file_close(struct mount *mount, struct fsif_request *req)
78 {
79 int ret;
80 RING_IDX rsp_idx;
81 fsif_response_t *rsp;
82 uint16_t req_id;
84 printf("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
86 req_id = req->id;
87 ret = close(req->u.fclose.fd);
88 printf("Got ret: %d\n", ret);
89 /* We can advance the request consumer index, from here on, the request
90 * should not be used (it may be overrinden by a response) */
91 mount->ring.req_cons++;
94 /* Get a response from the ring */
95 rsp_idx = mount->ring.rsp_prod_pvt++;
96 printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
97 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
98 rsp->id = req_id;
99 rsp->ret_val = (uint64_t)ret;
100 }
101 void dispatch_file_read(struct mount *mount, struct fsif_request *req)
102 {
103 void *buf;
104 int fd;
105 uint16_t req_id;
106 unsigned short priv_id;
107 struct fs_request *priv_req;
109 /* Read the request */
110 buf = xc_gnttab_map_grant_ref(mount->gnth,
111 mount->dom_id,
112 req->u.fread.gref,
113 PROT_WRITE);
115 req_id = req->id;
116 printf("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n",
117 req->u.fread.fd, req->u.fread.len, req->u.fread.offset);
119 priv_id = get_request(mount, req);
120 printf("Private id is: %d\n", priv_id);
121 priv_req = &mount->requests[priv_id];
122 priv_req->page = buf;
124 /* Dispatch AIO read request */
125 bzero(&priv_req->aiocb, sizeof(struct aiocb));
126 priv_req->aiocb.aio_fildes = req->u.fread.fd;
127 priv_req->aiocb.aio_nbytes = req->u.fread.len;
128 priv_req->aiocb.aio_offset = req->u.fread.offset;
129 priv_req->aiocb.aio_buf = buf;
130 assert(aio_read(&priv_req->aiocb) >= 0);
133 /* We can advance the request consumer index, from here on, the request
134 * should not be used (it may be overrinden by a response) */
135 mount->ring.req_cons++;
136 }
138 void end_file_read(struct mount *mount, struct fs_request *priv_req)
139 {
140 RING_IDX rsp_idx;
141 fsif_response_t *rsp;
142 uint16_t req_id;
144 /* Release the grant */
145 assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0);
147 /* Get a response from the ring */
148 rsp_idx = mount->ring.rsp_prod_pvt++;
149 req_id = priv_req->req_shadow.id;
150 printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
151 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
152 rsp->id = req_id;
153 rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
154 }
156 void dispatch_file_write(struct mount *mount, struct fsif_request *req)
157 {
158 void *buf;
159 int fd;
160 uint16_t req_id;
161 unsigned short priv_id;
162 struct fs_request *priv_req;
164 /* Read the request */
165 buf = xc_gnttab_map_grant_ref(mount->gnth,
166 mount->dom_id,
167 req->u.fwrite.gref,
168 PROT_READ);
170 req_id = req->id;
171 printf("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n",
172 req->u.fwrite.fd, req->u.fwrite.len, req->u.fwrite.offset);
174 priv_id = get_request(mount, req);
175 printf("Private id is: %d\n", priv_id);
176 priv_req = &mount->requests[priv_id];
177 priv_req->page = buf;
179 /* Dispatch AIO write request */
180 bzero(&priv_req->aiocb, sizeof(struct aiocb));
181 priv_req->aiocb.aio_fildes = req->u.fwrite.fd;
182 priv_req->aiocb.aio_nbytes = req->u.fwrite.len;
183 priv_req->aiocb.aio_offset = req->u.fwrite.offset;
184 priv_req->aiocb.aio_buf = buf;
185 assert(aio_write(&priv_req->aiocb) >= 0);
188 /* We can advance the request consumer index, from here on, the request
189 * should not be used (it may be overrinden by a response) */
190 mount->ring.req_cons++;
191 }
193 void end_file_write(struct mount *mount, struct fs_request *priv_req)
194 {
195 RING_IDX rsp_idx;
196 fsif_response_t *rsp;
197 uint16_t req_id;
199 /* Release the grant */
200 assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0);
202 /* Get a response from the ring */
203 rsp_idx = mount->ring.rsp_prod_pvt++;
204 req_id = priv_req->req_shadow.id;
205 printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
206 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
207 rsp->id = req_id;
208 rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
209 }
211 void dispatch_stat(struct mount *mount, struct fsif_request *req)
212 {
213 struct fsif_stat_response *buf;
214 struct stat stat;
215 int fd, ret;
216 uint16_t req_id;
217 RING_IDX rsp_idx;
218 fsif_response_t *rsp;
220 /* Read the request */
221 buf = xc_gnttab_map_grant_ref(mount->gnth,
222 mount->dom_id,
223 req->u.fstat.gref,
224 PROT_WRITE);
226 req_id = req->id;
227 fd = req->u.fstat.fd;
228 printf("File stat issued for FD=%d\n", fd);
230 /* We can advance the request consumer index, from here on, the request
231 * should not be used (it may be overrinden by a response) */
232 mount->ring.req_cons++;
234 /* Stat, and create the response */
235 ret = fstat(fd, &stat);
236 printf("Mode=%o, uid=%d, a_time=%ld\n",
237 stat.st_mode, stat.st_uid, stat.st_atime);
238 buf->stat_mode = stat.st_mode;
239 buf->stat_uid = stat.st_uid;
240 buf->stat_gid = stat.st_gid;
241 #ifdef BLKGETSIZE
242 if (S_ISBLK(stat.st_mode)) {
243 int sectors;
244 if (ioctl(fd, BLKGETSIZE, &sectors)) {
245 perror("getting device size\n");
246 buf->stat_size = 0;
247 } else
248 buf->stat_size = sectors << 9;
249 } else
250 #endif
251 buf->stat_size = stat.st_size;
252 buf->stat_atime = stat.st_atime;
253 buf->stat_mtime = stat.st_mtime;
254 buf->stat_ctime = stat.st_ctime;
256 /* Release the grant */
257 assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
259 /* Get a response from the ring */
260 rsp_idx = mount->ring.rsp_prod_pvt++;
261 printf("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->ret_val = (uint64_t)ret;
265 }
268 void dispatch_truncate(struct mount *mount, struct fsif_request *req)
269 {
270 int fd, ret;
271 uint16_t req_id;
272 RING_IDX rsp_idx;
273 fsif_response_t *rsp;
274 int64_t length;
276 req_id = req->id;
277 fd = req->u.ftruncate.fd;
278 length = req->u.ftruncate.length;
279 printf("File truncate issued for FD=%d, length=%"PRId64"\n", fd, length);
281 /* We can advance the request consumer index, from here on, the request
282 * should not be used (it may be overrinden by a response) */
283 mount->ring.req_cons++;
285 /* Stat, and create the response */
286 ret = ftruncate(fd, length);
288 /* Get a response from the ring */
289 rsp_idx = mount->ring.rsp_prod_pvt++;
290 printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
291 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
292 rsp->id = req_id;
293 rsp->ret_val = (uint64_t)ret;
294 }
296 void dispatch_remove(struct mount *mount, struct fsif_request *req)
297 {
298 char *file_name, full_path[BUFFER_SIZE];
299 int ret;
300 RING_IDX rsp_idx;
301 fsif_response_t *rsp;
302 uint16_t req_id;
304 printf("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
305 /* Read the request, and open file */
306 file_name = xc_gnttab_map_grant_ref(mount->gnth,
307 mount->dom_id,
308 req->u.fremove.gref,
309 PROT_READ);
311 req_id = req->id;
312 printf("File remove issued for %s\n", file_name);
313 assert(BUFFER_SIZE >
314 strlen(file_name) + strlen(mount->export->export_path) + 1);
315 snprintf(full_path, sizeof(full_path), "%s/%s",
316 mount->export->export_path, file_name);
317 assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
318 printf("Issuing remove for %s\n", full_path);
319 ret = remove(full_path);
320 printf("Got ret: %d\n", ret);
321 /* We can advance the request consumer index, from here on, the request
322 * should not be used (it may be overrinden by a response) */
323 mount->ring.req_cons++;
326 /* Get a response from the ring */
327 rsp_idx = mount->ring.rsp_prod_pvt++;
328 printf("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->ret_val = (uint64_t)ret;
332 }
335 void dispatch_rename(struct mount *mount, struct fsif_request *req)
336 {
337 char *buf, *old_file_name, *new_file_name;
338 char old_full_path[BUFFER_SIZE], new_full_path[BUFFER_SIZE];
339 int ret;
340 RING_IDX rsp_idx;
341 fsif_response_t *rsp;
342 uint16_t req_id;
344 printf("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
345 /* Read the request, and open file */
346 buf = xc_gnttab_map_grant_ref(mount->gnth,
347 mount->dom_id,
348 req->u.frename.gref,
349 PROT_READ);
351 req_id = req->id;
352 old_file_name = buf + req->u.frename.old_name_offset;
353 new_file_name = buf + req->u.frename.new_name_offset;
354 printf("File rename issued for %s -> %s (buf=%s)\n",
355 old_file_name, new_file_name, buf);
356 assert(BUFFER_SIZE >
357 strlen(old_file_name) + strlen(mount->export->export_path) + 1);
358 assert(BUFFER_SIZE >
359 strlen(new_file_name) + strlen(mount->export->export_path) + 1);
360 snprintf(old_full_path, sizeof(old_full_path), "%s/%s",
361 mount->export->export_path, old_file_name);
362 snprintf(new_full_path, sizeof(new_full_path), "%s/%s",
363 mount->export->export_path, new_file_name);
364 assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
365 printf("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
366 ret = rename(old_full_path, new_full_path);
367 printf("Got ret: %d\n", ret);
368 /* We can advance the request consumer index, from here on, the request
369 * should not be used (it may be overrinden by a response) */
370 mount->ring.req_cons++;
373 /* Get a response from the ring */
374 rsp_idx = mount->ring.rsp_prod_pvt++;
375 printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
376 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
377 rsp->id = req_id;
378 rsp->ret_val = (uint64_t)ret;
379 }
382 void dispatch_create(struct mount *mount, struct fsif_request *req)
383 {
384 char *file_name, full_path[BUFFER_SIZE];
385 int ret;
386 int8_t directory;
387 int32_t mode;
388 RING_IDX rsp_idx;
389 fsif_response_t *rsp;
390 uint16_t req_id;
392 printf("Dispatching file create operation (gref=%d).\n", req->u.fcreate.gref);
393 /* Read the request, and create file/directory */
394 mode = req->u.fcreate.mode;
395 directory = req->u.fcreate.directory;
396 file_name = xc_gnttab_map_grant_ref(mount->gnth,
397 mount->dom_id,
398 req->u.fcreate.gref,
399 PROT_READ);
401 req_id = req->id;
402 printf("File create issued for %s\n", file_name);
403 assert(BUFFER_SIZE >
404 strlen(file_name) + strlen(mount->export->export_path) + 1);
405 snprintf(full_path, sizeof(full_path), "%s/%s",
406 mount->export->export_path, file_name);
407 assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
408 /* We can advance the request consumer index, from here on, the request
409 * should not be used (it may be overrinden by a response) */
410 mount->ring.req_cons++;
412 if(directory)
413 {
414 printf("Issuing create for directory: %s\n", full_path);
415 ret = mkdir(full_path, mode);
416 }
417 else
418 {
419 printf("Issuing create for file: %s\n", full_path);
420 ret = creat(full_path, mode);
421 }
422 printf("Got ret %d (errno=%d)\n", ret, errno);
424 /* Get a response from the ring */
425 rsp_idx = mount->ring.rsp_prod_pvt++;
426 printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
427 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
428 rsp->id = req_id;
429 rsp->ret_val = (uint64_t)ret;
430 }
432 void dispatch_list(struct mount *mount, struct fsif_request *req)
433 {
434 char *file_name, *buf, full_path[BUFFER_SIZE];
435 uint32_t offset, nr_files, error_code;
436 uint64_t ret_val;
437 RING_IDX rsp_idx;
438 fsif_response_t *rsp;
439 uint16_t req_id;
440 DIR *dir;
441 struct dirent *dirent = NULL;
443 printf("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
444 /* Read the request, and list directory */
445 offset = req->u.flist.offset;
446 buf = file_name = xc_gnttab_map_grant_ref(mount->gnth,
447 mount->dom_id,
448 req->u.flist.gref,
449 PROT_READ | PROT_WRITE);
451 req_id = req->id;
452 printf("Dir list issued for %s\n", file_name);
453 assert(BUFFER_SIZE >
454 strlen(file_name) + strlen(mount->export->export_path) + 1);
455 snprintf(full_path, sizeof(full_path), "%s/%s",
456 mount->export->export_path, file_name);
457 /* We can advance the request consumer index, from here on, the request
458 * should not be used (it may be overrinden by a response) */
459 mount->ring.req_cons++;
461 ret_val = 0;
462 nr_files = 0;
463 dir = opendir(full_path);
464 if(dir == NULL)
465 {
466 error_code = errno;
467 goto error_out;
468 }
469 /* Skip offset dirs */
470 dirent = readdir(dir);
471 while(offset-- > 0 && dirent != NULL)
472 dirent = readdir(dir);
473 /* If there was any error with reading the directory, errno will be set */
474 error_code = errno;
475 /* Copy file names of the remaining non-NULL dirents into buf */
476 assert(NAME_MAX < PAGE_SIZE >> 1);
477 while(dirent != NULL &&
478 (PAGE_SIZE - ((unsigned long)buf & PAGE_MASK) > NAME_MAX))
479 {
480 int curr_length = strlen(dirent->d_name) + 1;
482 memcpy(buf, dirent->d_name, curr_length);
483 buf += curr_length;
484 dirent = readdir(dir);
485 error_code = errno;
486 nr_files++;
487 }
488 error_out:
489 ret_val = ((nr_files << NR_FILES_SHIFT) & NR_FILES_MASK) |
490 ((error_code << ERROR_SHIFT) & ERROR_MASK) |
491 (dirent != NULL ? HAS_MORE_FLAG : 0);
492 assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
494 /* Get a response from the ring */
495 rsp_idx = mount->ring.rsp_prod_pvt++;
496 printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
497 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
498 rsp->id = req_id;
499 rsp->ret_val = ret_val;
500 }
502 void dispatch_chmod(struct mount *mount, struct fsif_request *req)
503 {
504 int fd, ret;
505 RING_IDX rsp_idx;
506 fsif_response_t *rsp;
507 uint16_t req_id;
508 int32_t mode;
510 printf("Dispatching file chmod operation (fd=%d, mode=%o).\n",
511 req->u.fchmod.fd, req->u.fchmod.mode);
512 req_id = req->id;
513 fd = req->u.fchmod.fd;
514 mode = req->u.fchmod.mode;
515 /* We can advance the request consumer index, from here on, the request
516 * should not be used (it may be overrinden by a response) */
517 mount->ring.req_cons++;
519 ret = fchmod(fd, mode);
521 /* Get a response from the ring */
522 rsp_idx = mount->ring.rsp_prod_pvt++;
523 printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
524 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
525 rsp->id = req_id;
526 rsp->ret_val = (uint64_t)ret;
527 }
529 void dispatch_fs_space(struct mount *mount, struct fsif_request *req)
530 {
531 char *file_name, full_path[BUFFER_SIZE];
532 RING_IDX rsp_idx;
533 fsif_response_t *rsp;
534 uint16_t req_id;
535 struct statfs stat;
536 int64_t ret;
538 printf("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref);
539 /* Read the request, and open file */
540 file_name = xc_gnttab_map_grant_ref(mount->gnth,
541 mount->dom_id,
542 req->u.fspace.gref,
543 PROT_READ);
545 req_id = req->id;
546 printf("Fs space issued for %s\n", file_name);
547 assert(BUFFER_SIZE >
548 strlen(file_name) + strlen(mount->export->export_path) + 1);
549 snprintf(full_path, sizeof(full_path), "%s/%s",
550 mount->export->export_path, file_name);
551 assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
552 printf("Issuing fs space for %s\n", full_path);
553 ret = statfs(full_path, &stat);
554 if(ret >= 0)
555 ret = stat.f_bsize * stat.f_bfree;
557 /* We can advance the request consumer index, from here on, the request
558 * should not be used (it may be overrinden by a response) */
559 mount->ring.req_cons++;
562 /* Get a response from the ring */
563 rsp_idx = mount->ring.rsp_prod_pvt++;
564 printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
565 rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
566 rsp->id = req_id;
567 rsp->ret_val = (uint64_t)ret;
568 }
570 void dispatch_file_sync(struct mount *mount, struct fsif_request *req)
571 {
572 int fd;
573 uint16_t req_id;
574 unsigned short priv_id;
575 struct fs_request *priv_req;
577 req_id = req->id;
578 fd = req->u.fsync.fd;
579 printf("File sync issued for FD=%d\n", fd);
581 priv_id = get_request(mount, req);
582 printf("Private id is: %d\n", priv_id);
583 priv_req = &mount->requests[priv_id];
585 /* Dispatch AIO read request */
586 bzero(&priv_req->aiocb, sizeof(struct aiocb));
587 priv_req->aiocb.aio_fildes = fd;
588 assert(aio_fsync(O_SYNC, &priv_req->aiocb) >= 0);
591 /* We can advance the request consumer index, from here on, the request
592 * should not be used (it may be overrinden by a response) */
593 mount->ring.req_cons++;
594 }
596 void end_file_sync(struct mount *mount, struct fs_request *priv_req)
597 {
598 RING_IDX rsp_idx;
599 fsif_response_t *rsp;
600 uint16_t req_id;
602 /* Get a response from the ring */
603 rsp_idx = mount->ring.rsp_prod_pvt++;
604 req_id = priv_req->req_shadow.id;
605 printf("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->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
609 }
611 struct fs_op fopen_op = {.type = REQ_FILE_OPEN,
612 .dispatch_handler = dispatch_file_open,
613 .response_handler = NULL};
614 struct fs_op fclose_op = {.type = REQ_FILE_CLOSE,
615 .dispatch_handler = dispatch_file_close,
616 .response_handler = NULL};
617 struct fs_op fread_op = {.type = REQ_FILE_READ,
618 .dispatch_handler = dispatch_file_read,
619 .response_handler = end_file_read};
620 struct fs_op fwrite_op = {.type = REQ_FILE_WRITE,
621 .dispatch_handler = dispatch_file_write,
622 .response_handler = end_file_write};
623 struct fs_op fstat_op = {.type = REQ_STAT,
624 .dispatch_handler = dispatch_stat,
625 .response_handler = NULL};
626 struct fs_op ftruncate_op = {.type = REQ_FILE_TRUNCATE,
627 .dispatch_handler = dispatch_truncate,
628 .response_handler = NULL};
629 struct fs_op fremove_op = {.type = REQ_REMOVE,
630 .dispatch_handler = dispatch_remove,
631 .response_handler = NULL};
632 struct fs_op frename_op = {.type = REQ_RENAME,
633 .dispatch_handler = dispatch_rename,
634 .response_handler = NULL};
635 struct fs_op fcreate_op = {.type = REQ_CREATE,
636 .dispatch_handler = dispatch_create,
637 .response_handler = NULL};
638 struct fs_op flist_op = {.type = REQ_DIR_LIST,
639 .dispatch_handler = dispatch_list,
640 .response_handler = NULL};
641 struct fs_op fchmod_op = {.type = REQ_CHMOD,
642 .dispatch_handler = dispatch_chmod,
643 .response_handler = NULL};
644 struct fs_op fspace_op = {.type = REQ_FS_SPACE,
645 .dispatch_handler = dispatch_fs_space,
646 .response_handler = NULL};
647 struct fs_op fsync_op = {.type = REQ_FILE_SYNC,
648 .dispatch_handler = dispatch_file_sync,
649 .response_handler = end_file_sync};
652 struct fs_op *fsops[] = {&fopen_op,
653 &fclose_op,
654 &fread_op,
655 &fwrite_op,
656 &fstat_op,
657 &ftruncate_op,
658 &fremove_op,
659 &frename_op,
660 &fcreate_op,
661 &flist_op,
662 &fchmod_op,
663 &fspace_op,
664 &fsync_op,
665 NULL};