Annotation of prex/usr/server/fs/vfs/main.c, Revision 1.1.1.1
1.1 nbrk 1: /*
2: * Copyright (c) 2005-2007, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * main.c - File system server
32: */
33:
34: /*
35: * All file systems work as a sub-modules under VFS (Virtual File System).
36: * The routines in this file have the responsible to the following jobs.
37: *
38: * - Interpret the IPC message and pass the request into VFS routines.
39: * - Validate the some of passed arguments in the message.
40: * - Mapping of the task ID and cwd/file pointers.
41: *
42: * Note: All path string is translated to the full path before passing
43: * it to the sys_* routines.
44: */
45:
46: #include <prex/prex.h>
47: #include <prex/capability.h>
48: #include <server/fs.h>
49: #include <server/proc.h>
50: #include <server/stdmsg.h>
51: #include <server/object.h>
52: #include <sys/list.h>
53: #include <sys/stat.h>
54: #include <sys/vnode.h>
55: #include <sys/mount.h>
56: #include <sys/buf.h>
57: #include <sys/file.h>
58:
59: #include <limits.h>
60: #include <unistd.h>
61: #include <stdio.h>
62: #include <stdlib.h>
63: #include <string.h>
64: #include <errno.h>
65: #include <fcntl.h>
66: #include <signal.h>
67:
68: #include "vfs.h"
69:
70: #ifdef DEBUG_VFS
71: int vfs_debug = 0;
72: #endif
73: /*
74: * Message mapping
75: */
76: struct msg_map {
77: int code;
78: int (*func)(struct task *, struct msg *);
79: };
80:
81: #define MSGMAP(code, fn) {code, (int (*)(struct task *, struct msg *))fn}
82:
83: /* object for file service */
84: static object_t fs_obj;
85:
86:
87: static int
88: fs_mount(struct task *t, struct mount_msg *msg)
89: {
90: int err;
91:
92: /* Check mount capability. */
93: if ((t->cap & CAP_ADMIN) == 0)
94: return EPERM;
95:
96: err = sys_mount(msg->dev, msg->dir, msg->fs, msg->flags,
97: (void *)msg->data);
98: if (err)
99: dprintf("VFS: mount failed! fs=%s\n", msg->fs);
100: return err;
101: }
102:
103: static int
104: fs_umount(struct task *t, struct path_msg *msg)
105: {
106:
107: /* Check mount capability. */
108: if ((t->cap & CAP_ADMIN) == 0)
109: return EPERM;
110: return sys_umount(msg->path);
111: }
112:
113: static int
114: fs_sync(struct task *t, struct msg *msg)
115: {
116:
117: return sys_sync();
118: }
119:
120: static int
121: fs_open(struct task *t, struct open_msg *msg)
122: {
123: char path[PATH_MAX];
124: file_t fp;
125: int fd, err;
126: mode_t mode;
127:
128: /* Find empty slot for file descriptor. */
129: if ((fd = task_newfd(t)) == -1)
130: return EMFILE;
131:
132: /*
133: * Check the capability of caller task.
134: */
135: mode = msg->mode;
136: if ((mode & 0111) && (t->cap & CAP_EXEC) == 0)
137: return EACCES;
138: if ((mode & 0222) && (t->cap & CAP_FS_WRITE) == 0)
139: return EACCES;
140: if ((mode & 0444) && (t->cap & CAP_FS_READ) == 0)
141: return EACCES;
142:
143: if ((err = task_conv(t, msg->path, path)) != 0)
144: return err;
145: if ((err = sys_open(path, msg->flags, mode, &fp)) != 0)
146: return err;
147:
148: t->file[fd] = fp;
149: t->nopens++;
150: msg->fd = fd;
151: return 0;
152: }
153:
154: static int
155: fs_close(struct task *t, struct msg *msg)
156: {
157: file_t fp;
158: int fd, err;
159:
160: fd = msg->data[0];
161: if (fd >= OPEN_MAX)
162: return EBADF;
163:
164: fp = t->file[fd];
165: if (fp == NULL)
166: return EBADF;
167:
168: if ((err = sys_close(fp)) != 0)
169: return err;
170:
171: t->file[fd] = NULL;
172: t->nopens--;
173: return 0;
174: }
175:
176: static int
177: fs_mknod(struct task *t, struct open_msg *msg)
178: {
179: char path[PATH_MAX];
180: int err;
181:
182: if ((t->cap & CAP_FS_WRITE) == 0)
183: return EACCES;
184: if ((err = task_conv(t, msg->path, path)) != 0)
185: return err;
186: return sys_mknod(path, msg->mode);
187: }
188:
189: static int
190: fs_lseek(struct task *t, struct msg *msg)
191: {
192: file_t fp;
193: off_t offset, org;
194: int err, type;
195:
196: if ((fp = task_getfp(t, msg->data[0])) == NULL)
197: return EBADF;
198: offset = (off_t)msg->data[1];
199: type = msg->data[2];
200: err = sys_lseek(fp, offset, type, &org);
201: msg->data[0] = (int)org;
202: return err;
203: }
204:
205: static int
206: fs_read(struct task *t, struct io_msg *msg)
207: {
208: file_t fp;
209: void *buf;
210: size_t size, bytes;
211: int err;
212:
213: if ((fp = task_getfp(t, msg->fd)) == NULL)
214: return EBADF;
215: size = msg->size;
216: if ((err = vm_map(msg->hdr.task, msg->buf, size, &buf)) != 0)
217: return EFAULT;
218: err = sys_read(fp, buf, size, &bytes);
219: msg->size = bytes;
220: vm_free(task_self(), buf);
221: return err;
222: }
223:
224: static int
225: fs_write(struct task *t, struct io_msg *msg)
226: {
227: file_t fp;
228: void *buf;
229: size_t size, bytes;
230: int err;
231:
232: if ((fp = task_getfp(t, msg->fd)) == NULL)
233: return EBADF;
234: size = msg->size;
235: if ((err = vm_map(msg->hdr.task, msg->buf, size, &buf)) != 0)
236: return EFAULT;
237: err = sys_write(fp, buf, size, &bytes);
238: msg->size = bytes;
239: vm_free(task_self(), buf);
240: return err;
241: }
242:
243: static int
244: fs_ioctl(struct task *t, struct ioctl_msg *msg)
245: {
246: file_t fp;
247:
248: if ((fp = task_getfp(t, msg->fd)) == NULL)
249: return EBADF;
250: return sys_ioctl(fp, msg->request, msg->buf);
251: }
252:
253: static int
254: fs_fsync(struct task *t, struct msg *msg)
255: {
256: file_t fp;
257:
258: if ((fp = task_getfp(t, msg->data[0])) == NULL)
259: return EBADF;
260: return sys_fsync(fp);
261: }
262:
263: static int
264: fs_fstat(struct task *t, struct stat_msg *msg)
265: {
266: file_t fp;
267: struct stat *st;
268:
269: if ((fp = task_getfp(t, msg->fd)) == NULL)
270: return EBADF;
271: st = &msg->st;
272: return sys_fstat(fp, st);
273: }
274:
275: static int
276: fs_opendir(struct task *t, struct open_msg *msg)
277: {
278: char path[PATH_MAX];
279: file_t fp;
280: int fd, err;
281:
282: /* Find empty slot for file descriptor. */
283: if ((fd = task_newfd(t)) == -1)
284: return EMFILE;
285:
286: /* Get the mounted file system and node */
287: if ((err = task_conv(t, msg->path, path)) != 0)
288: return err;
289: if ((err = sys_opendir(path, &fp)) != 0)
290: return err;
291: t->file[fd] = fp;
292: msg->fd = fd;
293: return 0;
294: }
295:
296: static int
297: fs_closedir(struct task *t, struct msg *msg)
298: {
299: file_t fp;
300: int fd, err;
301:
302: fd = msg->data[0];
303: if (fd >= OPEN_MAX)
304: return EBADF;
305: fp = t->file[fd];
306: if (fp == NULL)
307: return EBADF;
308: if ((err = sys_closedir(fp)) != 0)
309: return err;
310: t->file[fd] = NULL;
311: return 0;
312: }
313:
314: static int
315: fs_readdir(struct task *t, struct dir_msg *msg)
316: {
317: file_t fp;
318:
319: if ((fp = task_getfp(t, msg->fd)) == NULL)
320: return EBADF;
321: return sys_readdir(fp, &msg->dirent);
322: }
323:
324: static int
325: fs_rewinddir(struct task *t, struct msg *msg)
326: {
327: file_t fp;
328:
329: if ((fp = task_getfp(t, msg->data[0])) == NULL)
330: return EBADF;
331: return sys_rewinddir(fp);
332: }
333:
334: static int
335: fs_seekdir(struct task *t, struct msg *msg)
336: {
337: file_t fp;
338: long loc;
339:
340: if ((fp = task_getfp(t, msg->data[0])) == NULL)
341: return EBADF;
342: loc = msg->data[1];
343: return sys_seekdir(fp, loc);
344: }
345:
346: static int
347: fs_telldir(struct task *t, struct msg *msg)
348: {
349: file_t fp;
350: long loc;
351: int err;
352:
353: if ((fp = task_getfp(t, msg->data[0])) == NULL)
354: return EBADF;
355: loc = msg->data[1];
356: if ((err = sys_telldir(fp, &loc)) != 0)
357: return err;
358: msg->data[0] = loc;
359: return 0;
360: }
361:
362: static int
363: fs_mkdir(struct task *t, struct open_msg *msg)
364: {
365: char path[PATH_MAX];
366: int err;
367:
368: if ((t->cap & CAP_FS_WRITE) == 0)
369: return EACCES;
370: if ((err = task_conv(t, msg->path, path)) != 0)
371: return err;
372: return sys_mkdir(path, msg->mode);
373: }
374:
375: static int
376: fs_rmdir(struct task *t, struct path_msg *msg)
377: {
378: char path[PATH_MAX];
379: int err;
380:
381: if ((t->cap & CAP_FS_WRITE) == 0)
382: return EACCES;
383: if (msg->path == NULL)
384: return ENOENT;
385: if ((err = task_conv(t, msg->path, path)) != 0)
386: return err;
387: return sys_rmdir(path);
388: }
389:
390: static int
391: fs_rename(struct task *t, struct path_msg *msg)
392: {
393: char src[PATH_MAX];
394: char dest[PATH_MAX];
395: int err;
396:
397: if ((t->cap & CAP_FS_WRITE) == 0)
398: return EACCES;
399: if (msg->path == NULL || msg->path2 == NULL)
400: return ENOENT;
401: if ((err = task_conv(t, msg->path, src)) != 0)
402: return err;
403: if ((err = task_conv(t, msg->path2, dest)) != 0)
404: return err;
405: return sys_rename(src, dest);
406: }
407:
408: static int
409: fs_chdir(struct task *t, struct path_msg *msg)
410: {
411: char path[PATH_MAX];
412: file_t fp;
413: int err;
414:
415: if (msg->path == NULL)
416: return ENOENT;
417: if ((err = task_conv(t, msg->path, path)) != 0)
418: return err;
419: /* Check if directory exits */
420: if ((err = sys_opendir(path, &fp)) != 0)
421: return err;
422: if (t->cwdfp)
423: sys_closedir(t->cwdfp);
424: t->cwdfp = fp;
425: strcpy(t->cwd, path);
426: return 0;
427: }
428:
429: static int
430: fs_link(struct task *t, struct msg *msg)
431: {
432: /* XXX */
433: return EPERM;
434: }
435:
436: static int
437: fs_unlink(struct task *t, struct path_msg *msg)
438: {
439: char path[PATH_MAX];
440:
441: if ((t->cap & CAP_FS_WRITE) == 0)
442: return EACCES;
443: if (msg->path == NULL)
444: return ENOENT;
445: task_conv(t, msg->path, path);
446: return sys_unlink(path);
447: }
448:
449: static int
450: fs_stat(struct task *t, struct stat_msg *msg)
451: {
452: char path[PATH_MAX];
453: struct stat *st;
454: int err;
455:
456: task_conv(t, msg->path, path);
457: st = &msg->st;
458: err = sys_stat(path, st);
459: return err;
460: }
461:
462: static int
463: fs_getcwd(struct task *t, struct path_msg *msg)
464: {
465:
466: strcpy(msg->path, t->cwd);
467: return 0;
468: }
469:
470: /*
471: * Duplicate a file descriptor.
472: */
473: static int
474: fs_dup(struct task *t, struct msg *msg)
475: {
476: file_t fp;
477: int old_fd, new_fd;
478:
479: old_fd = msg->data[0];
480: if (old_fd >= OPEN_MAX)
481: return EBADF;
482: fp = t->file[old_fd];
483: if (fp == NULL)
484: return EBADF;
485:
486: /* Find smallest empty slot as new fd. */
487: if ((new_fd = task_newfd(t)) == -1)
488: return EMFILE;
489:
490: t->file[new_fd] = fp;
491:
492: /* Increment file reference */
493: vref(fp->f_vnode);
494: fp->f_count++;
495:
496: msg->data[0] = new_fd;
497: return 0;
498: }
499:
500: /*
501: * Duplicate a file descriptor to a particular value.
502: */
503: static int
504: fs_dup2(struct task *t, struct msg *msg)
505: {
506: file_t fp, org;
507: int old_fd, new_fd;
508: int err;
509:
510: old_fd = msg->data[0];
511: new_fd = msg->data[1];
512: if (old_fd >= OPEN_MAX || new_fd >= OPEN_MAX)
513: return EBADF;
514: fp = t->file[old_fd];
515: if (fp == NULL)
516: return EBADF;
517: org = t->file[new_fd];
518: if (org != NULL) {
519: /* Close previous file if it's opened. */
520: err = sys_close(org);
521: }
522: t->file[new_fd] = fp;
523: msg->data[0] = new_fd;
524: return 0;
525: }
526:
527: /*
528: * The file control system call.
529: */
530: static int
531: fs_fcntl(struct task *t, struct fcntl_msg *msg)
532: {
533: file_t fp;
534: int arg, new_fd;
535:
536: if ((fp = task_getfp(t, msg->fd)) == NULL)
537: return EBADF;
538:
539: arg = msg->arg;
540: switch (msg->cmd) {
541: case F_DUPFD:
542: if (arg >= OPEN_MAX)
543: return EINVAL;
544:
545: /* Find smallest empty slot as new fd. */
546: if ((new_fd = task_newfd(t)) == -1)
547: return EMFILE;
548: t->file[new_fd] = fp;
549: break;
550: case F_GETFD:
551: msg->arg = fp->f_flags & FD_CLOEXEC;
552: break;
553: case F_SETFD:
554: fp->f_flags = (fp->f_flags & ~FD_CLOEXEC) |
555: (msg->arg & FD_CLOEXEC);
556: break;
557: case F_GETFL:
558: break;
559: case F_SETFL:
560: break;
561: default:
562: break;
563: }
564: return 0;
565: }
566:
567: /*
568: * Check permission for file access
569: */
570: static int
571: fs_access(struct task *t, struct path_msg *msg)
572: {
573: char path[PATH_MAX];
574: int mode, err;
575:
576: mode = msg->data[0];
577:
578: /*
579: * Check file permission.
580: */
581: task_conv(t, msg->path, path);
582: if ((err = sys_access(path, mode)) != 0)
583: return err;
584:
585: /*
586: * Check task permission.
587: */
588: err = EACCES;
589: if ((mode & X_OK) && (t->cap & CAP_EXEC) == 0)
590: goto out;
591: if ((mode & W_OK) && (t->cap & CAP_FS_WRITE) == 0)
592: goto out;
593: if ((mode & R_OK) && (t->cap & CAP_FS_READ) == 0)
594: goto out;
595: err = 0;
596: out:
597: return err;
598: }
599:
600: /*
601: * Copy parent's cwd & file/directory descriptor to child's.
602: */
603: static int
604: fs_fork(struct task *t, struct msg *msg)
605: {
606: struct task *newtask;
607: file_t fp;
608: int err, i;
609:
610: DPRINTF(VFSDB_CORE, ("fs_fork\n"));
611:
612: if ((err = task_alloc((task_t)msg->data[0], &newtask)) != 0)
613: return err;
614:
615: /*
616: * Copy task related data
617: */
618: newtask->cwdfp = t->cwdfp;
619: strcpy(newtask->cwd, t->cwd);
620: for (i = 0; i < OPEN_MAX; i++) {
621: fp = t->file[i];
622: newtask->file[i] = fp;
623: /*
624: * Increment file reference if it's
625: * already opened.
626: */
627: if (fp != NULL) {
628: vref(fp->f_vnode);
629: fp->f_count++;
630: }
631: }
632: if (newtask->cwdfp)
633: newtask->cwdfp->f_count++;
634: /* Increment cwd's reference count */
635: if (newtask->cwdfp)
636: vref(newtask->cwdfp->f_vnode);
637: return 0;
638: }
639:
640: /*
641: * fs_exec() is called for POSIX exec().
642: * It closes all directory stream.
643: * File descriptor which is marked close-on-exec are also closed.
644: */
645: static int
646: fs_exec(struct task *t, struct msg *msg)
647: {
648: task_t old_id, new_id;
649: struct task *target;
650: file_t fp;
651: int fd;
652:
653: old_id = (task_t)msg->data[0];
654: new_id = (task_t)msg->data[1];
655:
656: if (!(target = task_lookup(old_id)))
657: return EINVAL;
658:
659: /* Update task id in the task. */
660: task_update(target, new_id);
661:
662: /* Close all directory descriptor */
663: for (fd = 0; fd < OPEN_MAX; fd++) {
664: fp = target->file[fd];
665: if (fp) {
666: if (fp->f_vnode->v_type == VDIR) {
667: sys_close(fp);
668: target->file[fd] = NULL;
669: }
670:
671: /* XXX: need to check close-on-exec flag */
672: }
673: }
674: task_unlock(target);
675: return 0;
676: }
677:
678: /*
679: * fs_exit() cleans up data for task's termination.
680: */
681: static int
682: fs_exit(struct task *t, struct msg *msg)
683: {
684: file_t fp;
685: int fd;
686:
687: /*
688: * Close all files opened by task.
689: */
690: for (fd = 0; fd < OPEN_MAX; fd++) {
691: fp = t->file[fd];
692: if (fp != NULL)
693: sys_close(fp);
694: }
695: if (t->cwdfp)
696: sys_close(t->cwdfp);
697: task_free(t);
698: return 0;
699: }
700:
701: /*
702: * fs_register() is called by boot tasks.
703: * This can be called even when no fs is mounted.
704: */
705: static int
706: fs_register(struct task *t, struct msg *msg)
707: {
708: struct task *tmp;
709: cap_t cap;
710: int err;
711:
712: DPRINTF(VFSDB_CORE, ("fs_register\n"));
713:
714: if (task_getcap(msg->hdr.task, &cap))
715: return EINVAL;
716: if ((cap & CAP_ADMIN) == 0)
717: return EPERM;
718:
719: err = task_alloc(msg->hdr.task, &tmp);
720: return err;
721: }
722:
723: static int
724: fs_pipe(struct task *t, struct msg *msg)
725: {
726: #ifdef CONFIG_FIFOFS
727: char path[PATH_MAX];
728: file_t rfp, wfp;
729: int err, rfd, wfd;
730:
731: DPRINTF(VFSDB_CORE, ("fs_pipe\n"));
732:
733: if ((rfd = task_newfd(t)) == -1)
734: return EMFILE;
735: t->file[rfd] = (file_t)1; /* temp */
736:
737: if ((wfd = task_newfd(t)) == -1) {
738: t->file[rfd] = NULL;
739: return EMFILE;
740: }
741: sprintf(path, "/fifo/%x-%d", (u_int)t->task, rfd);
742:
743: if ((err = sys_mknod(path, S_IFIFO)) != 0)
744: goto out;
745: if ((err = sys_open(path, O_RDONLY | O_NONBLOCK, 0, &rfp)) != 0) {
746: goto out;
747: }
748: if ((err = sys_open(path, O_WRONLY | O_NONBLOCK, 0, &wfp)) != 0) {
749: goto out;
750: }
751: t->file[rfd] = rfp;
752: t->file[wfd] = wfp;
753: t->nopens += 2;
754: msg->data[0] = rfd;
755: msg->data[1] = wfd;
756: return 0;
757: out:
758: t->file[rfd] = NULL;
759: t->file[wfd] = NULL;
760: return err;
761: #else
762: return ENOSYS;
763: #endif
764: }
765:
766: /*
767: * Prepare for shutdown
768: */
769: static int
770: fs_shutdown(struct task *t, struct msg *msg)
771: {
772:
773: sys_sync();
774: return 0;
775: }
776:
777: /*
778: * Dump internal data.
779: */
780: static int
781: fs_debug(struct task *t, struct msg *msg)
782: {
783:
784: #ifdef DEBUG
785: dprintf("<File System Server>\n");
786: task_dump();
787: vnode_dump();
788: mount_dump();
789: #endif
790: return 0;
791: }
792:
793: /*
794: * Register to process server if it is loaded.
795: */
796: static void
797: process_init(void)
798: {
799: int i, err = 0;
800: object_t obj = 0;
801: struct msg m;
802:
803: /*
804: * Wait for server loading. timeout is 1 sec.
805: */
806: for (i = 0; i < 100; i++) {
807: err = object_lookup(OBJNAME_PROC, &obj);
808: if (err == 0)
809: break;
810:
811: /* Wait 10msec */
812: timer_sleep(10, 0);
813: thread_yield();
814: }
815: if (obj == 0)
816: return;
817:
818: /*
819: * Notify to process server.
820: */
821: m.hdr.code = PS_REGISTER;
822: msg_send(obj, &m, sizeof(m));
823: }
824:
825: static void
826: fs_init(void)
827: {
828: const struct vfssw *fs;
829: struct msg msg;
830:
831: process_init();
832:
833: /*
834: * Initialize VFS core.
835: */
836: task_init();
837: bio_init();
838: vnode_init();
839:
840: /*
841: * Initialize each file system.
842: */
843: for (fs = vfssw_table; fs->vs_name; fs++) {
844: DPRINTF(VFSDB_CORE, ("VFS: Initializing %s\n",
845: fs->vs_name));
846: fs->vs_init();
847: }
848:
849: /*
850: * Create task data for ourselves.
851: */
852: msg.hdr.task = task_self();
853: fs_register(NULL, &msg);
854: }
855:
856: /*
857: * Run specified routine as a thread.
858: */
859: static int
860: thread_run(void (*entry)(void))
861: {
862: task_t self;
863: thread_t th;
864: void *stack, *sp;
865: int err;
866:
867: self = task_self();
868: if ((err = thread_create(self, &th)) != 0)
869: return err;
870: if ((err = vm_allocate(self, &stack, USTACK_SIZE, 1)) != 0)
871: return err;
872:
873: sp = (void *)((u_long)stack + USTACK_SIZE - sizeof(u_long) * 3);
874: if ((err = thread_load(th, entry, sp)) != 0)
875: return err;
876: if ((err = thread_setprio(th, PRIO_FS)) != 0)
877: return err;
878:
879: return thread_resume(th);
880: }
881:
882: /*
883: * Message mapping
884: */
885: static const struct msg_map fsmsg_map[] = {
886: MSGMAP( STD_DEBUG, fs_debug ),
887: MSGMAP( STD_SHUTDOWN, fs_shutdown ),
888: MSGMAP( FS_MOUNT, fs_mount ),
889: MSGMAP( FS_UMOUNT, fs_umount ),
890: MSGMAP( FS_SYNC, fs_sync ),
891: MSGMAP( FS_OPEN, fs_open ),
892: MSGMAP( FS_CLOSE, fs_close ),
893: MSGMAP( FS_MKNOD, fs_mknod ),
894: MSGMAP( FS_LSEEK, fs_lseek ),
895: MSGMAP( FS_READ, fs_read ),
896: MSGMAP( FS_WRITE, fs_write ),
897: MSGMAP( FS_IOCTL, fs_ioctl ),
898: MSGMAP( FS_FSYNC, fs_fsync ),
899: MSGMAP( FS_FSTAT, fs_fstat ),
900: MSGMAP( FS_OPENDIR, fs_opendir ),
901: MSGMAP( FS_CLOSEDIR, fs_closedir ),
902: MSGMAP( FS_READDIR, fs_readdir ),
903: MSGMAP( FS_REWINDDIR, fs_rewinddir ),
904: MSGMAP( FS_SEEKDIR, fs_seekdir ),
905: MSGMAP( FS_TELLDIR, fs_telldir ),
906: MSGMAP( FS_MKDIR, fs_mkdir ),
907: MSGMAP( FS_RMDIR, fs_rmdir ),
908: MSGMAP( FS_RENAME, fs_rename ),
909: MSGMAP( FS_CHDIR, fs_chdir ),
910: MSGMAP( FS_LINK, fs_link ),
911: MSGMAP( FS_UNLINK, fs_unlink ),
912: MSGMAP( FS_STAT, fs_stat ),
913: MSGMAP( FS_GETCWD, fs_getcwd ),
914: MSGMAP( FS_DUP, fs_dup ),
915: MSGMAP( FS_DUP2, fs_dup2 ),
916: MSGMAP( FS_FCNTL, fs_fcntl ),
917: MSGMAP( FS_ACCESS, fs_access ),
918: MSGMAP( FS_FORK, fs_fork ),
919: MSGMAP( FS_EXEC, fs_exec ),
920: MSGMAP( FS_EXIT, fs_exit ),
921: MSGMAP( FS_REGISTER, fs_register ),
922: MSGMAP( FS_PIPE, fs_pipe ),
923: MSGMAP( 0, NULL ),
924: };
925:
926: /*
927: * File system thread.
928: */
929: static void
930: fs_thread(void)
931: {
932: struct msg *msg;
933: const struct msg_map *map;
934: struct task *t;
935: int err;
936:
937: msg = (struct msg *)malloc(MAX_FSMSG);
938:
939: /*
940: * Message loop
941: */
942: for (;;) {
943: /*
944: * Wait for an incoming request.
945: */
946: if ((err = msg_receive(fs_obj, msg, MAX_FSMSG)) != 0)
947: continue;
948:
949: err = EINVAL;
950: map = &fsmsg_map[0];
951: while (map->code != 0) {
952: if (map->code == msg->hdr.code) {
953: if (map->code == FS_REGISTER) {
954: err = fs_register(NULL, msg);
955: break;
956: }
957: /* Lookup and lock task */
958: t = task_lookup(msg->hdr.task);
959: if (t == NULL)
960: break;
961:
962: /* Get the capability list of caller task. */
963: if (task_getcap(msg->hdr.task, &t->cap))
964: break;
965:
966: /* Dispatch request */
967: err = (*map->func)(t, msg);
968: if (map->code != FS_EXIT)
969: task_unlock(t);
970: break;
971: }
972: map++;
973: }
974: #ifdef DEBUG_VFS
975: if (err)
976: dprintf("VFS: task=%x code=%x error=%d\n",
977: msg->hdr.task, map->code, err);
978: #endif
979: /*
980: * Reply to the client.
981: */
982: msg->hdr.status = err;
983: msg_reply(fs_obj, msg, MAX_FSMSG);
984: }
985: }
986:
987: /*
988: * Main routine for file system service
989: */
990: int
991: main(int argc, char *argv[])
992: {
993: int i;
994:
995: sys_log("Starting File System Server\n");
996:
997: /*
998: * Boost current priority.
999: */
1000: thread_setprio(thread_self(), PRIO_FS);
1001:
1002: /*
1003: * Initialize file systems.
1004: */
1005: fs_init();
1006:
1007: /*
1008: * Create an object to expose our service.
1009: */
1010: if (object_create(OBJNAME_FS, &fs_obj))
1011: sys_panic("VFS: fail to create object");
1012:
1013: /*
1014: * Create new server threads.
1015: */
1016: #ifdef DEBUG_VFS
1017: dprintf("VFS: Number of fs threads: %d\n", CONFIG_FS_THREADS);
1018: #endif
1019: i = CONFIG_FS_THREADS;
1020: while (--i > 0) {
1021: if (thread_run(fs_thread))
1022: goto err;
1023: }
1024: fs_thread();
1025: exit(0);
1026: err:
1027: sys_panic("VFS: failed to create thread");
1028: return 0;
1029: }
CVSweb