基于Android 11(Android R)分析
Fuse上层实现位于MediaProvider工程的jni相关代码中,现在整理一下sdcard挂fuse的流程
1,Vold中mount sdcard目录
开机可以查看以下log
12-24 13:52:23.531 601 601 I vold : mount volId:emulated;0.
12-24 13:52:23.531 601 601 I vold : Mounting emulated fuse volume
12-24 13:52:23.544 601 601 I vold : Bind mounting /data/media to /mnt/pass_through/0/emulated
12-24 13:52:23.544 601 601 D vold : try to unmount /mnt/pass_through/0/emulated
代码路径位于:
system/vold/model/EmulatedVolume.cpp
status_t EmulatedVolume::doMount() {
....
res = MountUserFuse(user_id, getInternalPath(), label, &fd);//internalPath=/data/media
.....
status_t MountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
1575 const std::string& relative_upper_path, android::base::unique_fd* fuse_fd) {
...........
// Note: leaving out default_permissions since we don't want kernel to do lower filesystem
1650 // permission checks before routing to FUSE daemon.
1651 const auto opts = StringPrintf(
1652 "fd=%i,"
1653 "rootmode=40000,"
1654 "allow_other,"
1655 "user_id=0,group_id=0,",
1656 fuse_fd->get());
1657
1658 result = TEMP_FAILURE_RETRY(mount("/dev/fuse", fuse_path.c_str(), "fuse",
1659 MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME | MS_LAZYTIME,
1660 opts.c_str()));
1661 if (result != 0) {
1662 PLOG(ERROR) << "Failed to mount " << fuse_path;
1663 return -errno;
1664 }
2,上层的通知及调用路径
上述第1步将data/media挂到fuse中后,接着通知到frameworks
通过log可以看到StorageManagerService收到了挂载通知
12-24 13:52:23.529 1354 2938 V StorageManagerService: Found primary storage at VolumeInfo{emulated;0}:
12-24 13:52:23.529 1354 2938 V StorageManagerService: type=EMULATED diskId=null partGuid= mountFlags=0 mountUserId=0
12-24 13:52:23.529 1354 2938 V StorageManagerService: state=UNMOUNTED
12-24 13:52:23.529 1354 2938 V StorageManagerService: fsType=null fsUuid=null fsLabel=null
12-24 13:52:23.529 1354 2938 V StorageManagerService: path=null internalPath=null
12-24 13:52:23.530 1354 2559 I StorageManagerService: Mounting volume VolumeInfo{emulated;0}:
12-24 13:52:23.530 1354 2559 I StorageManagerService: type=EMULATED diskId=null partGuid= mountFlags=PRIMARY|VISIBLE
12-24 13:52:23.530 1354 2559 I StorageManagerService: mountUserId=0 state=UNMOUNTED
12-24 13:52:23.530 1354 2559 I StorageManagerService: fsType=null fsUuid=null fsLabel=null
12-24 13:52:23.530 1354 2559 I StorageManagerService: path=null internalPath=null
12-24 13:52:23.530 1354 2559 I StorageManagerService: , isBind:false
调用StorageSessionController
12-24 13:52:23.545 1354 2559 I StorageSessionController: On volume mount VolumeInfo{emulated;0}:
12-24 13:52:23.545 1354 2559 I StorageSessionController: type=EMULATED diskId=null partGuid= mountFlags=PRIMARY|VISIBLE
12-24 13:52:23.545 1354 2559 I StorageSessionController: mountUserId=0 state=CHECKING
12-24 13:52:23.545 1354 2559 I StorageSessionController: fsType=null fsUuid=null fsLabel=null
12-24 13:52:23.545 1354 2559 I StorageSessionController: path=/storage/emulated internalPath=/data/media
12-24 13:52:23.545 1354 2559 I StorageSessionController: Creating connection for user: 0
12-24 13:52:23.546 1354 2559 I StorageSessionController: Creating and starting session with id: emulated;0
12-24 13:52:23.546 1354 2559 I StorageUserConnection: Binding to the ExternalStorageService for user 0
StorageSessionController与远程的mediaprovider服务绑定并通知它进行fuse daemon初始化操作:
StorageSessionController(onVolumeMount)
----------->StorageUserConnection
------->ExternalStorageServiceImpl(onStartSession(fd,upperFileSystem, lowerFileSystem))
------>ExternalStorageServiceImpl(new FuseDaemon(fd,path)
------>FuseDaemon.java(native_start(fd,mpath)
--->jni(com_android_providers_media_FuseDaemon.cpp)
--->FuseDaemon.cpp(start)
至此,可以看到fuse文件系统中的上层fuse daemon的主要调用流程。
参考:
https://www.cnblogs.com/Linux-tech/p/14110335.html
https://blog.csdn.net/sunedy2007/article/details/39155661?spm=1001.2014.3001.5501
https://blog.csdn.net/zhonglinzhang/article/details/104262658