分区表修改和分区挂载流

分区表修改和分区挂载流程总结

项目: MTK平台项目

二、分区的挂载
首先介绍fstab文件,这个文件描述系统中各种文件系统的信息,在这个文件中,每个文件系统用一行来描述,在每一行中,用空格或TAB符号来分隔各个字段,文件中以#开头的行是注释信息。Fstab文件中的纪录的排序十分重要。因为fsck,mount或umount等程序在做它们的工作时会按此顺序进行。
首先来看该文件中每个字段的定义。
<fs_mgr_flags>
product /product _MTK_VNDIMG_FSTYPE ro wait,avb,logical,first_stage_mount,FLAG_SLOT_SELECT
字段1:待挂载的设备节点路径
字段2:挂载点
字段3:所挂载磁盘的文件系统类型(ext4,f2fs,emmc)
字段4:文件系统参数(rw/ro noauto_da_alloc/auto_da_alloc barrier async/syncd defaults等)
字段5:

在我们的项目中,一般用如下文件描述:
alps/vendor/mediatek/proprietary/hardware/fstab/mtxxxx/fstab.in.mtxxxx

kernel起来以后执行的第一个文件是init进程,init进程会根据init.rc的规则启动进程或者服务。init.rc通过"import /init.${ro.hardware}.rc"语句导入平台的规则。
mount_all是一条命令,/vendor/etc/fstab.mt6765是传入的参数
126on fs
127 write /proc/bootprof “INIT:Mount_START”
128 write /sys/kernel/debug/tracing/trace_marker “B|1|Mount”
129 wait_for_prop hwservicemanager.ready “true”
130 start vendor.boot-hal-1-0
131 mount_all /vendor/etc/fstab.mt6765
133 write /sys/kernel/debug/tracing/trace_marker “E”
134 write /proc/bootprof “INIT:Mount_END”

static const Map builtin_functions = {
….
{“mount_all”, {1, kMax, {false, do_mount_all}}},
….
}
通过这个map结构体把mount_all和do_mount_all函数绑定在一起。
do_mount_all函数主要调用了mount_fstab(fstabfile, mount_mode);
两个参数分别为/vendor/etc/fstab.mt6765 MOUNT_MODE_DEFAULT

529static Result mount_fstab(const std::string& fstabfile, int mount_mode) {
530 return handle_fstab(fstabfile, [mount_mode](Fstab* fstab) {
531 int ret = fs_mgr_mount_all(fstab, mount_mode);
532 if (ret == -1) {
533 PLOG(ERROR) << “fs_mgr_mount_all returned an error”;
534 }
535 return ret;
536 });
537}
该函数调用了handle_fstab,这个函数2个参数为传进来的fstabfile文件(在手机的vendor/etc下面
)和一个函数(这个函数主要是调用fs_mgr_mount_all(fstab, mount_mode))。
生成的fstab.mt6765文件的部分内容

113 “vendor/mediatek/proprietary/hardware/fstab/mt6765/fstab.in.mt6765”

system /system ext4 ro wait,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey,
vendor /vendor ext4 ro wait,avb,logical,first_stage_mount,

product /product ext4 ro wait,avb,logical,first_stage_mount,

static Result handle_fstab(const std::string& fstabfile, std::function<int(Fstab*)> func) {
//使用fs_mgr_mount_all()函数去挂载所有的文件系统,使用fork()函数分配一个新的进程,在子进程中做挂载的事情,这样即使挂载出现问题,也能保护init主进程。
488 pid_t pid = fork();
489 if (pid > 0) {
490 /* Parent. Wait for the child to return */
……
503 } else if (pid == 0) {
……
514 Fstab fstab;
//加载分区挂载文件的内容到fstab容器中
515 ReadFstabFromFile(fstabfile, &fstab);
//调用fs_mgr_mount_all函数挂载分区
517 int child_ret = func(&fstab);
518
519 _exit(child_ret);
520 } else {
521 return Error() << “fork() failed”;
522 }
523}
524

Fstab的定义,是一个容器的别名。
using Fstab = std::vector;
FstabEntry的结构体成员主要如下:

std::string blk_device;
34 std::string logical_partition_name;
35 std::string mount_point;
36 std::string fs_type;
37 unsigned long flags = 0;
struct FsMgrFlags {
61 bool wait : 1;
62 bool check : 1;
63 bool crypt : 1;
64 bool nonremovable : 1;
65 bool vold_managed : 1;
66 bool recovery_only : 1;
67 bool verify : 1;
……
}

在ReadFstabFromFile(fstabfile, &fstab);中主要调用ReadFstabFile(),该函数将fstab文件中的信息解析到fstab容器中。下面
465bool ReadFstabFile(FILE* fstab_file, bool proc_mounts, Fstab* fstab_out) {
470 char *save_ptr, *p;
471 Fstab fstab;
472 //一行一行解析,赋值给entry结构体,最后将entry结构体放进fstab容器中
473 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
488 FstabEntry entry;
……
494 entry.blk_device = p;//文件系统的绝对路径
……
500 entry.mount_point = p;//挂载点
….
506 entry.fs_type = p;//文件系统类型
….
//挂载标志
513 ParseMountFlags(p, &entry);
523 ParseFsMgrFlags(p, &entry);
524
525 if (entry.fs_mgr_flags.logical) {
526 entry.logical_partition_name = entry.blk_device;
527 }
528
529 fstab.emplace_back(std::move(entry));
530 }
531
543 *fstab_out = std::move(fstab);
}

