| 1049 | } |
| 1050 | |
| 1051 | void |
| 1052 | vfs_mountroot(void) |
| 1053 | { |
| 1054 | struct mount *mp; |
| 1055 | struct sbuf *sb; |
| 1056 | struct thread *td; |
| 1057 | time_t timebase; |
| 1058 | int error; |
| 1059 | |
| 1060 | mtx_assert(&Giant, MA_NOTOWNED); |
| 1061 | |
| 1062 | TSENTER(); |
| 1063 | |
| 1064 | td = curthread; |
| 1065 | |
| 1066 | sb = sbuf_new_auto(); |
| 1067 | vfs_mountroot_conf0(sb); |
| 1068 | sbuf_finish(sb); |
| 1069 | |
| 1070 | error = vfs_mountroot_devfs(td, &mp); |
| 1071 | while (!error) { |
| 1072 | error = vfs_mountroot_parse(sb, mp); |
| 1073 | if (!error) { |
| 1074 | vfs_mountroot_shuffle(td, mp); |
| 1075 | sbuf_clear(sb); |
| 1076 | error = vfs_mountroot_readconf(td, sb); |
| 1077 | sbuf_finish(sb); |
| 1078 | } |
| 1079 | } |
| 1080 | |
| 1081 | sbuf_delete(sb); |
| 1082 | |
| 1083 | /* |
| 1084 | * Iterate over all currently mounted file systems and use |
| 1085 | * the time stamp found to check and/or initialize the RTC. |
| 1086 | * Call inittodr() only once and pass it the largest of the |
| 1087 | * timestamps we encounter. |
| 1088 | */ |
| 1089 | timebase = 0; |
| 1090 | mtx_lock(&mountlist_mtx); |
| 1091 | mp = TAILQ_FIRST(&mountlist); |
| 1092 | while (mp != NULL) { |
| 1093 | if (mp->mnt_time > timebase) |
| 1094 | timebase = mp->mnt_time; |
| 1095 | mp = TAILQ_NEXT(mp, mnt_list); |
| 1096 | } |
| 1097 | mtx_unlock(&mountlist_mtx); |
| 1098 | inittodr(timebase); |
| 1099 | |
| 1100 | /* Keep prison0's root in sync with the global rootvnode. */ |
| 1101 | mtx_lock(&prison0.pr_mtx); |
| 1102 | prison0.pr_root = rootvnode; |
| 1103 | vref(prison0.pr_root); |
| 1104 | mtx_unlock(&prison0.pr_mtx); |
| 1105 | |
| 1106 | mtx_lock(&root_holds_mtx); |
| 1107 | atomic_store_rel_int(&root_mount_complete, 1); |
| 1108 | wakeup(&root_mount_complete); |
no test coverage detected