* The system call that results in changing the rootfs. */
| 496 | * The system call that results in changing the rootfs. |
| 497 | */ |
| 498 | static int |
| 499 | kern_reroot(void) |
| 500 | { |
| 501 | struct vnode *oldrootvnode, *vp; |
| 502 | struct mount *mp, *devmp; |
| 503 | int error; |
| 504 | |
| 505 | if (curproc != initproc) |
| 506 | return (EPERM); |
| 507 | |
| 508 | /* |
| 509 | * Mark the filesystem containing currently-running executable |
| 510 | * (the temporary copy of init(8)) busy. |
| 511 | */ |
| 512 | vp = curproc->p_textvp; |
| 513 | error = vn_lock(vp, LK_SHARED); |
| 514 | if (error != 0) |
| 515 | return (error); |
| 516 | mp = vp->v_mount; |
| 517 | error = vfs_busy(mp, MBF_NOWAIT); |
| 518 | if (error != 0) { |
| 519 | vfs_ref(mp); |
| 520 | VOP_UNLOCK(vp); |
| 521 | error = vfs_busy(mp, 0); |
| 522 | vn_lock(vp, LK_SHARED | LK_RETRY); |
| 523 | vfs_rel(mp); |
| 524 | if (error != 0) { |
| 525 | VOP_UNLOCK(vp); |
| 526 | return (ENOENT); |
| 527 | } |
| 528 | if (VN_IS_DOOMED(vp)) { |
| 529 | VOP_UNLOCK(vp); |
| 530 | vfs_unbusy(mp); |
| 531 | return (ENOENT); |
| 532 | } |
| 533 | } |
| 534 | VOP_UNLOCK(vp); |
| 535 | |
| 536 | /* |
| 537 | * Remove the filesystem containing currently-running executable |
| 538 | * from the mount list, to prevent it from being unmounted |
| 539 | * by vfs_unmountall(), and to avoid confusing vfs_mountroot(). |
| 540 | * |
| 541 | * Also preserve /dev - forcibly unmounting it could cause driver |
| 542 | * reinitialization. |
| 543 | */ |
| 544 | |
| 545 | vfs_ref(rootdevmp); |
| 546 | devmp = rootdevmp; |
| 547 | rootdevmp = NULL; |
| 548 | |
| 549 | mtx_lock(&mountlist_mtx); |
| 550 | TAILQ_REMOVE(&mountlist, mp, mnt_list); |
| 551 | TAILQ_REMOVE(&mountlist, devmp, mnt_list); |
| 552 | mtx_unlock(&mountlist_mtx); |
| 553 | |
| 554 | oldrootvnode = rootvnode; |
| 555 |
no test coverage detected