接着分析另外一个重要的函数,在将编译出来的fstab.mt6765文件解析到fstab容器后,调用函数fs_mgr_mount_all来挂载。

1233int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
//对fstab容器中的每一个分区进行判断,并对需要挂载的分区进行挂载
1243 for (size_t i = 0; i < fstab->size(); i++) {
//如下为一些排除掉的分区
//第一阶段挂载&&(不可格式化||挂载点已经被挂载)
if (current_entry.fs_mgr_flags.first_stage_mount &&
1251 (!current_entry.fs_mgr_flags.formattable ||
1252 IsMountPointMounted(current_entry.mount_point))) {
1253 continue;
1254 }
1255
1256 // vold管理的分区,只在recovery模式存在的分区,和一些非正常挂载模式
1257 if (current_entry.fs_mgr_flags.vold_managed || current_entry.fs_mgr_flags.recovery_only ||
1258 ((mount_mode == MOUNT_MODE_LATE) && !current_entry.fs_mgr_flags.late_mount) ||
1259 ((mount_mode == MOUNT_MODE_EARLY) && current_entry.fs_mgr_flags.late_mount)) {
1260 continue;
1261 }
1262
1263 //没有文件系统的分区
1264 if (current_entry.fs_type == “swap” || current_entry.fs_type == “emmc” ||
1265 current_entry.fs_type == “mtd”) {
1266 continue;
1267 }
1268
1269 // 挂载点为根目录和system
1270 if (current_entry.mount_point == “/” || current_entry.mount_point == “/system”) {
1271 if ((current_entry.flags & MS_RDONLY) != 0) {
1272 fs_mgr_set_blk_ro(current_entry.blk_device);
1273 }
1274 continue;
1275 }
1276
1277 // Translate LABEL= file system labels into block devices.
1278 if (is_extfs(current_entry.fs_type)) {
1279 if (!TranslateExtLabels(&current_entry)) {
1280 LERROR << “Could not translate label to block device”;
1281 continue;
1282 }
1283 }
1284 //逻辑分区
1285 if (current_entry.fs_mgr_flags.logical) {
1286 if (!fs_mgr_update_logical_partition(&current_entry)) {
1287 LERROR << “Could not set up logical partition, skipping!”;
1288 continue;
1289 }
1290 }
1291
1292 if (!checkpoint_manager.Update(&current_entry)) {
1293 continue;
1294 }
1295
1296 if (current_entry.fs_mgr_flags.wait &&
1297 !fs_mgr_wait_for_file(current_entry.blk_device, 20s)) {
1298 LERROR << “Skipping '” << current_entry.blk_device << “’ during mount_all”;
1299 continue;
1300 }
1301
1302 if (current_entry.fs_mgr_flags.avb) {
1303 if (!avb_handle) {
1304 avb_handle = AvbHandle::Open();
1305 if (!avb_handle) {
1306 LERROR << “Failed to open AvbHandle”;
1307 return FS_MGR_MNTALL_FAIL;
1308 }
1309 }
1310 if (avb_handle->SetUpAvbHashtree(&current_entry, true /* wait_for_verity_dev */) ==
1311 AvbHashtreeResult::kFail) {
1312 LERROR << "Failed to set up AVB on partition: " << current_entry.mount_point
1313 << “, skipping!”;
1314 // Skips mounting the device.
1315 continue;
1316 }
1317 } else if (!current_entry.avb_keys.empty()) {
1318 if (AvbHandle::SetUpStandaloneAvbHashtree(&current_entry) == AvbHashtreeResult::kFail) {
1319 LERROR << "Failed to set up AVB on standalone partition: "
1320 << current_entry.mount_point << “, skipping!”;
1321 // Skips mounting the device.
1322 continue;
1323 }
1324 } else if ((current_entry.fs_mgr_flags.verify)) {
1325 int rc = fs_mgr_setup_verity(&current_entry, true);
1326 if (rc == FS_MGR_SETUP_VERITY_DISABLED || rc == FS_MGR_SETUP_VERITY_SKIPPED) {
1327 LINFO << “Verity disabled”;
1328 } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
1329 LERROR << “Could not set up verified partition, skipping!”;
1330 continue;
1331 }
1332
auto& current_entry = (*fstab)[i];
//挂载函数
1338 bool mret = mount_with_alternatives(*fstab, i, &last_idx_inspected, &attempted_idx);
1366 ……
top_idx =i;

		//如果挂载失败,符合一定条件且分区能够格式化可以重新挂载

1397 if (fs_mgr_do_format(current_entry, crypt_footer) == 0) {
1398 // Let’s replay the mount actions.
1399 i = top_idx - 1;
1400 continue;
1401 }
1369 }

一层层调用后最终的实现函数为fs_mgr.cpp的__mount函数,然后调用系统的mount函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值