挂载磁盘。这里都有一个const char *类型的参数,这参数保存着每个磁盘的标签信息,比如sd卡的label是sdcard。
- int VolumeManager::mountVolume(const char *label) {
- Volume *v = lookupVolume(label);
-
- if (!v) {
- errno = ENOENT;
- return -1;
- }
-
- return v->mountVol();
- }
lookupVolume函数寻找与label匹配的对象:
- Volume *VolumeManager::lookupVolume(const char *label) {
- VolumeCollection::iterator i;
-
- for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
- if (label[0] == '/') {
- if (!strcmp(label, (*i)->getMountpoint()))
- return (*i);
- } else {
- if (!strcmp(label, (*i)->getLabel()))
- return (*i);
- }
- }
- return NULL;
- }
如果找到,直接返回磁盘对象Volume*,挂载操作在mountVol函数里面,该函数内容有点多,贴源码:
- int Volume::mountVol() {
- dev_t deviceNodes[4];
- int n, i, rc = 0;
- char errmsg[255];
-
- if (getState() == Volume::State_NoMedia) {
- snprintf(errmsg, sizeof(errmsg),
- "Volume %s %s mount failed - no media",
- getLabel(), getMountpoint());
- mVm->getBroadcaster()->sendBroadcast(
- ResponseCode::VolumeMountFailedNoMedia,
- errmsg, false);
- errno = ENODEV;
- return -1;
- } else if (getState() != Volume::State_Idle) {
- errno = EBUSY;
- return -1;
- }
-
- if (isMountpointMounted(getMountpoint())) {
- SLOGW("Volume is idle but appears to be mounted - fixing");
-
- setState(Volume::State_Mounted);
-
- return 0;
- }
-
- n = getDeviceNodes((dev_t *) &deviceNodes, 4);
- if (!n) {
- SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
- return -1;
- }
-
- for (i = 0; i < n; i++) {
- char devicePath[255];
-
- sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),
- MINOR(deviceNodes[i]));
-
- SLOGI("%s being considered for volume %s\n", devicePath, getLabel());
-
- errno = 0;
- setState(Volume::State_Checking);
-
- if (Fat::check(devicePath)) {
- if (errno == ENODATA) {
- SLOGW("%s does not contain a FAT filesystem\n", devicePath);
- continue;
- }
- errno = EIO;
-
- SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
- setState(Volume::State_Idle);
- return -1;
- }
-
-
-
-
-
- errno = 0;
-
- if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, 1000, 1015, 0702, true)) {
- SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
- continue;
- }
-
- SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint());
-
- protectFromAutorunStupidity();
-
-
-
- if (createBindMounts()) {
- SLOGE("Failed to create bindmounts (%s)", strerror(errno));
- umount("/mnt/secure/staging");
- setState(Volume::State_Idle);
- return -1;
- }
-
-
-
-
-
-
- if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) {
- SLOGE("Failed to move mount (%s)", strerror(errno));
- umount("/mnt/secure/staging");
- setState(Volume::State_Idle);
- return -1;
- }
- setState(Volume::State_Mounted);
- mLastMountedKdev = mCurrentlyMountedKdev = deviceNodes[i];
- return 0;
- }
-
- SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());
- setState(Volume::State_Idle);
-
- return -1;
- }
这个挂载函数看起来,会发现很繁琐,好几个目录的挂载关系,有以下挂载目录:
/dev/block/vold/8:1 挂载在-> /mnt/secure/staging
/mnt/secure/staging/.android_secure 挂载在-> /mnt/secure/asec
tmpfs 挂载在-> /mnt/secure/staging/.android_secure
/mnt/secure/staging 挂载在-> /mnt/sdcard
从程序的注释看,这样的目的是挂载一个只有root用户能查看的目录,具体还是没搞清楚谷歌为什么要这样挂载,
还是有疑问,希望有清楚的高手指点一下。
sd卡的挂载比较清楚,中间多了一个中介,将设备节点8:1挂载在/mnt/secure/staging,最后又将该目录挂载在/mnt/sdcard,
这目录就是最终用户能够看到文件的目录。
函数里面涉及到几个函数:
getDeviceNodes函数获取挂载设备的设备号与分区数量,是Volume类的一个纯虚函数,在子类DirectVolume中实现,源码:
- int DirectVolume::getDeviceNodes(dev_t *devs, int max) {
- if (mPartIdx == -1) {
-
- if (!mDiskNumParts) {
- devs[0] = MKDEV(mDiskMajor, mDiskMinor);
- return 1;
- }
-
- int i;
- for (i = 0; i < mDiskNumParts; i++) {
- if (i == max)
- break;
- devs[i] = MKDEV(mDiskMajor, mPartMinors[i]);
- }
- return mDiskNumParts;
- }
- devs[0] = MKDEV(mDiskMajor, mPartMinors[mPartIdx -1]);
- return 1;
- }
下面贴一些mountVol里面挂载的源码:
- int Fat::doMount(const char *fsPath, const char *mountPoint,
- bool ro, bool remount, int ownerUid, int ownerGid,
- int permMask, bool createLost) {
- int rc;
- unsigned long flags;
- char mountData[255];
-
- flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC;
-
- flags |= (ro ? MS_RDONLY : 0);
- flags |= (remount ? MS_REMOUNT : 0);
-
-
-
-
-
-
-
- char value[PROPERTY_VALUE_MAX];
- property_get("persist.sampling_profiler", value, "");
- if (value[0] == '1') {
- SLOGW("The SD card is world-writable because the"
- " 'persist.sampling_profiler' system property is set to '1'.");
- permMask = 0;
- }
-
- sprintf(mountData,
- "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",
- ownerUid, ownerGid, permMask, permMask);
-
- rc = mount(fsPath, mountPoint, "vfat", flags, mountData);
-
- if (rc && errno == EROFS) {
- SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath);
- flags |= MS_RDONLY;
- rc = mount(fsPath, mountPoint, "vfat", flags, mountData);
- }
-
- if (rc == 0 && createLost) {
- char *lost_path;
- asprintf(&lost_path, "%s/LOST.DIR", mountPoint);
- if (access(lost_path, F_OK)) {
-
-
-
-
- if (mkdir(lost_path, 0755)) {
- SLOGE("Unable to create LOST.DIR (%s)", strerror(errno));
- }
- }
- free(lost_path);
- }
-
- return rc;
- }
-
- int Volume::createBindMounts() {
- unsigned long flags;
-
-
-
-
- if (!access("/mnt/secure/staging/android_secure", R_OK | X_OK) &&
- access(SEC_STG_SECIMGDIR, R_OK | X_OK)) {
- if (rename("/mnt/secure/staging/android_secure", SEC_STG_SECIMGDIR)) {
- SLOGE("Failed to rename legacy asec dir (%s)", strerror(errno));
- }
- }
-
-
-
-
- if (access(SEC_STG_SECIMGDIR, R_OK | X_OK)) {
- if (errno == ENOENT) {
- if (mkdir(SEC_STG_SECIMGDIR, 0777)) {
- SLOGE("Failed to create %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
- return -1;
- }
- } else {
- SLOGE("Failed to access %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
- return -1;
- }
- } else {
- struct stat sbuf;
-
- if (stat(SEC_STG_SECIMGDIR, &sbuf)) {
- SLOGE("Failed to stat %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
- return -1;
- }
- if (!S_ISDIR(sbuf.st_mode)) {
- SLOGE("%s is not a directory", SEC_STG_SECIMGDIR);
- errno = ENOTDIR;
- return -1;
- }
- }
-
-
-
-
-
- if (mount(SEC_STG_SECIMGDIR, SEC_ASECDIR, "", MS_BIND, NULL)) {
- SLOGE("Failed to bind mount points %s -> %s (%s)",
- SEC_STG_SECIMGDIR, SEC_ASECDIR, strerror(errno));
- return -1;
- }
-
-
-
-
-
- if (mount("tmpfs", SEC_STG_SECIMGDIR, "tmpfs", MS_RDONLY, "size=0,mode=000,uid=0,gid=0")) {
- SLOGE("Failed to obscure %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
- umount("/mnt/asec_secure");
- return -1;
- }
-
- return 0;
- }
-
- int Volume::doMoveMount(const char *src, const char *dst, bool force) {
- unsigned int flags = MS_MOVE;
- int retries = 5;
-
- while(retries--) {
- if (!mount(src, dst, "", flags, NULL)) {
- if (mDebug) {
- SLOGD("Moved mount %s -> %s sucessfully", src, dst);
- }
- return 0;
- } else if (errno != EBUSY) {
- SLOGE("Failed to move mount %s -> %s (%s)", src, dst, strerror(errno));
- return -1;
- }
- int action = 0;
-
- if (force) {
- if (retries == 1) {
- action = 2;
- } else if (retries == 2) {
- action = 1;
- }
- }
- SLOGW("Failed to move %s -> %s (%s, retries %d, action %d)",
- src, dst, strerror(errno), retries, action);
- Process::killProcessesWithOpenFiles(src, action);
- usleep(1000*250);
- }
-
- errno = EBUSY;
- SLOGE("Giving up on move %s -> %s (%s)", src, dst, strerror(errno));
- return -1;
- }