|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/usr/server/fs/vfs/main.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.
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 <sys/prex.h> 47 #include <sys/capability.h> 48 #include <sys/param.h> 49 #include <ipc/fs.h> 50 #include <ipc/proc.h> 51 #include <ipc/exec.h> 52 #include <ipc/ipc.h> 53 #include <sys/list.h> 54 #include <sys/stat.h> 55 #include <sys/vnode.h> 56 #include <sys/mount.h> 57 #include <sys/buf.h> 58 #include <sys/file.h> 59 60 #include <limits.h> 61 #include <unistd.h> 62 #include <stdio.h> 63 #include <stdlib.h> 64 #include <string.h> 65 #include <errno.h> 66 #include <fcntl.h> 67 #include <signal.h> 68 69 #include "vfs.h" 70 71 #ifdef DEBUG_VFS 72 int vfs_debug = VFSDB_FLAGS; 73 #endif 74 75 /* 76 * Message mapping 77 */ 78 struct msg_map { 79 int code; 80 int (*func)(struct task *, struct msg *); 81 }; 82 83 #define MSGMAP(code, fn) {code, (int (*)(struct task *, struct msg *))fn} 84 85 /* object for file service */ 86 static object_t fsobj; 87 88 static int 89 fs_mount(struct task *t, struct mount_msg *msg) 90 { 91 int error = 0; 92 93 /* Check client's mount capability. */ 94 if (task_chkcap(t->t_taskid, CAP_DISKADMIN) != 0) 95 error = EPERM; 96 97 if (error == 0) { 98 error = sys_mount(msg->dev, msg->dir, msg->fs, msg->flags, 99 (void *)msg->data); 100 } 101 #ifdef DEBUG 102 if (error) 103 dprintf("VFS: mount failed!\n"); 104 #endif 105 return error; 106 } 107 108 static int 109 fs_umount(struct task *t, struct path_msg *msg) 110 { 111 112 /* Check mount capability. */ 113 if (task_chkcap(t->t_taskid, CAP_DISKADMIN) != 0) 114 return EPERM; 115 116 return sys_umount(msg->path); 117 } 118 119 static int 120 fs_sync(struct task *t, struct msg *msg) 121 { 122 123 return sys_sync(); 124 } 125 126 static int 127 fs_open(struct task *t, struct open_msg *msg) 128 { 129 char path[PATH_MAX]; 130 file_t fp; 131 int fd, error; 132 int acc; 133 134 /* Find empty slot for file descriptor. */ 135 if ((fd = task_newfd(t)) == -1) 136 return EMFILE; 137 138 acc = 0; 139 switch (msg->flags & O_ACCMODE) { 140 case O_RDONLY: 141 acc = VREAD; 142 break; 143 case O_WRONLY: 144 acc = VWRITE; 145 break; 146 case O_RDWR: 147 acc = VREAD | VWRITE; 148 break; 149 } 150 if ((error = task_conv(t, msg->path, acc, path)) != 0) 151 return error; 152 153 if ((error = sys_open(path, msg->flags, msg->mode, &fp)) != 0) 154 return error; 155 156 t->t_ofile[fd] = fp; 157 t->t_nopens++; 158 msg->fd = fd; 159 return 0; 160 } 161 162 static int 163 fs_close(struct task *t, struct msg *msg) 164 { 165 file_t fp; 166 int fd, error; 167 168 fd = msg->data[0]; 169 if (fd >= OPEN_MAX) 170 return EBADF; 171 172 fp = t->t_ofile[fd]; 173 if (fp == NULL) 174 return EBADF; 175 176 if ((error = sys_close(fp)) != 0) 177 return error; 178 179 t->t_ofile[fd] = NULL; 180 t->t_nopens--; 181 return 0; 182 } 183 184 static int 185 fs_mknod(struct task *t, struct open_msg *msg) 186 { 187 char path[PATH_MAX]; 188 int error; 189 190 if ((error = task_conv(t, msg->path, VWRITE, path)) != 0) 191 return error; 192 193 return sys_mknod(path, msg->mode); 194 } 195 196 static int 197 fs_lseek(struct task *t, struct msg *msg) 198 { 199 file_t fp; 200 off_t offset, org; 201 int error, type; 202 203 if ((fp = task_getfp(t, msg->data[0])) == NULL) 204 return EBADF; 205 offset = (off_t)msg->data[1]; 206 type = msg->data[2]; 207 208 error = sys_lseek(fp, offset, type, &org); 209 msg->data[0] = (int)org; 210 return error; 211 } 212 213 static int 214 fs_read(struct task *t, struct io_msg *msg) 215 { 216 file_t fp; 217 void *buf; 218 size_t size, bytes; 219 int error; 220 221 if ((fp = task_getfp(t, msg->fd)) == NULL) 222 return EBADF; 223 size = msg->size; 224 if ((error = vm_map(msg->hdr.task, msg->buf, size, &buf)) != 0) 225 return EFAULT; 226 227 error = sys_read(fp, buf, size, &bytes); 228 msg->size = bytes; 229 vm_free(task_self(), buf); 230 return error; 231 } 232 233 static int 234 fs_write(struct task *t, struct io_msg *msg) 235 { 236 file_t fp; 237 void *buf; 238 size_t size, bytes; 239 int error; 240 241 if ((fp = task_getfp(t, msg->fd)) == NULL) 242 return EBADF; 243 size = msg->size; 244 if ((error = vm_map(msg->hdr.task, msg->buf, size, &buf)) != 0) 245 return EFAULT; 246 247 error = sys_write(fp, buf, size, &bytes); 248 msg->size = bytes; 249 vm_free(task_self(), buf); 250 return error; 251 } 252 253 static int 254 fs_ioctl(struct task *t, struct ioctl_msg *msg) 255 { 256 file_t fp; 257 258 if ((fp = task_getfp(t, msg->fd)) == NULL) 259 return EBADF; 260 261 return sys_ioctl(fp, msg->request, msg->buf); 262 } 263 264 static int 265 fs_fsync(struct task *t, struct msg *msg) 266 { 267 file_t fp; 268 269 if ((fp = task_getfp(t, msg->data[0])) == NULL) 270 return EBADF; 271 272 return sys_fsync(fp); 273 } 274 275 static int 276 fs_fstat(struct task *t, struct stat_msg *msg) 277 { 278 file_t fp; 279 struct stat *st; 280 int error; 281 282 if ((fp = task_getfp(t, msg->fd)) == NULL) 283 return EBADF; 284 285 st = &msg->st; 286 error = sys_fstat(fp, st); 287 return error; 288 } 289 290 static int 291 fs_opendir(struct task *t, struct open_msg *msg) 292 { 293 char path[PATH_MAX]; 294 file_t fp; 295 int fd, error; 296 297 /* Find empty slot for file descriptor. */ 298 if ((fd = task_newfd(t)) == -1) 299 return EMFILE; 300 301 /* Get the mounted file system and node */ 302 if ((error = task_conv(t, msg->path, VREAD, path)) != 0) 303 return error; 304 305 if ((error = sys_opendir(path, &fp)) != 0) 306 return error; 307 t->t_ofile[fd] = fp; 308 msg->fd = fd; 309 return 0; 310 } 311 312 static int 313 fs_closedir(struct task *t, struct msg *msg) 314 { 315 file_t fp; 316 int fd, error; 317 318 fd = msg->data[0]; 319 if (fd >= OPEN_MAX) 320 return EBADF; 321 fp = t->t_ofile[fd]; 322 if (fp == NULL) 323 return EBADF; 324 325 if ((error = sys_closedir(fp)) != 0) 326 return error; 327 t->t_ofile[fd] = NULL; 328 return 0; 329 } 330 331 static int 332 fs_readdir(struct task *t, struct dir_msg *msg) 333 { 334 file_t fp; 335 336 if ((fp = task_getfp(t, msg->fd)) == NULL) 337 return EBADF; 338 339 return sys_readdir(fp, &msg->dirent); 340 } 341 342 static int 343 fs_rewinddir(struct task *t, struct msg *msg) 344 { 345 file_t fp; 346 347 if ((fp = task_getfp(t, msg->data[0])) == NULL) 348 return EBADF; 349 350 return sys_rewinddir(fp); 351 } 352 353 static int 354 fs_seekdir(struct task *t, struct msg *msg) 355 { 356 file_t fp; 357 long loc; 358 359 if ((fp = task_getfp(t, msg->data[0])) == NULL) 360 return EBADF; 361 loc = msg->data[1]; 362 363 return sys_seekdir(fp, loc); 364 } 365 366 static int 367 fs_telldir(struct task *t, struct msg *msg) 368 { 369 file_t fp; 370 long loc; 371 int error; 372 373 if ((fp = task_getfp(t, msg->data[0])) == NULL) 374 return EBADF; 375 loc = msg->data[1]; 376 377 if ((error = sys_telldir(fp, &loc)) != 0) 378 return error; 379 msg->data[0] = loc; 380 return 0; 381 } 382 383 static int 384 fs_mkdir(struct task *t, struct open_msg *msg) 385 { 386 char path[PATH_MAX]; 387 int error; 388 389 if ((error = task_conv(t, msg->path, VWRITE, path)) != 0) 390 return error; 391 392 return sys_mkdir(path, msg->mode); 393 } 394 395 static int 396 fs_rmdir(struct task *t, struct path_msg *msg) 397 { 398 char path[PATH_MAX]; 399 int error; 400 401 if (msg->path == NULL) 402 return ENOENT; 403 if ((error = task_conv(t, msg->path, VWRITE, path)) != 0) 404 return error; 405 406 return sys_rmdir(path); 407 } 408 409 static int 410 fs_rename(struct task *t, struct path_msg *msg) 411 { 412 char src[PATH_MAX]; 413 char dest[PATH_MAX]; 414 int error; 415 416 if (msg->path == NULL || msg->path2 == NULL) 417 return ENOENT; 418 419 if ((error = task_conv(t, msg->path, VREAD, src)) != 0) 420 return error; 421 422 if ((error = task_conv(t, msg->path2, VWRITE, dest)) != 0) 423 return error; 424 425 return sys_rename(src, dest); 426 } 427 428 static int 429 fs_chdir(struct task *t, struct path_msg *msg) 430 { 431 char path[PATH_MAX]; 432 file_t fp; 433 int error; 434 435 if (msg->path == NULL) 436 return ENOENT; 437 if ((error = task_conv(t, msg->path, VREAD, path)) != 0) 438 return error; 439 440 /* Check if directory exits */ 441 if ((error = sys_opendir(path, &fp)) != 0) 442 return error; 443 if (t->t_cwdfp) 444 sys_closedir(t->t_cwdfp); 445 t->t_cwdfp = fp; 446 strlcpy(t->t_cwd, path, sizeof(t->t_cwd)); 447 return 0; 448 } 449 450 static int 451 fs_fchdir(struct task *t, struct msg *msg) 452 { 453 file_t fp; 454 int fd; 455 456 fd = msg->data[0]; 457 if ((fp = task_getfp(t, fd)) == NULL) 458 return EBADF; 459 460 if (t->t_cwdfp) 461 sys_closedir(t->t_cwdfp); 462 t->t_cwdfp = fp; 463 return sys_fchdir(fp, t->t_cwd); 464 } 465 466 static int 467 fs_link(struct task *t, struct msg *msg) 468 { 469 /* XXX */ 470 return EPERM; 471 } 472 473 static int 474 fs_unlink(struct task *t, struct path_msg *msg) 475 { 476 char path[PATH_MAX]; 477 int error; 478 479 if (msg->path == NULL) 480 return ENOENT; 481 if ((error = task_conv(t, msg->path, VWRITE, path)) != 0) 482 return error; 483 484 return sys_unlink(path); 485 } 486 487 static int 488 fs_stat(struct task *t, struct stat_msg *msg) 489 { 490 char path[PATH_MAX]; 491 struct stat *st; 492 int error; 493 494 error = task_conv(t, msg->path, 0, path); 495 if (error == 0) { 496 st = &msg->st; 497 error = sys_stat(path, st); 498 } 499 return error; 500 } 501 502 static int 503 fs_getcwd(struct task *t, struct path_msg *msg) 504 { 505 506 strlcpy(msg->path, t->t_cwd, sizeof(msg->path)); 507 return 0; 508 } 509 510 /* 511 * Duplicate a file descriptor 512 */ 513 static int 514 fs_dup(struct task *t, struct msg *msg) 515 { 516 file_t fp; 517 int old_fd, new_fd; 518 519 old_fd = msg->data[0]; 520 if ((fp = task_getfp(t, old_fd)) == NULL) 521 return EBADF; 522 523 /* Find smallest empty slot as new fd. */ 524 if ((new_fd = task_newfd(t)) == -1) 525 return EMFILE; 526 527 t->t_ofile[new_fd] = fp; 528 529 /* Increment file reference */ 530 vref(fp->f_vnode); 531 fp->f_count++; 532 533 msg->data[0] = new_fd; 534 return 0; 535 } 536 537 /* 538 * Duplicate a file descriptor to a particular value. 539 */ 540 static int 541 fs_dup2(struct task *t, struct msg *msg) 542 { 543 file_t fp, org; 544 int old_fd, new_fd; 545 int error; 546 547 old_fd = msg->data[0]; 548 new_fd = msg->data[1]; 549 if (old_fd >= OPEN_MAX || new_fd >= OPEN_MAX) 550 return EBADF; 551 fp = t->t_ofile[old_fd]; 552 if (fp == NULL) 553 return EBADF; 554 org = t->t_ofile[new_fd]; 555 if (org != NULL) { 556 /* Close previous file if it's opened. */ 557 error = sys_close(org); 558 } 559 t->t_ofile[new_fd] = fp; 560 561 /* Increment file reference */ 562 vref(fp->f_vnode); 563 fp->f_count++; 564 565 msg->data[0] = new_fd; 566 return 0; 567 } 568 569 /* 570 * The file control system call. 571 */ 572 static int 573 fs_fcntl(struct task *t, struct fcntl_msg *msg) 574 { 575 file_t fp; 576 int arg, new_fd; 577 578 if ((fp = task_getfp(t, msg->fd)) == NULL) 579 return EBADF; 580 581 arg = msg->arg; 582 switch (msg->cmd) { 583 case F_DUPFD: 584 if (arg >= OPEN_MAX) 585 return EINVAL; 586 /* Find smallest empty slot as new fd. */ 587 if ((new_fd = task_newfd(t)) == -1) 588 return EMFILE; 589 t->t_ofile[new_fd] = fp; 590 591 /* Increment file reference */ 592 vref(fp->f_vnode); 593 fp->f_count++; 594 msg->arg = new_fd; 595 break; 596 case F_GETFD: 597 msg->arg = fp->f_flags & FD_CLOEXEC; 598 break; 599 case F_SETFD: 600 fp->f_flags = (fp->f_flags & ~FD_CLOEXEC) | 601 (msg->arg & FD_CLOEXEC); 602 msg->arg = 0; 603 break; 604 case F_GETFL: 605 case F_SETFL: 606 msg->arg = -1; 607 break; 608 default: 609 msg->arg = -1; 610 break; 611 } 612 return 0; 613 } 614 615 /* 616 * Check permission for file access 617 */ 618 static int 619 fs_access(struct task *t, struct path_msg *msg) 620 { 621 char path[PATH_MAX]; 622 int acc, mode, error = 0; 623 624 mode = msg->data[0]; 625 acc = 0; 626 if (mode & R_OK) 627 acc |= VREAD; 628 if (mode & W_OK) 629 acc |= VWRITE; 630 631 if ((error = task_conv(t, msg->path, acc, path)) != 0) 632 return error; 633 634 return sys_access(path, mode); 635 } 636 637 /* 638 * Copy parent's cwd & file/directory descriptor to child's. 639 */ 640 static int 641 fs_fork(struct task *t, struct msg *msg) 642 { 643 struct task *newtask; 644 file_t fp; 645 int error, i; 646 647 DPRINTF(VFSDB_CORE, ("fs_fork\n")); 648 649 if ((error = task_alloc((task_t)msg->data[0], &newtask)) != 0) 650 return error; 651 652 /* 653 * Copy task related data 654 */ 655 newtask->t_cwdfp = t->t_cwdfp; 656 strlcpy(newtask->t_cwd, t->t_cwd, sizeof(newtask->t_cwd)); 657 for (i = 0; i < OPEN_MAX; i++) { 658 fp = t->t_ofile[i]; 659 newtask->t_ofile[i] = fp; 660 /* 661 * Increment file reference if it's 662 * already opened. 663 */ 664 if (fp != NULL) { 665 vref(fp->f_vnode); 666 fp->f_count++; 667 } 668 } 669 if (newtask->t_cwdfp) 670 newtask->t_cwdfp->f_count++; 671 /* Increment cwd's reference count */ 672 if (newtask->t_cwdfp) 673 vref(newtask->t_cwdfp->f_vnode); 674 675 DPRINTF(VFSDB_CORE, ("fs_fork-complete\n")); 676 return 0; 677 } 678 679 /* 680 * fs_exec() is called for POSIX exec(). 681 * It closes all directory stream. 682 * File descriptor which is marked close-on-exec are also closed. 683 */ 684 static int 685 fs_exec(struct task *t, struct msg *msg) 686 { 687 task_t old_id, new_id; 688 struct task *target; 689 file_t fp; 690 int fd; 691 692 old_id = (task_t)msg->data[0]; 693 new_id = (task_t)msg->data[1]; 694 695 if (!(target = task_lookup(old_id))) 696 return EINVAL; 697 698 /* Update task id in the task. */ 699 task_setid(target, new_id); 700 701 /* Close all directory descriptor */ 702 for (fd = 0; fd < OPEN_MAX; fd++) { 703 fp = target->t_ofile[fd]; 704 if (fp) { 705 if (fp->f_vnode->v_type == VDIR) { 706 sys_close(fp); 707 target->t_ofile[fd] = NULL; 708 } 709 710 /* XXX: need to check close-on-exec flag */ 711 } 712 } 713 task_unlock(target); 714 return 0; 715 } 716 717 /* 718 * fs_exit() cleans up data for task's termination. 719 */ 720 static int 721 fs_exit(struct task *t, struct msg *msg) 722 { 723 file_t fp; 724 int fd; 725 726 DPRINTF(VFSDB_CORE, ("fs_exit\n")); 727 728 /* 729 * Close all files opened by task. 730 */ 731 for (fd = 0; fd < OPEN_MAX; fd++) { 732 fp = t->t_ofile[fd]; 733 if (fp != NULL) 734 sys_close(fp); 735 } 736 if (t->t_cwdfp) 737 sys_close(t->t_cwdfp); 738 task_free(t); 739 return 0; 740 } 741 742 /* 743 * fs_register() is called by boot tasks. 744 * This can be called even when no fs is mounted. 745 */ 746 static int 747 fs_register(struct task *t, struct msg *msg) 748 { 749 struct task *tmp; 750 int error; 751 752 DPRINTF(VFSDB_CORE, ("fs_register\n")); 753 754 error = task_alloc(msg->hdr.task, &tmp); 755 return error; 756 } 757 758 static int 759 fs_pipe(struct task *t, struct msg *msg) 760 { 761 #ifdef CONFIG_FIFOFS 762 char path[PATH_MAX]; 763 file_t rfp, wfp; 764 int error, rfd, wfd; 765 766 DPRINTF(VFSDB_CORE, ("fs_pipe\n")); 767 768 if ((rfd = task_newfd(t)) == -1) 769 return EMFILE; 770 t->t_ofile[rfd] = (file_t)1; /* temp */ 771 772 if ((wfd = task_newfd(t)) == -1) { 773 t->t_ofile[rfd] = NULL; 774 return EMFILE; 775 } 776 sprintf(path, "/mnt/fifo/pipe-%x-%d", (u_int)t->t_taskid, rfd); 777 778 if ((error = sys_mknod(path, S_IFIFO)) != 0) 779 goto out; 780 if ((error = sys_open(path, O_RDONLY | O_NONBLOCK, 0, &rfp)) != 0) { 781 goto out; 782 } 783 if ((error = sys_open(path, O_WRONLY | O_NONBLOCK, 0, &wfp)) != 0) { 784 goto out; 785 } 786 t->t_ofile[rfd] = rfp; 787 t->t_ofile[wfd] = wfp; 788 t->t_nopens += 2; 789 msg->data[0] = rfd; 790 msg->data[1] = wfd; 791 return 0; 792 out: 793 t->t_ofile[rfd] = NULL; 794 t->t_ofile[wfd] = NULL; 795 return error; 796 #else 797 return ENOSYS; 798 #endif 799 } 800 801 /* 802 * Return if specified file is a tty 803 */ 804 static int 805 fs_isatty(struct task *t, struct msg *msg) 806 { 807 file_t fp; 808 int istty = 0; 809 810 if ((fp = task_getfp(t, msg->data[0])) == NULL) 811 return EBADF; 812 813 if (fp->f_vnode->v_flags & VISTTY) 814 istty = 1; 815 msg->data[0] = istty; 816 return 0; 817 } 818 819 static int 820 fs_truncate(struct task *t, struct path_msg *msg) 821 { 822 char path[PATH_MAX]; 823 int error; 824 825 if (msg->path == NULL) 826 return ENOENT; 827 if ((error = task_conv(t, msg->path, VWRITE, path)) != 0) 828 return error; 829 830 return sys_truncate(path, msg->data[0]); 831 } 832 833 static int 834 fs_ftruncate(struct task *t, struct msg *msg) 835 { 836 file_t fp; 837 838 if ((fp = task_getfp(t, msg->data[0])) == NULL) 839 return EBADF; 840 841 return sys_ftruncate(fp, msg->data[1]); 842 } 843 844 /* 845 * Prepare for boot 846 */ 847 static int 848 fs_boot(struct task *t, struct msg *msg) 849 { 850 object_t execobj, procobj; 851 struct bind_msg bm; 852 struct msg m; 853 854 /* Check client's capability. */ 855 if (task_chkcap(msg->hdr.task, CAP_PROTSERV) != 0) 856 return EPERM; 857 858 /* 859 * Request exec server to bind an appropriate 860 * capability for us. 861 */ 862 if (object_lookup("!exec", &execobj) != 0) 863 sys_panic("fs: no exec found"); 864 bm.hdr.code = EXEC_BINDCAP; 865 strlcpy(bm.path, "/boot/fs", sizeof(bm.path)); 866 msg_send(execobj, &bm, sizeof(bm)); 867 868 /* 869 * Notify to process server. 870 */ 871 if (object_lookup("!proc", &procobj) != 0) 872 sys_panic("fs: no proc found"); 873 m.hdr.code = PS_REGISTER; 874 msg_send(procobj, &m, sizeof(m)); 875 876 return 0; 877 } 878 879 /* 880 * Prepare for shutdown 881 */ 882 static int 883 fs_shutdown(struct task *t, struct msg *msg) 884 { 885 886 DPRINTF(VFSDB_CORE, ("fs_shutdown\n")); 887 return 0; 888 } 889 890 int 891 fs_noop(void) 892 { 893 return 0; 894 } 895 896 #ifdef DEBUG_VFS 897 /* 898 * Dump internal data. 899 */ 900 static int 901 fs_debug(struct task *t, struct msg *msg) 902 { 903 904 dprintf("<File System Server>\n"); 905 task_dump(); 906 vnode_dump(); 907 mount_dump(); 908 return 0; 909 } 910 #endif 911 912 static void 913 vfs_init(void) 914 { 915 const struct vfssw *fs; 916 struct msg msg; 917 918 /* 919 * Initialize VFS core. 920 */ 921 task_init(); 922 bio_init(); 923 vnode_init(); 924 925 /* 926 * Initialize each file system. 927 */ 928 for (fs = vfssw; fs->vs_name; fs++) { 929 DPRINTF(VFSDB_CORE, ("VFS: initializing %s\n", 930 fs->vs_name)); 931 fs->vs_init(); 932 } 933 934 /* 935 * Create task data for ourselves. 936 */ 937 msg.hdr.task = task_self(); 938 fs_register(NULL, &msg); 939 } 940 941 /* 942 * Run specified routine as a thread. 943 */ 944 static int 945 run_thread(void (*entry)(void)) 946 { 947 task_t self; 948 thread_t t; 949 void *stack, *sp; 950 int error; 951 952 self = task_self(); 953 if ((error = thread_create(self, &t)) != 0) 954 return error; 955 if ((error = vm_allocate(self, &stack, DFLSTKSZ, 1)) != 0) 956 return error; 957 958 sp = (void *)((u_long)stack + DFLSTKSZ - sizeof(u_long) * 3); 959 if ((error = thread_load(t, entry, sp)) != 0) 960 return error; 961 962 return thread_resume(t); 963 } 964 965 static void 966 exception_handler(int sig) 967 { 968 969 exception_return(); 970 } 971 972 /* 973 * Message mapping 974 */ 975 static const struct msg_map fsmsg_map[] = { 976 MSGMAP( FS_MOUNT, fs_mount ), 977 MSGMAP( FS_UMOUNT, fs_umount ), 978 MSGMAP( FS_SYNC, fs_sync ), 979 MSGMAP( FS_OPEN, fs_open ), 980 MSGMAP( FS_CLOSE, fs_close ), 981 MSGMAP( FS_MKNOD, fs_mknod ), 982 MSGMAP( FS_LSEEK, fs_lseek ), 983 MSGMAP( FS_READ, fs_read ), 984 MSGMAP( FS_WRITE, fs_write ), 985 MSGMAP( FS_IOCTL, fs_ioctl ), 986 MSGMAP( FS_FSYNC, fs_fsync ), 987 MSGMAP( FS_FSTAT, fs_fstat ), 988 MSGMAP( FS_OPENDIR, fs_opendir ), 989 MSGMAP( FS_CLOSEDIR, fs_closedir ), 990 MSGMAP( FS_READDIR, fs_readdir ), 991 MSGMAP( FS_REWINDDIR, fs_rewinddir ), 992 MSGMAP( FS_SEEKDIR, fs_seekdir ), 993 MSGMAP( FS_TELLDIR, fs_telldir ), 994 MSGMAP( FS_MKDIR, fs_mkdir ), 995 MSGMAP( FS_RMDIR, fs_rmdir ), 996 MSGMAP( FS_RENAME, fs_rename ), 997 MSGMAP( FS_CHDIR, fs_chdir ), 998 MSGMAP( FS_LINK, fs_link ), 999 MSGMAP( FS_UNLINK, fs_unlink ), 1000 MSGMAP( FS_STAT, fs_stat ), 1001 MSGMAP( FS_GETCWD, fs_getcwd ), 1002 MSGMAP( FS_DUP, fs_dup ), 1003 MSGMAP( FS_DUP2, fs_dup2 ), 1004 MSGMAP( FS_FCNTL, fs_fcntl ), 1005 MSGMAP( FS_ACCESS, fs_access ), 1006 MSGMAP( FS_FORK, fs_fork ), 1007 MSGMAP( FS_EXEC, fs_exec ), 1008 MSGMAP( FS_EXIT, fs_exit ), 1009 MSGMAP( FS_REGISTER, fs_register ), 1010 MSGMAP( FS_PIPE, fs_pipe ), 1011 MSGMAP( FS_ISATTY, fs_isatty ), 1012 MSGMAP( FS_TRUNCATE, fs_truncate ), 1013 MSGMAP( FS_FTRUNCATE, fs_ftruncate ), 1014 MSGMAP( FS_FCHDIR, fs_fchdir ), 1015 MSGMAP( STD_BOOT, fs_boot ), 1016 MSGMAP( STD_SHUTDOWN, fs_shutdown ), 1017 #ifdef DEBUG_VFS 1018 MSGMAP( STD_DEBUG, fs_debug ), 1019 #endif 1020 MSGMAP( 0, NULL ), 1021 }; 1022 1023 /* 1024 * File system thread. 1025 */ 1026 static void 1027 fs_thread(void) 1028 { 1029 struct msg *msg; 1030 const struct msg_map *map; 1031 struct task *t; 1032 int error; 1033 1034 msg = malloc(MAX_FSMSG); 1035 1036 /* 1037 * Message loop 1038 */ 1039 for (;;) { 1040 /* 1041 * Wait for an incoming request. 1042 */ 1043 if ((error = msg_receive(fsobj, msg, MAX_FSMSG)) != 0) 1044 continue; 1045 1046 error = EINVAL; 1047 map = &fsmsg_map[0]; 1048 while (map->code != 0) { 1049 if (map->code == msg->hdr.code) { 1050 /* 1051 * Handle messages by non-registerd tasks 1052 */ 1053 if (map->code == STD_BOOT) { 1054 error = fs_boot(NULL, msg); 1055 break; 1056 } 1057 if (map->code == FS_REGISTER) { 1058 error = fs_register(NULL, msg); 1059 break; 1060 } 1061 1062 /* Lookup and lock task */ 1063 t = task_lookup(msg->hdr.task); 1064 if (t == NULL) 1065 break; 1066 1067 /* Dispatch request */ 1068 error = (*map->func)(t, msg); 1069 if (map->code != FS_EXIT) 1070 task_unlock(t); 1071 break; 1072 } 1073 map++; 1074 } 1075 #ifdef DEBUG_VFS 1076 if (error) 1077 dprintf("VFS: task=%x code=%x error=%d\n", 1078 msg->hdr.task, map->code, error); 1079 #endif 1080 /* 1081 * Reply to the client. 1082 */ 1083 msg->hdr.status = error; 1084 msg_reply(fsobj, msg, MAX_FSMSG); 1085 } 1086 } 1087 1088 /* 1089 * Main routine for file system service 1090 */ 1091 int 1092 main(int argc, char *argv[]) 1093 { 1094 int i; 1095 1096 sys_log("Starting file system server\n"); 1097 1098 DPRINTF(VFSDB_CORE, ("VFS: number of fs threads: %d\n", 1099 CONFIG_FS_THREADS)); 1100 1101 /* Set thread priority. */ 1102 thread_setpri(thread_self(), PRI_FS); 1103 1104 /* Setup exception handler */ 1105 exception_setup(exception_handler); 1106 1107 /* Initialize the file systems. */ 1108 vfs_init(); 1109 1110 /* Create an object to expose our service. */ 1111 if (object_create("!fs", &fsobj)) 1112 sys_panic("VFS: fail to create object"); 1113 1114 /* 1115 * Create new server threads. 1116 */ 1117 i = CONFIG_FS_THREADS; 1118 while (--i > 0) { 1119 if (run_thread(fs_thread)) 1120 goto err; 1121 } 1122 fs_thread(); 1123 1124 sys_panic("VFS: exit!"); 1125 exit(0); 1126 err: 1127 sys_panic("VFS: failed to create thread"); 1128 return 0; 1129 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |