Annotation of prex-old/usr/server/fs/vfs/main.c, Revision 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/file.h>
! 57: #include <sys/syslog.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: /*
! 71: * Message mapping
! 72: */
! 73: struct msg_map {
! 74: int code;
! 75: int (*func)(struct task *, struct msg *);
! 76: };
! 77:
! 78: #define MSGMAP(code, fn) {code, (int (*)(struct task *, struct msg *))fn}
! 79:
! 80: /* object for file service */
! 81: static object_t fs_obj;
! 82:
! 83:
! 84: static int
! 85: fs_mount(struct task *t, struct mount_msg *msg)
! 86: {
! 87: int err;
! 88:
! 89: /* Check mount capability. */
! 90: if ((t->cap & CAP_ADMIN) == 0)
! 91: return EPERM;
! 92:
! 93: err = sys_mount(msg->dev, msg->dir, msg->fs, msg->flags,
! 94: (void *)msg->data);
! 95: #ifdef DEBUG
! 96: if (err)
! 97: syslog(LOG_INFO, "fs: mount failed! fs=%s\n", msg->fs);
! 98: #endif
! 99: return err;
! 100: }
! 101:
! 102: static int
! 103: fs_umount(struct task *t, struct path_msg *msg)
! 104: {
! 105:
! 106: /* Check mount capability. */
! 107: if ((t->cap & CAP_ADMIN) == 0)
! 108: return EPERM;
! 109: return sys_umount(msg->path);
! 110: }
! 111:
! 112: static int
! 113: fs_sync(struct task *t, struct msg *msg)
! 114: {
! 115:
! 116: return sys_sync();
! 117: }
! 118:
! 119: static int
! 120: fs_open(struct task *t, struct open_msg *msg)
! 121: {
! 122: char path[PATH_MAX];
! 123: file_t fp;
! 124: int fd, err;
! 125: mode_t mode;
! 126:
! 127: /* Find empty slot for file descriptor */
! 128: for (fd = 0; fd < OPEN_MAX; fd++)
! 129: if (t->file[fd] == NULL)
! 130: break;
! 131: if (fd == OPEN_MAX)
! 132: return EMFILE;
! 133:
! 134: /* Check the capability of caller task */
! 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->nr_open++;
! 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->nr_open--;
! 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 ((err = task_conv(t, msg->path, path)) != 0)
! 183: return err;
! 184: return sys_mknod(path, msg->mode);
! 185: }
! 186:
! 187: static int
! 188: fs_lseek(struct task *t, struct msg *msg)
! 189: {
! 190: file_t fp;
! 191: off_t offset, org;
! 192: int err, type;
! 193:
! 194: if ((fp = task_getfp(t, msg->data[0])) == NULL)
! 195: return EBADF;
! 196: offset = (off_t)msg->data[1];
! 197: type = msg->data[2];
! 198: err = sys_lseek(fp, offset, type, &org);
! 199: msg->data[0] = (int)org;
! 200: return err;
! 201: }
! 202:
! 203: static int
! 204: fs_read(struct task *t, struct io_msg *msg)
! 205: {
! 206: file_t fp;
! 207: void *buf;
! 208: size_t size, bytes;
! 209: int err;
! 210:
! 211: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 212: return EBADF;
! 213: size = msg->size;
! 214: if ((err = vm_map(msg->hdr.task, msg->buf, size, &buf)) != 0)
! 215: return EFAULT;
! 216: err = sys_read(fp, buf, size, &bytes);
! 217: msg->size = bytes;
! 218: vm_free(task_self(), buf);
! 219: return err;
! 220: }
! 221:
! 222: static int
! 223: fs_write(struct task *t, struct io_msg *msg)
! 224: {
! 225: file_t fp;
! 226: void *buf;
! 227: size_t size, bytes;
! 228: int err;
! 229:
! 230: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 231: return EBADF;
! 232: size = msg->size;
! 233: if ((err = vm_map(msg->hdr.task, msg->buf, size, &buf)) != 0)
! 234: return EFAULT;
! 235: err = sys_write(fp, buf, size, &bytes);
! 236: msg->size = bytes;
! 237: vm_free(task_self(), buf);
! 238: return err;
! 239: }
! 240:
! 241: static int
! 242: fs_ioctl(struct task *t, struct ioctl_msg *msg)
! 243: {
! 244: file_t fp;
! 245:
! 246: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 247: return EBADF;
! 248: return sys_ioctl(fp, msg->request, msg->buf);
! 249: }
! 250:
! 251: static int
! 252: fs_fsync(struct task *t, struct msg *msg)
! 253: {
! 254: file_t fp;
! 255:
! 256: if ((fp = task_getfp(t, msg->data[0])) == NULL)
! 257: return EBADF;
! 258: return sys_fsync(fp);
! 259: }
! 260:
! 261: static int
! 262: fs_fstat(struct task *t, struct stat_msg *msg)
! 263: {
! 264: file_t fp;
! 265: struct stat *st;
! 266:
! 267: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 268: return EBADF;
! 269: st = &msg->st;
! 270: return sys_fstat(fp, st);
! 271: }
! 272:
! 273: static int
! 274: fs_opendir(struct task *t, struct open_msg *msg)
! 275: {
! 276: char path[PATH_MAX];
! 277: file_t fp;
! 278: int fd, err;
! 279:
! 280: /* Find empty slot for file structure */
! 281: for (fd = 0; fd < OPEN_MAX; fd++)
! 282: if (t->file[fd] == NULL)
! 283: break;
! 284: if (fd == OPEN_MAX)
! 285: return EMFILE;
! 286:
! 287: /* Get the mounted file system and node */
! 288: if ((err = task_conv(t, msg->path, path)) != 0)
! 289: return err;
! 290: if ((err = sys_opendir(path, &fp)) != 0)
! 291: return err;
! 292: t->file[fd] = fp;
! 293: msg->fd = fd;
! 294: return 0;
! 295: }
! 296:
! 297: static int
! 298: fs_closedir(struct task *t, struct msg *msg)
! 299: {
! 300: file_t fp;
! 301: int fd, err;
! 302:
! 303: fd = msg->data[0];
! 304: if (fd >= OPEN_MAX)
! 305: return EBADF;
! 306: fp = t->file[fd];
! 307: if (fp == NULL)
! 308: return EBADF;
! 309: if ((err = sys_closedir(fp)) != 0)
! 310: return err;
! 311: t->file[fd] = NULL;
! 312: return 0;
! 313: }
! 314:
! 315: static int
! 316: fs_readdir(struct task *t, struct dir_msg *msg)
! 317: {
! 318: file_t fp;
! 319:
! 320: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 321: return EBADF;
! 322: return sys_readdir(fp, &msg->dirent);
! 323: }
! 324:
! 325: static int
! 326: fs_rewinddir(struct task *t, struct msg *msg)
! 327: {
! 328: file_t fp;
! 329:
! 330: if ((fp = task_getfp(t, msg->data[0])) == NULL)
! 331: return EBADF;
! 332: return sys_rewinddir(fp);
! 333: }
! 334:
! 335: static int
! 336: fs_seekdir(struct task *t, struct msg *msg)
! 337: {
! 338: file_t fp;
! 339: long loc;
! 340:
! 341: if ((fp = task_getfp(t, msg->data[0])) == NULL)
! 342: return EBADF;
! 343: loc = msg->data[1];
! 344: return sys_seekdir(fp, loc);
! 345: }
! 346:
! 347: static int
! 348: fs_telldir(struct task *t, struct msg *msg)
! 349: {
! 350: file_t fp;
! 351: long loc;
! 352: int err;
! 353:
! 354: if ((fp = task_getfp(t, msg->data[0])) == NULL)
! 355: return EBADF;
! 356: loc = msg->data[1];
! 357: if ((err = sys_telldir(fp, &loc)) != 0)
! 358: return err;
! 359: msg->data[0] = loc;
! 360: return 0;
! 361: }
! 362:
! 363: static int
! 364: fs_mkdir(struct task *t, struct open_msg *msg)
! 365: {
! 366: char path[PATH_MAX];
! 367: int err;
! 368:
! 369: if ((t->cap & CAP_FS_WRITE) == 0)
! 370: return EACCES;
! 371: if ((err = task_conv(t, msg->path, path)) != 0)
! 372: return err;
! 373: return sys_mkdir(path, msg->mode);
! 374: }
! 375:
! 376: static int
! 377: fs_rmdir(struct task *t, struct path_msg *msg)
! 378: {
! 379: char path[PATH_MAX];
! 380: int err;
! 381:
! 382: if ((t->cap & CAP_FS_WRITE) == 0)
! 383: return EACCES;
! 384: if (msg->path == NULL)
! 385: return ENOENT;
! 386: if ((err = task_conv(t, msg->path, path)) != 0)
! 387: return err;
! 388: return sys_rmdir(path);
! 389: }
! 390:
! 391: static int
! 392: fs_rename(struct task *t, struct path_msg *msg)
! 393: {
! 394: char src[PATH_MAX];
! 395: char dest[PATH_MAX];
! 396: int err;
! 397:
! 398: if ((t->cap & CAP_FS_WRITE) == 0)
! 399: return EACCES;
! 400: if (msg->path == NULL || msg->path2 == NULL)
! 401: return ENOENT;
! 402: if ((err = task_conv(t, msg->path, src)) != 0)
! 403: return err;
! 404: if ((err = task_conv(t, msg->path2, dest)) != 0)
! 405: return err;
! 406: return sys_rename(src, dest);
! 407: }
! 408:
! 409: static int
! 410: fs_chdir(struct task *t, struct path_msg *msg)
! 411: {
! 412: char path[PATH_MAX];
! 413: file_t fp;
! 414: int err;
! 415:
! 416: if (msg->path == NULL)
! 417: return ENOENT;
! 418: if ((err = task_conv(t, msg->path, path)) != 0)
! 419: return err;
! 420: /* Check if directory exits */
! 421: if ((err = sys_opendir(path, &fp)) != 0)
! 422: return err;
! 423: if (t->cwd_fp)
! 424: sys_closedir(t->cwd_fp);
! 425: t->cwd_fp = fp;
! 426: strcpy(t->cwd, path);
! 427: return 0;
! 428: }
! 429:
! 430: static int
! 431: fs_link(struct task *t, struct msg *msg)
! 432: {
! 433: /* XXX */
! 434: return EPERM;
! 435: }
! 436:
! 437: static int
! 438: fs_unlink(struct task *t, struct path_msg *msg)
! 439: {
! 440: char path[PATH_MAX];
! 441:
! 442: if ((t->cap & CAP_FS_WRITE) == 0)
! 443: return EACCES;
! 444: if (msg->path == NULL)
! 445: return ENOENT;
! 446: task_conv(t, msg->path, path);
! 447: return sys_unlink(path);
! 448: }
! 449:
! 450: static int
! 451: fs_stat(struct task *t, struct stat_msg *msg)
! 452: {
! 453: char path[PATH_MAX];
! 454: struct stat *st;
! 455: file_t fp;
! 456: int err;
! 457:
! 458: task_conv(t, msg->path, path);
! 459: if ((err = sys_open(path, O_RDONLY, 0, &fp)) != 0)
! 460: return err;
! 461: st = &msg->st;
! 462: err = sys_fstat(fp, st);
! 463: sys_close(fp);
! 464: return err;
! 465: }
! 466:
! 467: static int
! 468: fs_getcwd(struct task *t, struct path_msg *msg)
! 469: {
! 470:
! 471: strcpy(msg->path, t->cwd);
! 472: return 0;
! 473: }
! 474:
! 475: /*
! 476: * Duplicate a file descriptor.
! 477: */
! 478: static int
! 479: fs_dup(struct task *t, struct msg *msg)
! 480: {
! 481: file_t fp;
! 482: int old_fd, new_fd;
! 483:
! 484: old_fd = msg->data[0];
! 485: if (old_fd >= OPEN_MAX)
! 486: return EBADF;
! 487: fp = t->file[old_fd];
! 488: if (fp == NULL)
! 489: return EBADF;
! 490: /* Find smallest empty slot as new fd. */
! 491: for (new_fd = 0; new_fd < OPEN_MAX; new_fd++)
! 492: if (t->file[new_fd] == NULL)
! 493: break;
! 494: if (new_fd == OPEN_MAX)
! 495: return EMFILE;
! 496: t->file[new_fd] = fp;
! 497:
! 498: /* Increment file reference */
! 499: vref(fp->f_vnode);
! 500: fp->f_count++;
! 501:
! 502: msg->data[0] = new_fd;
! 503: return 0;
! 504: }
! 505:
! 506: /*
! 507: * Duplicate a file descriptor to a particular value.
! 508: */
! 509: static int
! 510: fs_dup2(struct task *t, struct msg *msg)
! 511: {
! 512: file_t fp, org;
! 513: int old_fd, new_fd;
! 514: int err;
! 515:
! 516: old_fd = msg->data[0];
! 517: new_fd = msg->data[1];
! 518: if (old_fd >= OPEN_MAX || new_fd >= OPEN_MAX)
! 519: return EBADF;
! 520: fp = t->file[old_fd];
! 521: if (fp == NULL)
! 522: return EBADF;
! 523: org = t->file[new_fd];
! 524: if (org != NULL) {
! 525: /* Close previous file if it's opened. */
! 526: err = sys_close(org);
! 527: }
! 528: t->file[new_fd] = fp;
! 529: msg->data[0] = new_fd;
! 530: return 0;
! 531: }
! 532:
! 533: /*
! 534: * The file control system call.
! 535: */
! 536: static int
! 537: fs_fcntl(struct task *t, struct fcntl_msg *msg)
! 538: {
! 539: file_t fp;
! 540: int arg, new_fd;
! 541:
! 542: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 543: return EBADF;
! 544:
! 545: arg = msg->arg;
! 546: switch (msg->cmd) {
! 547: case F_DUPFD:
! 548: if (arg >= OPEN_MAX)
! 549: return EINVAL;
! 550: /* Find smallest empty slot as new fd. */
! 551: for (new_fd = arg; new_fd < OPEN_MAX; new_fd++)
! 552: if (t->file[new_fd] == NULL)
! 553: break;
! 554: if (new_fd == OPEN_MAX)
! 555: return EMFILE;
! 556: t->file[new_fd] = fp;
! 557: break;
! 558: case F_GETFD:
! 559: msg->arg = fp->f_flags & FD_CLOEXEC;
! 560: break;
! 561: case F_SETFD:
! 562: fp->f_flags = (fp->f_flags & ~FD_CLOEXEC) |
! 563: (msg->arg & FD_CLOEXEC);
! 564: break;
! 565: case F_GETFL:
! 566: break;
! 567: case F_SETFL:
! 568: break;
! 569: default:
! 570: break;
! 571: }
! 572: return 0;
! 573: }
! 574:
! 575: /*
! 576: * Check permission for file access
! 577: */
! 578: static int
! 579: fs_access(struct task *t, struct path_msg *msg)
! 580: {
! 581: char path[PATH_MAX];
! 582: int mode, err;
! 583:
! 584: mode = msg->data[0];
! 585:
! 586: /* Check file permission */
! 587: task_conv(t, msg->path, path);
! 588: if ((err = sys_access(path, mode)) != 0)
! 589: return err;
! 590:
! 591: /* Check task permission */
! 592: err = EACCES;
! 593: if ((mode & X_OK) && (t->cap & CAP_EXEC) == 0)
! 594: goto out;
! 595: if ((mode & W_OK) && (t->cap & CAP_FS_WRITE) == 0)
! 596: goto out;
! 597: if ((mode & R_OK) && (t->cap & CAP_FS_READ) == 0)
! 598: goto out;
! 599: err = 0;
! 600: out:
! 601: return err;
! 602: }
! 603:
! 604: /*
! 605: * Copy parent's cwd & file/directory descriptor to child's.
! 606: */
! 607: static int
! 608: fs_fork(struct task *t, struct msg *msg)
! 609: {
! 610: struct task *newtask;
! 611: file_t fp;
! 612: int err, i;
! 613:
! 614: dprintf("fs_fork\n");
! 615:
! 616: if ((err = task_alloc((task_t)msg->data[0], &newtask)) != 0)
! 617: return err;
! 618: /*
! 619: * Copy task related data
! 620: */
! 621: newtask->cwd_fp = t->cwd_fp;
! 622: strcpy(newtask->cwd, t->cwd);
! 623: for (i = 0; i < OPEN_MAX; i++) {
! 624: fp = t->file[i];
! 625: newtask->file[i] = fp;
! 626: /* Increment file reference if it's already opened. */
! 627: if (fp != NULL) {
! 628: vref(fp->f_vnode);
! 629: fp->f_count++;
! 630: }
! 631: }
! 632: if (newtask->cwd_fp)
! 633: newtask->cwd_fp->f_count++;
! 634: /* Increment cwd's reference count */
! 635: if (newtask->cwd_fp)
! 636: vref(newtask->cwd_fp->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: /* Close all files opened by task. */
! 688: for (fd = 0; fd < OPEN_MAX; fd++) {
! 689: fp = t->file[fd];
! 690: if (fp != NULL)
! 691: sys_close(fp);
! 692: }
! 693: if (t->cwd_fp)
! 694: sys_close(t->cwd_fp);
! 695: task_free(t);
! 696: return 0;
! 697: }
! 698:
! 699: /*
! 700: * fs_register() is called by boot tasks.
! 701: * This can be called even when no fs is mounted.
! 702: */
! 703: static int
! 704: fs_register(struct task *t, struct msg *msg)
! 705: {
! 706: struct task *tmp;
! 707: cap_t cap;
! 708: int err;
! 709:
! 710: dprintf("fs_register\n");
! 711:
! 712: if (task_getcap(msg->hdr.task, &cap))
! 713: return EINVAL;
! 714: if ((cap & CAP_ADMIN) == 0)
! 715: return EPERM;
! 716:
! 717: err = task_alloc(msg->hdr.task, &tmp);
! 718: return err;
! 719: }
! 720:
! 721: /*
! 722: * Return version
! 723: */
! 724: static int
! 725: fs_version(struct task *t, struct msg *msg)
! 726: {
! 727: return 0;
! 728: }
! 729:
! 730: /*
! 731: * Prepare for shutdown
! 732: */
! 733: static int
! 734: fs_shutdown(struct task *t, struct msg *msg)
! 735: {
! 736:
! 737: sys_sync();
! 738: return 0;
! 739: }
! 740:
! 741: static int
! 742: fs_debug(struct task *t, struct msg *msg)
! 743: {
! 744:
! 745: #ifdef DEBUG
! 746: printf("<File System Server>\n");
! 747: task_dump();
! 748: vnode_dump();
! 749: mount_dump();
! 750: #endif
! 751: return 0;
! 752: }
! 753:
! 754: /*
! 755: * Register to process server if it is loaded.
! 756: */
! 757: static void
! 758: process_init(void)
! 759: {
! 760: int i, err = 0;
! 761: object_t obj = 0;
! 762: struct msg m;
! 763:
! 764: /*
! 765: * Wait for server loading. timeout is 1 sec.
! 766: */
! 767: for (i = 0; i < 100; i++) {
! 768: err = object_lookup(OBJNAME_PROC, &obj);
! 769: if (err == 0)
! 770: break;
! 771:
! 772: /* Wait 10msec */
! 773: timer_sleep(10, 0);
! 774: thread_yield();
! 775: }
! 776: if (obj == 0)
! 777: return;
! 778:
! 779: /*
! 780: * Notify to process server.
! 781: */
! 782: m.hdr.code = PS_REGISTER;
! 783: msg_send(obj, &m, sizeof(m));
! 784: }
! 785:
! 786: static void
! 787: fs_init(void)
! 788: {
! 789: const struct vfssw *fs;
! 790: struct msg msg;
! 791:
! 792: process_init();
! 793:
! 794: /*
! 795: * Initialize VFS core.
! 796: */
! 797: task_init();
! 798: bio_init();
! 799: vnode_init();
! 800:
! 801: /*
! 802: * Initialize each file system.
! 803: */
! 804: for (fs = vfssw_table; fs->vs_name; fs++) {
! 805: syslog(LOG_INFO, "VFS: Initializing %s\n", fs->vs_name);
! 806: fs->vs_init();
! 807: }
! 808:
! 809: /*
! 810: * Create task data for ourselves.
! 811: */
! 812: msg.hdr.task = task_self();
! 813: fs_register(NULL, &msg);
! 814: }
! 815:
! 816: /*
! 817: * Run specified routine as a thread.
! 818: */
! 819: static int
! 820: thread_run(void (*entry)(void))
! 821: {
! 822: task_t self;
! 823: thread_t th;
! 824: void *stack;
! 825: int err;
! 826:
! 827: self = task_self();
! 828: if ((err = thread_create(self, &th)) != 0)
! 829: return err;
! 830: if ((err = vm_allocate(self, &stack, USTACK_SIZE, 1)) != 0)
! 831: return err;
! 832: if ((err = thread_load(th, entry,
! 833: (void *)((u_long)stack + USTACK_SIZE))) != 0)
! 834: return err;
! 835: if ((err = thread_setprio(th, PRIO_FS)) != 0)
! 836: return err;
! 837:
! 838: return thread_resume(th);
! 839: }
! 840:
! 841: /*
! 842: * Message mapping
! 843: */
! 844: static const struct msg_map fsmsg_map[] = {
! 845: MSGMAP( STD_VERSION, fs_version ),
! 846: MSGMAP( STD_DEBUG, fs_debug ),
! 847: MSGMAP( STD_SHUTDOWN, fs_shutdown ),
! 848: MSGMAP( FS_MOUNT, fs_mount ),
! 849: MSGMAP( FS_UMOUNT, fs_umount ),
! 850: MSGMAP( FS_SYNC, fs_sync ),
! 851: MSGMAP( FS_OPEN, fs_open ),
! 852: MSGMAP( FS_CLOSE, fs_close ),
! 853: MSGMAP( FS_MKNOD, fs_mknod ),
! 854: MSGMAP( FS_LSEEK, fs_lseek ),
! 855: MSGMAP( FS_READ, fs_read ),
! 856: MSGMAP( FS_WRITE, fs_write ),
! 857: MSGMAP( FS_IOCTL, fs_ioctl ),
! 858: MSGMAP( FS_FSYNC, fs_fsync ),
! 859: MSGMAP( FS_FSTAT, fs_fstat ),
! 860: MSGMAP( FS_OPENDIR, fs_opendir ),
! 861: MSGMAP( FS_CLOSEDIR, fs_closedir ),
! 862: MSGMAP( FS_READDIR, fs_readdir ),
! 863: MSGMAP( FS_REWINDDIR, fs_rewinddir ),
! 864: MSGMAP( FS_SEEKDIR, fs_seekdir ),
! 865: MSGMAP( FS_TELLDIR, fs_telldir ),
! 866: MSGMAP( FS_MKDIR, fs_mkdir ),
! 867: MSGMAP( FS_RMDIR, fs_rmdir ),
! 868: MSGMAP( FS_RENAME, fs_rename ),
! 869: MSGMAP( FS_CHDIR, fs_chdir ),
! 870: MSGMAP( FS_LINK, fs_link ),
! 871: MSGMAP( FS_UNLINK, fs_unlink ),
! 872: MSGMAP( FS_STAT, fs_stat ),
! 873: MSGMAP( FS_GETCWD, fs_getcwd ),
! 874: MSGMAP( FS_DUP, fs_dup ),
! 875: MSGMAP( FS_DUP2, fs_dup2 ),
! 876: MSGMAP( FS_FCNTL, fs_fcntl ),
! 877: MSGMAP( FS_ACCESS, fs_access ),
! 878: MSGMAP( FS_FORK, fs_fork ),
! 879: MSGMAP( FS_EXEC, fs_exec ),
! 880: MSGMAP( FS_EXIT, fs_exit ),
! 881: MSGMAP( FS_REGISTER, fs_register ),
! 882: MSGMAP( 0, NULL ),
! 883: };
! 884:
! 885: /*
! 886: * File system thread.
! 887: */
! 888: static void
! 889: fs_thread(void)
! 890: {
! 891: struct msg *msg;
! 892: const struct msg_map *map;
! 893: struct task *t;
! 894: int err;
! 895:
! 896: msg = (struct msg *)malloc(MAX_FSMSG);
! 897:
! 898: /*
! 899: * Message loop
! 900: */
! 901: for (;;) {
! 902: /*
! 903: * Wait for an incoming request.
! 904: */
! 905: if ((err = msg_receive(fs_obj, msg, MAX_FSMSG)) != 0)
! 906: continue;
! 907:
! 908: err = EINVAL;
! 909: map = &fsmsg_map[0];
! 910: while (map->code != 0) {
! 911: if (map->code == msg->hdr.code) {
! 912: if (map->code == FS_REGISTER) {
! 913: err = fs_register(NULL, msg);
! 914: break;
! 915: }
! 916: /* Lookup and lock task */
! 917: t = task_lookup(msg->hdr.task);
! 918: if (t == NULL)
! 919: break;
! 920:
! 921: /* Get the capability list of caller task. */
! 922: if (task_getcap(msg->hdr.task, &t->cap))
! 923: break;
! 924:
! 925: /* Dispatch request */
! 926: err = map->func(t, msg);
! 927: if (map->code != FS_EXIT)
! 928: task_unlock(t);
! 929: break;
! 930: }
! 931: map++;
! 932: }
! 933: #ifdef DEBUG_VFS
! 934: if (err)
! 935: dprintf("code=%x error=%d\n", map->code, err);
! 936: #endif
! 937: /*
! 938: * Reply to the client.
! 939: */
! 940: msg->hdr.status = err;
! 941: msg_reply(fs_obj, msg, MAX_FSMSG);
! 942: }
! 943: }
! 944:
! 945: /*
! 946: * Main routine for file system service
! 947: */
! 948: int
! 949: main(int argc, char *argv[])
! 950: {
! 951: int i;
! 952:
! 953: syslog(LOG_INFO, "Starting File System Server\n");
! 954:
! 955: /*
! 956: * Boost current priority.
! 957: */
! 958: thread_setprio(thread_self(), PRIO_FS);
! 959:
! 960: /*
! 961: * Initialize file systems.
! 962: */
! 963: fs_init();
! 964:
! 965: /*
! 966: * Create an object to expose our service.
! 967: */
! 968: if (object_create(OBJNAME_FS, &fs_obj))
! 969: sys_panic("VFS: fail to create object");
! 970:
! 971: /*
! 972: * Create new server threads.
! 973: */
! 974: syslog(LOG_INFO, "VFS: Number of fs threads: %d\n", CONFIG_FS_THREADS);
! 975:
! 976: i = CONFIG_FS_THREADS;
! 977: while (--i > 0) {
! 978: if (thread_run(fs_thread))
! 979: goto err;
! 980: }
! 981: fs_thread();
! 982: exit(0);
! 983: err:
! 984: sys_panic("VFS: failed to create thread");
! 985: return 0;
! 986: }
CVSweb