1 /* This file performs the MOUNT and UMOUNT system calls. 2 * 3 * The entry points into this file are 4 * do_mount: perform the MOUNT system call 5 * do_umount: perform the UMOUNT system call 6 * unmount: unmount a file system 7 */ 8 9 #include "fs.h" 10 #include <fcntl.h> 11 #include <string.h> 12 #include <minix/callnr.h> 13 #include <minix/com.h> 14 #include <minix/const.h> 15 #include <minix/endpoint.h> 16 #include <minix/syslib.h> 17 #include <minix/bitmap.h> 18 #include <minix/ds.h> 19 #include <unistd.h> 20 #include <sys/stat.h> 21 #include <sys/mount.h> 22 #include <sys/dirent.h> 23 #include <assert.h> 24 #include "file.h" 25 #include <minix/vfsif.h> 26 #include "vnode.h" 27 #include "vmnt.h" 28 #include "path.h" 29 30 /* Allow the root to be replaced before the first 'real' mount. */ 31 static int have_root = 0; 32 33 /* Bitmap of in-use "none" pseudo devices. */ 34 static bitchunk_t nonedev[BITMAP_CHUNKS(NR_NONEDEVS)] = { 0 }; 35 36 #define alloc_nonedev(dev) SET_BIT(nonedev, minor(dev) - 1) 37 #define free_nonedev(dev) UNSET_BIT(nonedev, minor(dev) - 1) 38 39 static dev_t name_to_dev(int allow_mountpt, char path[PATH_MAX]); 40 static dev_t find_free_nonedev(void); 41 static void update_bspec(dev_t dev, endpoint_t fs_e, int send_drv_e); 42 43 /*===========================================================================* 44 * update_bspec * 45 *===========================================================================*/ 46 static void update_bspec(dev_t dev, endpoint_t fs_e, int send_drv_e) 47 { 48 /* Update all block special files for a certain device, to use a new FS endpt 49 * to route raw block I/O requests through. 50 */ 51 struct vnode *vp; 52 struct dmap *dp; 53 int r, major; 54 55 for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) 56 if (vp->v_ref_count > 0 && S_ISBLK(vp->v_mode) && vp->v_sdev == dev) { 57 vp->v_bfs_e = fs_e; 58 if (send_drv_e) { 59 major = major(dev); 60 if (major < 0 || major >= NR_DEVICES) { 61 /* Can't update for out-of-range major */ 62 continue; 63 } 64 dp = &dmap[major(dev)]; 65 if (dp->dmap_driver == NONE) { 66 /* Can't update for vanished driver */ 67 printf("VFS: can't send new driver label\n"); 68 continue; 69 } 70 71 if ((r = req_newdriver(fs_e, vp->v_sdev, 72 dp->dmap_label)) != OK) { 73 printf("VFS: Failed to send new driver label" 74 " for moved block special file to %d\n", 75 fs_e); 76 } 77 } 78 } 79 } 80 81 /*===========================================================================* 82 * do_mount * 83 *===========================================================================*/ 84 int do_mount(void) 85 { 86 /* Perform the mount(name, mfile, mount_flags) system call. */ 87 endpoint_t fs_e; 88 int r, slot, nodev; 89 char mount_path[PATH_MAX], mount_dev[PATH_MAX]; 90 char mount_label[LABEL_MAX], mount_type[FSTYPE_MAX]; 91 dev_t dev; 92 int mflags; 93 vir_bytes label, type, vname1, vname2; 94 size_t vname1_length, vname2_length, label_len, type_len; 95 96 mflags = job_m_in.m_lc_vfs_mount.flags; 97 label = job_m_in.m_lc_vfs_mount.label; 98 label_len = job_m_in.m_lc_vfs_mount.labellen; 99 vname1 = job_m_in.m_lc_vfs_mount.dev; 100 vname1_length = job_m_in.m_lc_vfs_mount.devlen; 101 vname2 = job_m_in.m_lc_vfs_mount.path; 102 vname2_length = job_m_in.m_lc_vfs_mount.pathlen; 103 type = job_m_in.m_lc_vfs_mount.type; 104 type_len = job_m_in.m_lc_vfs_mount.typelen; 105 106 /* Only the super-user may do MOUNT. */ 107 if (!super_user) return(EPERM); 108 109 /* Get the label from the caller, and ask DS for the endpoint of the FS. */ 110 if (label_len > sizeof(mount_label)) 111 return EINVAL; 112 r = sys_datacopy_wrapper(who_e, label, SELF, (vir_bytes) mount_label, 113 sizeof(mount_label)); 114 if (r != OK) return(r); 115 116 mount_label[sizeof(mount_label)-1] = 0; 117 118 r = ds_retrieve_label_endpt(mount_label, &fs_e); 119 if (r != OK) return(r); 120 121 /* Sanity check on process number. */ 122 if (isokendpt(fs_e, &slot) != OK) return(EINVAL); 123 124 /* A null string for block special device means don't use a device at all. */ 125 nodev = (vname1_length == 0); 126 if (!nodev) { 127 /* If 'name' is not for a block special file, return error. */ 128 if (fetch_name(vname1, vname1_length, mount_dev) != OK) 129 return(err_code); 130 if ((dev = name_to_dev(FALSE /*allow_mountpt*/, mount_dev)) == NO_DEV) 131 return(err_code); 132 } else { 133 /* Find a free pseudo-device as substitute for an actual device. */ 134 if ((dev = find_free_nonedev()) == NO_DEV) 135 return(err_code); 136 strlcpy(mount_dev, "none", sizeof(mount_dev)); 137 } 138 139 /* Fetch the name of the mountpoint */ 140 if (fetch_name(vname2, vname2_length, mount_path) != OK) return(err_code); 141 142 /* Fetch the type of the file system. */ 143 if (type_len > sizeof(mount_type)) return(ENAMETOOLONG); 144 if (fetch_name(type, type_len, mount_type) != OK) return(err_code); 145 146 /* Do the actual job */ 147 return mount_fs(dev, mount_dev, mount_path, fs_e, mflags, mount_type, 148 mount_label); 149 } 150 151 152 /*===========================================================================* 153 * mount_fs * 154 *===========================================================================*/ 155 int mount_fs( 156 dev_t dev, 157 char mount_dev[PATH_MAX], 158 char mount_path[PATH_MAX], 159 endpoint_t fs_e, 160 int flags, 161 char mount_type[FSTYPE_MAX], 162 char mount_label[LABEL_MAX] ) 163 { 164 int i, r = OK, found, isroot, mount_root, slot; 165 struct fproc *tfp, *rfp; 166 struct dmap *dp; 167 struct vnode *root_node, *vp = NULL; 168 struct vmnt *new_vmp, *parent_vmp; 169 char *label; 170 struct node_details res; 171 struct lookup resolve; 172 struct statvfs statvfs_buf; 173 unsigned int fs_flags; 174 175 /* Look up block device driver label when dev is not a pseudo-device */ 176 label = ""; 177 if (!is_nonedev(dev)) { 178 /* Get driver process' endpoint */ 179 dp = &dmap[major(dev)]; 180 if (dp->dmap_driver == NONE) { 181 printf("VFS: no driver for dev %llx\n", dev); 182 return(EINVAL); 183 } 184 185 label = dp->dmap_label; 186 assert(strlen(label) > 0); 187 } 188 189 /* Scan vmnt table to see if dev already mounted. If not, find a free slot.*/ 190 found = FALSE; 191 for (i = 0; i < NR_MNTS; ++i) { 192 if (vmnt[i].m_dev == dev) found = TRUE; 193 } 194 if (found) { 195 return(EBUSY); 196 } else if ((new_vmp = get_free_vmnt()) == NULL) { 197 return(ENOMEM); 198 } 199 if ((r = lock_vmnt(new_vmp, VMNT_EXCL)) != OK) return(r); 200 201 strlcpy(new_vmp->m_mount_path, mount_path, PATH_MAX); 202 strlcpy(new_vmp->m_mount_dev, mount_dev, PATH_MAX); 203 strlcpy(new_vmp->m_fstype, mount_type, sizeof(new_vmp->m_fstype)); 204 isroot = (strcmp(mount_path, "/") == 0); 205 mount_root = (isroot && have_root < 2); /* Root can be mounted twice: 206 * 1: ramdisk 207 * 2: boot disk (e.g., harddisk) 208 */ 209 210 if (!mount_root) { 211 /* Get vnode of mountpoint */ 212 lookup_init(&resolve, mount_path, PATH_NOFLAGS, &parent_vmp, &vp); 213 resolve.l_vmnt_lock = VMNT_EXCL; 214 resolve.l_vnode_lock = VNODE_WRITE; 215 if ((vp = eat_path(&resolve, fp)) == NULL) 216 r = err_code; 217 else if (vp->v_ref_count == 1) { 218 /*Tell FS on which vnode it is mounted (glue into mount tree)*/ 219 r = req_mountpoint(vp->v_fs_e, vp->v_inode_nr); 220 } else 221 r = EBUSY; 222 223 if (vp != NULL) { 224 /* Quickly unlock to allow back calls (from e.g. FUSE) to 225 * relock */ 226 unlock_vmnt(parent_vmp); 227 } 228 229 if (r != OK) { 230 if (vp != NULL) { 231 unlock_vnode(vp); 232 put_vnode(vp); 233 } 234 unlock_vmnt(new_vmp); 235 return(r); 236 } 237 } 238 239 /* We'll need a vnode for the root inode */ 240 if ((root_node = get_free_vnode()) == NULL) { 241 if (vp != NULL) { 242 unlock_vnode(vp); 243 put_vnode(vp); 244 } 245 unlock_vmnt(new_vmp); 246 return(err_code); 247 } 248 lock_vnode(root_node, VNODE_OPCL); 249 250 /* Record process as a system process */ 251 if (isokendpt(fs_e, &slot) != OK) { 252 if (vp != NULL) { 253 unlock_vnode(vp); 254 put_vnode(vp); 255 } 256 unlock_vnode(root_node); 257 unlock_vmnt(new_vmp); 258 return(EINVAL); 259 } 260 rfp = &fproc[slot]; 261 rfp->fp_flags |= FP_SRV_PROC; /* File Servers are also services */ 262 263 /* Store some essential vmnt data first */ 264 new_vmp->m_fs_e = fs_e; 265 new_vmp->m_dev = dev; 266 if (flags & MNT_RDONLY) new_vmp->m_flags |= VMNT_READONLY; 267 else new_vmp->m_flags &= ~VMNT_READONLY; 268 269 /* Tell FS which device to mount */ 270 new_vmp->m_flags |= VMNT_MOUNTING; 271 r = req_readsuper(new_vmp, label, dev, !!(flags & MNT_RDONLY), isroot, &res, 272 &fs_flags); 273 new_vmp->m_flags &= ~VMNT_MOUNTING; 274 275 new_vmp->m_fs_flags = fs_flags; 276 277 /* Fill the statvfs cache with initial values. */ 278 if (r == OK) 279 r = update_statvfs(new_vmp, &statvfs_buf); 280 281 if (r != OK) { 282 mark_vmnt_free(new_vmp); 283 unlock_vnode(root_node); 284 if (vp != NULL) { 285 unlock_vnode(vp); 286 put_vnode(vp); 287 } 288 unlock_vmnt(new_vmp); 289 return(r); 290 } 291 292 lock_bsf(); 293 294 /* Fill in root node's fields */ 295 root_node->v_fs_e = res.fs_e; 296 root_node->v_inode_nr = res.inode_nr; 297 root_node->v_mode = res.fmode; 298 root_node->v_uid = res.uid; 299 root_node->v_gid = res.gid; 300 root_node->v_size = res.fsize; 301 root_node->v_sdev = NO_DEV; 302 root_node->v_fs_count = 1; 303 root_node->v_ref_count = 1; 304 305 /* Root node is indeed on the partition */ 306 root_node->v_vmnt = new_vmp; 307 root_node->v_dev = new_vmp->m_dev; 308 if (!(new_vmp->m_fs_flags & RES_THREADED)) 309 new_vmp->m_comm.c_max_reqs = 1; 310 else 311 new_vmp->m_comm.c_max_reqs = NR_WTHREADS; 312 new_vmp->m_comm.c_cur_reqs = 0; 313 314 /* No more blocking operations, so we can now report on this file system. */ 315 new_vmp->m_flags |= VMNT_CANSTAT; 316 317 if (mount_root) { 318 /* Superblock and root node already read. 319 * Nothing else can go wrong. Perform the mount. */ 320 new_vmp->m_root_node = root_node; 321 new_vmp->m_mounted_on = NULL; 322 strlcpy(new_vmp->m_label, mount_label, LABEL_MAX); 323 if (is_nonedev(dev)) alloc_nonedev(dev); 324 update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */); 325 326 ROOT_DEV = dev; 327 ROOT_FS_E = fs_e; 328 329 /* Replace all root and working directories */ 330 for (i = 0, tfp = fproc; i < NR_PROCS; i++, tfp++) { 331 if (tfp->fp_pid == PID_FREE) 332 continue; 333 334 #define MAKEROOT(what) { \ 335 if (what) put_vnode(what); \ 336 dup_vnode(root_node); \ 337 what = root_node; \ 338 } 339 340 MAKEROOT(tfp->fp_rd); 341 MAKEROOT(tfp->fp_wd); 342 } 343 344 unlock_vnode(root_node); 345 unlock_vmnt(new_vmp); 346 have_root++; /* We have a (new) root */ 347 unlock_bsf(); 348 return(OK); 349 } 350 351 /* File types may not conflict. */ 352 if (!S_ISDIR(vp->v_mode) && S_ISDIR(root_node->v_mode)) r = EISDIR; 353 354 /* If error, return the super block and both inodes; release the vmnt. */ 355 if (r != OK) { 356 unlock_vnode(vp); 357 unlock_vnode(root_node); 358 mark_vmnt_free(new_vmp); 359 unlock_vmnt(new_vmp); 360 put_vnode(vp); 361 put_vnode(root_node); 362 unlock_bsf(); 363 return(r); 364 } 365 366 /* Nothing else can go wrong. Perform the mount. */ 367 new_vmp->m_mounted_on = vp; 368 new_vmp->m_root_node = root_node; 369 strlcpy(new_vmp->m_label, mount_label, LABEL_MAX); 370 371 /* Allocate the pseudo device that was found, if not using a real device. */ 372 if (is_nonedev(dev)) alloc_nonedev(dev); 373 374 /* The new FS will handle block I/O requests for its device now. */ 375 if (!(new_vmp->m_flags & VMNT_FORCEROOTBSF)) 376 update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */); 377 378 unlock_vnode(vp); 379 unlock_vnode(root_node); 380 unlock_vmnt(new_vmp); 381 unlock_bsf(); 382 383 return(OK); 384 } 385 386 387 /*===========================================================================* 388 * mount_pfs * 389 *===========================================================================*/ 390 void mount_pfs(void) 391 { 392 /* Mount the Pipe File Server. It's not really mounted onto the file system, 393 but it's necessary it has a vmnt entry to make locking easier */ 394 395 dev_t dev; 396 struct vmnt *vmp; 397 398 if ((dev = find_free_nonedev()) == NO_DEV) 399 panic("VFS: no nonedev to initialize PFS"); 400 401 if ((vmp = get_free_vmnt()) == NULL) 402 panic("VFS: no vmnt to initialize PFS"); 403 404 alloc_nonedev(dev); 405 406 vmp->m_dev = dev; 407 vmp->m_fs_e = PFS_PROC_NR; 408 vmp->m_fs_flags = 0; 409 strlcpy(vmp->m_label, "pfs", LABEL_MAX); 410 strlcpy(vmp->m_mount_path, "pipe", PATH_MAX); 411 strlcpy(vmp->m_mount_dev, "none", PATH_MAX); 412 } 413 414 /*===========================================================================* 415 * do_umount * 416 *===========================================================================*/ 417 int do_umount(void) 418 { 419 /* Perform the umount(name) system call. Return the label of the FS service. 420 */ 421 char label[LABEL_MAX]; 422 dev_t dev; 423 int r; 424 char fullpath[PATH_MAX]; 425 vir_bytes vname, label_addr; 426 size_t vname_length, label_len; 427 428 vname = job_m_in.m_lc_vfs_umount.name; 429 vname_length = job_m_in.m_lc_vfs_umount.namelen; 430 label_addr = job_m_in.m_lc_vfs_umount.label; 431 label_len = job_m_in.m_lc_vfs_umount.labellen; 432 433 /* Only the super-user may do umount. */ 434 if (!super_user) return(EPERM); 435 436 /* If 'name' is not for a block special file or mountpoint, return error. */ 437 if (fetch_name(vname, vname_length, fullpath) != OK) 438 return(err_code); 439 if ((dev = name_to_dev(TRUE /*allow_mountpt*/, fullpath)) == NO_DEV) 440 return(err_code); 441 442 if ((r = unmount(dev, label)) != OK) return(r); 443 444 /* Return the label of the mounted file system, so that the caller 445 * can shut down the corresponding server process. 446 */ 447 if (strlen(label) >= label_len) 448 label[label_len-1] = 0; 449 return sys_datacopy_wrapper(SELF, (vir_bytes) label, who_e, label_addr, 450 strlen(label) + 1); 451 } 452 453 454 /*===========================================================================* 455 * unmount * 456 *===========================================================================*/ 457 int unmount( 458 dev_t dev, /* block-special device */ 459 char label[LABEL_MAX] /* buffer to retrieve label, or NULL */ 460 ) 461 { 462 struct vnode *vp; 463 struct vmnt *vmp_i = NULL, *vmp = NULL; 464 int count, locks, r; 465 466 /* Find vmnt that is to be unmounted */ 467 for (vmp_i = &vmnt[0]; vmp_i < &vmnt[NR_MNTS]; ++vmp_i) { 468 if (vmp_i->m_dev == dev) { 469 if(vmp) panic("device mounted more than once: %llx", dev); 470 vmp = vmp_i; 471 } 472 } 473 474 /* Did we find the vmnt (i.e., was dev a mounted device)? */ 475 if(!vmp) return(EINVAL); 476 477 if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK) return(r); 478 479 /* See if the mounted device is busy. Only 1 vnode using it should be 480 * open -- the root vnode -- and that inode only 1 time. */ 481 locks = count = 0; 482 for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) 483 if (vp->v_ref_count > 0 && vp->v_dev == dev) { 484 count += vp->v_ref_count; 485 if (is_vnode_locked(vp)) locks++; 486 } 487 488 if (count > 1 || locks > 1 || tll_haspendinglock(&vmp->m_lock)) { 489 unlock_vmnt(vmp); 490 return(EBUSY); /* can't umount a busy file system */ 491 } 492 493 /* This FS will now disappear, so stop listing it in statistics. */ 494 vmp->m_flags &= ~VMNT_CANSTAT; 495 496 /* Tell FS to drop all inode references for root inode except 1. */ 497 vnode_clean_refs(vmp->m_root_node); 498 499 if (vmp->m_mounted_on) { 500 put_vnode(vmp->m_mounted_on); 501 vmp->m_mounted_on = NULL; 502 } 503 504 vmp->m_comm.c_max_reqs = 1; /* Force max concurrent reqs to just one, so 505 * we won't send any messages after the 506 * unmount request */ 507 508 /* Tell FS to unmount */ 509 if ((r = req_unmount(vmp->m_fs_e)) != OK) /* Not recoverable. */ 510 printf("VFS: ignoring failed umount attempt FS endpoint: %d (%d)\n", 511 vmp->m_fs_e, r); 512 513 if (is_nonedev(vmp->m_dev)) free_nonedev(vmp->m_dev); 514 515 if (label != NULL) strlcpy(label, vmp->m_label, LABEL_MAX); 516 517 if (vmp->m_root_node) { /* PFS lacks a root node */ 518 vmp->m_root_node->v_ref_count = 0; 519 vmp->m_root_node->v_fs_count = 0; 520 vmp->m_root_node->v_sdev = NO_DEV; 521 vmp->m_root_node = NULL; 522 } 523 mark_vmnt_free(vmp); 524 525 unlock_vmnt(vmp); 526 527 /* The root FS will handle block I/O requests for this device now. */ 528 lock_bsf(); 529 update_bspec(dev, ROOT_FS_E, 1 /* send new driver endpoint */); 530 unlock_bsf(); 531 532 return(OK); 533 } 534 535 536 /*===========================================================================* 537 * unmount_all * 538 *===========================================================================*/ 539 void unmount_all(int force) 540 { 541 /* Unmount all filesystems. File systems are mounted on other file systems, 542 * so you have to pull off the loose bits repeatedly to get it all undone. 543 */ 544 545 int i; 546 struct vmnt *vmp; 547 548 /* Now unmount the rest */ 549 for (i = 0; i < NR_MNTS; i++) { 550 /* Unmount at least one. */ 551 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) { 552 if (vmp->m_dev != NO_DEV) 553 unmount(vmp->m_dev, NULL); 554 } 555 } 556 557 if (!force) return; 558 559 /* Verify nothing is locked anymore */ 560 check_vnode_locks(); 561 check_vmnt_locks(); 562 check_filp_locks(); 563 check_bsf_lock(); 564 565 /* Verify we succesfully unmounted all file systems */ 566 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) { 567 if (vmp->m_dev != NO_DEV) { 568 panic("vmp still mounted: %s %d %llx\n", vmp->m_label, 569 vmp->m_fs_e, vmp->m_dev); 570 } 571 } 572 } 573 574 /*===========================================================================* 575 * name_to_dev * 576 *===========================================================================*/ 577 static dev_t name_to_dev(int allow_mountpt, char path[PATH_MAX]) 578 { 579 /* Convert the block special file in 'user_fullpath' to a device number. 580 * If the given path is not a block special file, but 'allow_mountpt' is set 581 * and the path is the root node of a mounted file system, return that device 582 * number. In all other cases, return NO_DEV and an error code in 'err_code'. 583 */ 584 dev_t dev; 585 struct vnode *vp; 586 struct vmnt *vmp; 587 struct lookup resolve; 588 589 lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp); 590 resolve.l_vmnt_lock = VMNT_READ; 591 resolve.l_vnode_lock = VNODE_READ; 592 593 /* Request lookup */ 594 if ((vp = eat_path(&resolve, fp)) == NULL) return(NO_DEV); 595 596 if (S_ISBLK(vp->v_mode)) { 597 dev = vp->v_sdev; 598 } else if (allow_mountpt && vp->v_vmnt->m_root_node == vp) { 599 dev = vp->v_dev; 600 } else { 601 err_code = ENOTBLK; 602 dev = NO_DEV; 603 } 604 605 unlock_vnode(vp); 606 unlock_vmnt(vmp); 607 put_vnode(vp); 608 return(dev); 609 } 610 611 612 /*===========================================================================* 613 * is_nonedev * 614 *===========================================================================*/ 615 int is_nonedev(dev_t dev) 616 { 617 /* Return whether the given device is a "none" pseudo device. 618 */ 619 620 return (major(dev) == NONE_MAJOR && 621 minor(dev) > 0 && minor(dev) <= NR_NONEDEVS); 622 } 623 624 625 /*===========================================================================* 626 * find_free_nonedev * 627 *===========================================================================*/ 628 static dev_t find_free_nonedev(void) 629 { 630 /* Find a free "none" pseudo device. Do not allocate it yet. 631 */ 632 int i; 633 634 for (i = 0; i < NR_NONEDEVS; i++) 635 if (!GET_BIT(nonedev, i)) 636 return makedev(NONE_MAJOR, i + 1); 637 638 err_code = EMFILE; 639 return NO_DEV; 640 } 641