Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/server/fs/vfs/main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fs_mount
  2. fs_umount
  3. fs_sync
  4. fs_open
  5. fs_close
  6. fs_mknod
  7. fs_lseek
  8. fs_read
  9. fs_write
  10. fs_ioctl
  11. fs_fsync
  12. fs_fstat
  13. fs_opendir
  14. fs_closedir
  15. fs_readdir
  16. fs_rewinddir
  17. fs_seekdir
  18. fs_telldir
  19. fs_mkdir
  20. fs_rmdir
  21. fs_rename
  22. fs_chdir
  23. fs_fchdir
  24. fs_link
  25. fs_unlink
  26. fs_stat
  27. fs_getcwd
  28. fs_dup
  29. fs_dup2
  30. fs_fcntl
  31. fs_access
  32. fs_fork
  33. fs_exec
  34. fs_exit
  35. fs_register
  36. fs_pipe
  37. fs_isatty
  38. fs_truncate
  39. fs_ftruncate
  40. fs_boot
  41. fs_shutdown
  42. fs_noop
  43. fs_debug
  44. vfs_init
  45. run_thread
  46. exception_handler
  47. fs_thread
  48. main

   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] */