int vfat_mount(blkdev_t *dev, volume_t *vol) { int flags, rc; #if VFAT_DEBUG LOG_VOL("vfat_mount(%s, %s):\n", dev->dev_fspath, vol->mount_point); #endif flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; rc = mount(dev->dev_fspath, vol->mount_point, "vfat", flags, "utf8,uid=1000,gid=1000,fmask=711,dmask=700"); if (rc && errno == EROFS) { LOGE("vfat_mount(%s, %s): Read only filesystem - retrying mount RO\n", dev->dev_fspath, vol->mount_point); flags |= MS_RDONLY; rc = mount(dev->dev_fspath, vol->mount_point, "vfat", flags, "utf8,uid=1000,gid=1000,fmask=711,dmask=700"); } #if VFAT_DEBUG LOG_VOL("vfat_mount(%s, %s): mount rc = %d\n", dev->dev_fspath, vol->mount_point, rc); #endif return rc; }
int devmapper_genesis(struct devmapping *dm) { if (dm->src_type == dmsrc_loopback) { int fd; LOG_VOL("devmapper_genesis(): Working on %s", dm->type_data.loop.loop_src); unlink(dm->type_data.loop.loop_src); LOG_VOL("devmapper_genesis(): Creating imagefile (%u MB)", dm->size_mb); if ((fd = creat(dm->type_data.loop.loop_src, 0600)) < 0) { LOGE("Error creating imagefile (%s)", strerror(errno)); return -errno; } if (ftruncate(fd, (dm->size_mb * (1024 * 1024))) < 0) { LOGE("Error truncating imagefile (%s)", strerror(errno)); close(fd); return -errno; } close(fd); } else if (dm->src_type == dmsrc_partition) { LOGE("partition maps not yet supported"); return -ENOSYS; } return devmapper_start(dm); }
static void check_uevent(struct uevent *event) { int i; int child_state; if ( !strcmp(event->subsystem,"usb") && event->action == action_add && !target_inserted) { for (i = 0; i < UEVENT_PARAMS_MAX; i++) { if (!event->param[i]) break; if (!strncmp(event->param[i], "PRODUCT=", strlen("PRODUCT="))) { char *a = event->param[i] + strlen("PRODUCT="); if (!strcmp(a, "12d1/1446/0")) { // got you! Huawei E161/E169u LOG_VOL("Find target:%s => ready to call system", event->param[i]); target_inserted = 1; pid = fork(); if (!pid) run_child(); else { LOGD("waiting for usb_modeswitch terminated"); wait(&child_state); pid = -1; LOGD("ok now usb_modeswitch terminated"); } break; } } LOG_VOL("%s", event->param[i]); } } else if ( !strcmp(event->subsystem,"usb") && event->action == action_remove && target_inserted ) { target_inserted = 0; } }
static void dump_uevent(struct uevent *event) { int i; LOG_VOL("[UEVENT] Sq: %u S: %s A: %d P: %s", event->seqnum, event->subsystem, event->action, event->path); for (i = 0; i < UEVENT_PARAMS_MAX; i++) { if (!event->param[i]) break; LOG_VOL("%s", event->param[i]); } }
int vfat_identify(blkdev_t *dev) { #if VFAT_DEBUG LOG_VOL("vfat_identify(%d:%d):", dev->major, dev->minor); #endif return 0; // XXX: Implement }
static int mmc_bootstrap_block(char *devpath) { char blockdir_path[255]; DIR *d; struct dirent *de; #if DEBUG_BOOTSTRAP LOG_VOL("mmc_bootstrap_block(%s):", devpath); #endif sprintf(blockdir_path, "/sys%s", devpath); if (!(d = opendir(blockdir_path))) { LOGE("Failed to opendir %s", devpath); return -errno; } while ((de = readdir(d))) { char tmp[255]; if (de->d_name[0] == '.') continue; sprintf(tmp, "%s/%s", devpath, de->d_name); if (mmc_bootstrap_mmcblk(tmp)) LOGE("Error bootstraping mmcblk @ %s", tmp); } closedir(d); return 0; }
static int destroy_devmapping(struct devmapping *dm) { struct dm_ioctl *io; int dmFd; int rc = 0; LOG_VOL("destroy_devmapping():"); if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) { LOGE("Error opening device mapper (%d)", errno); return -errno; } if (!(io = _dm_ioctl_setup(dm, DM_PERSISTENT_DEV_FLAG))) { LOGE("Unable to setup ioctl (out of memory)"); rc = -ENOMEM; goto out_nofree; } if ((rc = ioctl(dmFd, DM_DEV_REMOVE, io)) < 0) { LOGE("device-mapper remove ioctl failed (%d)", errno); rc = -errno; goto out_free; } out_free: free (io); out_nofree: close (dmFd); return rc; }
static int mmc_bootstrap_mmcblk(char *devpath) { char *mmcblk_devname; int part_no; int rc; #if DEBUG_BOOTSTRAP LOG_VOL("mmc_bootstrap_mmcblk(%s):", devpath); #endif if ((rc = mmc_bootstrap_mmcblk_partition(devpath))) { LOGE("Error bootstrapping mmcblk partition '%s'", devpath); return rc; } for (mmcblk_devname = &devpath[strlen(devpath)]; *mmcblk_devname != '/'; mmcblk_devname--); mmcblk_devname++; for (part_no = 0; part_no < 4; part_no++) { char part_file[255]; sprintf(part_file, "/sys%s/%sp%d", devpath, mmcblk_devname, part_no); if (!access(part_file, F_OK)) { char part_devpath[255]; sprintf(part_devpath, "%s/%sp%d", devpath, mmcblk_devname, part_no); if (mmc_bootstrap_mmcblk_partition(part_devpath)) LOGE("Error bootstrapping mmcblk partition '%s'", part_devpath); } } return 0; }
int devmapper_start(struct devmapping *dm) { int rc; char src_blkdev_path[255]; #if DEBUG_DEVMAPPER LOG_VOL("devmapper_start()"); #endif if (dm->src_type == dmsrc_loopback) { if ((rc = loopback_start(dm)) < 0) return rc; } else if (dm->src_type == dmsrc_partition) { LOGE("partition maps not yet supported"); return -ENOSYS; } else { LOGE("devmapper_start(): Unsupported source type '%d'", dm->src_type); return -ENOENT; } /* * Configure the device mapper */ if ((rc = create_devmapping(dm)) < 0) { LOGE("Failed to create devmapping (%d)", rc); // XXX: if loopback then tear down return rc; } return 0; }
int vfat_identify(blkdev_t *dev) { #if VFAT_DEBUG LOG_VOL("vfat_identify(%s):\n", dev->dev_fspath); #endif return 0; // XXX: Implement }
static void _cb_volume_stopped_for_shutdown(volume_t *v, void *arg) { void (* shutdown_cb) (volume_t *) = arg; #if DEBUG_VOLMGR LOG_VOL("Volume %s has been stopped for shutdown", v->mount_point); #endif shutdown_cb(v); }
static int volmgr_stop_volume(volume_t *v, void (*cb) (volume_t *, void *), void *arg, boolean emit_statechange) { int i, rc; if (v->state == volstate_mounted || v->state == volstate_badremoval) { // Try to unmount right away (5 retries) for (i = 0; i < 5; i++) { rc = umount(v->mount_point); if (!rc) break; if (rc && (errno == EINVAL || errno == ENOENT)) { rc = 0; break; } LOGI("volmngr quick stop umount(%s) attempt %d (%s)", v->mount_point, i + 1, strerror(errno)); if (i == 0) usleep(1000 * 250); // First failure, sleep for 250 ms else sched_yield(); } if (!rc) { LOGI("volmgr_stop_volume(%s): Volume unmounted sucessfully", v->mount_point); if (emit_statechange) volume_setstate(v, volstate_unmounted); v->fs = NULL; goto out_cb_immed; } /* * Since the volume is still in use, dispatch the stopping to * a thread */ LOGW("Volume %s is busy (%d) - uncaging the reaper", v->mount_point, rc); volmgr_uncage_reaper(v, cb, arg); return -EINPROGRESS; } else if (v->state == volstate_checking) { volume_setstate(v, volstate_unmounted); if (v->worker_running) { LOG_VOL("Cancelling worker thread"); pthread_kill(v->worker_thread, SIGUSR1); } else LOGE("Strange... we were in checking state but worker thread wasn't running.."); goto out_cb_immed; } out_cb_immed: if (cb) cb(v, arg); return 0; }
/* * Called when a volume is sucessfully unmounted for UMS enable */ static void _cb_volstopped_for_ums_enable(volume_t *v, void *arg) { int rc; char *devdir_path; #if DEBUG_VOLMGR LOG_VOL("_cb_volstopped_for_ums_enable(%s):", v->mount_point); #endif devdir_path = blkdev_get_devpath(v->dev->disk); #ifdef ADD_ISO LOG_VOL("call ums_enable:ums_path=%s\n", v->ums_path); if ((rc = ums_enable(devdir_path, v->ums_path, true)) < 0) { #else if ((rc = ums_enable(devdir_path, v->ums_path)) < 0) { #endif free(devdir_path); LOGE("Error enabling ums (%d)", rc); return; } free(devdir_path); volume_setstate(v, volstate_ums); pthread_mutex_unlock(&v->lock); } static int volmgr_readconfig(char *cfg_path) { cnode *root = config_node("", ""); cnode *node; config_load_file(root, cfg_path); node = root->first_child; while (node) { if (!strncmp(node->name, "volume_", 7)) volmgr_config_volume(node); else LOGE("Skipping unknown configuration node '%s'", node->name); node = node->next; } return 0; }
void ums_hostconnected_set(boolean connected) { #if DEBUG_UMS LOG_VOL("ums_hostconnected_set(%d):", connected); #endif host_connected = connected; if (!connected) ums_enabled_set(false); send_msg(connected ? VOLD_EVT_UMS_CONNECTED : VOLD_EVT_UMS_DISCONNECTED); }
/* * Instructs the volume manager to enable or disable USB mass storage * on any volumes configured to use it. */ int volmgr_enable_ums(boolean enable) { volume_t *v = vol_root; while(v) { if (v->ums_path) { int rc; if (enable) { pthread_mutex_lock(&v->lock); if (v->state == volstate_mounted) volmgr_send_eject_request(v); else if (v->state == volstate_ums || v->state == volstate_nomedia) { pthread_mutex_unlock(&v->lock); goto next_vol; } // Stop the volume, and enable UMS in the callback rc = volmgr_shutdown_volume(v, _cb_volstopped_for_ums_enable, false); if (rc != -EINPROGRESS) { if (rc) LOGE("unable to shutdown volume '%s'", v->mount_point); pthread_mutex_unlock(&v->lock); } } else { // Disable UMS pthread_mutex_lock(&v->lock); if (v->state != volstate_ums) { pthread_mutex_unlock(&v->lock); goto next_vol; } if ((rc = ums_disable(v->ums_path)) < 0) { LOGE("unable to disable ums on '%s'", v->mount_point); pthread_mutex_unlock(&v->lock); continue; } LOG_VOL("Kick-starting volume %d:%d after UMS disable", v->dev->disk->major, v->dev->disk->minor); // Start volume if ((rc = _volmgr_consider_disk_and_vol(v, v->dev->disk)) < 0) { LOGE("volmgr failed to consider disk %d:%d", v->dev->disk->major, v->dev->disk->minor); } pthread_mutex_unlock(&v->lock); } } next_vol: v = v->next; } return 0; }
static void _cb_volume_stopped_for_eject(volume_t *v, void *arg) { void (* eject_cb) (blkdev_t *) = arg; #if DEBUG_VOLMGR LOG_VOL("Volume %s has been stopped for eject", v->mount_point); #endif if (eject_cb) eject_cb(v->dev); v->dev = NULL; // Clear dev because its being ejected }
int vfat_check(blkdev_t *dev) { int rc; boolean rw = true; #if VFAT_DEBUG LOG_VOL("vfat_check(%d:%d):", dev->major, dev->minor); #endif if (access(FSCK_MSDOS_PATH, X_OK)) { LOGE("vfat_check(%d:%d): %s not found (skipping checks)", dev->major, dev->minor, FSCK_MSDOS_PATH); return 0; } int pass = 1; do { char *args[5]; args[0] = FSCK_MSDOS_PATH; args[1] = "-p"; args[2] = "-f"; args[3] = blkdev_get_devpath(dev); args[4] = NULL; rc = logwrap(4, args, 1); free(args[3]); if (rc == 0) { LOG_VOL("Filesystem check completed OK"); return 0; } else if (rc == 2) { LOG_VOL("Filesystem check failed (not a FAT filesystem)"); return -ENODATA; } else if (rc == 4) { if (pass++ <= 3) { LOG_VOL("Filesystem modified - rechecking (pass %d)", pass); continue; } else { LOG_VOL("Failing check after too many rechecks"); return -EIO; } } else if (rc == -11) { LOG_VOL("Filesystem check crashed"); return -EIO; } else { LOG_VOL("Filesystem check failed (unknown exit code %d)", rc); return -EIO; } } while (0); return 0; }
static void volmgr_add_mediapath_to_volume(volume_t *v, char *media_path) { int i; #if DEBUG_VOLMGR LOG_VOL("volmgr_add_mediapath_to_volume(%p, %s):", v, media_path); #endif for (i = 0; i < VOLMGR_MAX_MEDIAPATHS_PER_VOLUME; i++) { if (!v->media_paths[i]) { v->media_paths[i] = strdup(media_path); return; } } LOGE("Unable to add media path '%s' to volume (out of media slots)", media_path); }
static void dispatch_cmd(char *cmd) { struct cmd_dispatch *c; LOG_VOL("dispatch_cmd(%s):", cmd); for (c = dispatch_table; c->cmd != NULL; c++) { if (!strncmp(c->cmd, cmd, strlen(c->cmd))) { c->dispatch(cmd); return; } } LOGE("No cmd handlers defined for '%s'", cmd); }
static int mmc_bootstrap_mmcblk_partition(char *devpath) { char filename[255]; char *uevent_buffer; ssize_t sz; char *uevent_params[4]; char tmp[255]; FILE *fp; char line[255]; #if DEBUG_BOOTSTRAP LOG_VOL("mmc_bootstrap_mmcblk_partition(%s):", devpath); #endif sprintf(tmp, "DEVPATH=%s", devpath); uevent_params[0] = strdup(tmp); sprintf(filename, "/sys%s/uevent", devpath); if (!(fp = fopen(filename, "r"))) { LOGE("Unable to open '%s' (%s)", filename, strerror(errno)); return -errno; } while (fgets(line, sizeof(line), fp)) { line[strlen(line)-1] = 0; if (!strncmp(line, "DEVTYPE=", 8)) uevent_params[1] = strdup(line); else if (!strncmp(line, "MAJOR=",6)) uevent_params[2] = strdup(line); else if (!strncmp(line, "MINOR=",6)) uevent_params[3] = strdup(line); } fclose(fp); if (!uevent_params[1] || !uevent_params[2] || !uevent_params[3]) { LOGE("mmcblk uevent missing required params"); return -1; } uevent_params[4] = '\0'; if (simulate_uevent("block", devpath, "add", uevent_params) < 0) { LOGE("Error simulating uevent (%s)", strerror(errno)); return -errno; } return 0; }
static int dispatch_uevent(struct uevent *event) { int i; #if DEBUG_UEVENT dump_uevent(event); #endif for (i = 0; dispatch_table[i].subsystem != NULL; i++) { if (!strcmp(dispatch_table[i].subsystem, event->subsystem)) return dispatch_table[i].dispatch(event); } #if DEBUG_UEVENT LOG_VOL("No uevent handlers registered for '%s' subsystem", event->subsystem); #endif return 0; }
int volmgr_format_volume(char *mount_point) { int rc; volume_t *v; LOG_VOL("volmgr_format_volume(%s):", mount_point); v = volmgr_lookup_volume_by_mountpoint(mount_point, true); if (!v) return -ENOENT; if (v->state == volstate_mounted || v->state == volstate_mounted_ro || v->state == volstate_ums || v->state == volstate_checking) { LOGE("Can't format '%s', currently in state %d", mount_point, v->state); pthread_mutex_unlock(&v->lock); return -EBUSY; } else if (v->state == volstate_nomedia && v->media_type != media_devmapper) { LOGE("Can't format '%s', (no media)", mount_point); pthread_mutex_unlock(&v->lock); return -ENOMEDIUM; } // XXX:Reject if the underlying source media is not present if (v->media_type == media_devmapper) { if ((rc = devmapper_genesis(v->dm)) < 0) { LOGE("devmapper genesis failed for %s (%d)", mount_point, rc); pthread_mutex_unlock(&v->lock); return rc; } } else { if ((rc = initialize_mbr(v->dev->disk)) < 0) { LOGE("MBR init failed for %s (%d)", mount_point, rc); pthread_mutex_unlock(&v->lock); return rc; } } volume_setstate(v, volstate_formatting); pthread_mutex_unlock(&v->lock); return rc; }
int vfat_check(blkdev_t *dev) { int rc; #if VFAT_DEBUG LOG_VOL("vfat_check(%s):\n", dev->dev_fspath); #endif if (access(FSCK_MSDOS_PATH, X_OK)) { LOGE("vfat_check(%s): %s not found (skipping checks)\n", FSCK_MSDOS_PATH, dev->dev_fspath); return 0; } #ifdef VERIFY_PASS char *args[7]; args[0] = FSCK_MSDOS_PATH; args[1] = "-v"; args[2] = "-V"; args[3] = "-w"; args[4] = "-p"; args[5] = dev->dev_fspath; args[6] = NULL; rc = logwrap(6, args); #else char *args[6]; args[0] = FSCK_MSDOS_PATH; args[1] = "-v"; args[2] = "-w"; args[3] = "-p"; args[4] = dev->dev_fspath; args[5] = NULL; rc = logwrap(5, args); #endif if (rc == 0) { LOG_VOL("Filesystem check completed OK\n"); return 0; } else if (rc == 1) { LOG_VOL("Filesystem check failed (general failure)\n"); return -EINVAL; } else if (rc == 2) { LOG_VOL("Filesystem check failed (invalid usage)\n"); return -EIO; } else if (rc == 4) { LOG_VOL("Filesystem check completed (errors fixed)\n"); } else { LOG_VOL("Filesystem check failed (unknown exit code %d)\n", rc); return -EIO; } return 0; }
int devmapper_stop(struct devmapping *dm) { int rc; LOG_VOL("devmapper_stop():"); if ((rc = destroy_devmapping(dm))) return rc; if (dm->src_type == dmsrc_loopback) { if ((rc = loopback_stop(dm))) return rc; } else if (dm->src_type == dmsrc_partition) { LOGE("partition maps not yet supported"); return -ENOSYS; } return 0; }
int ums_send_status(void) { int rc; #if DEBUG_UMS LOG_VOL("ums_send_status():"); #endif rc = send_msg(ums_enabled_get() ? VOLD_EVT_UMS_ENABLED : VOLD_EVT_UMS_DISABLED); if (rc < 0) return rc; rc = send_msg(ums_hostconnected_get() ? VOLD_EVT_UMS_CONNECTED : VOLD_EVT_UMS_DISCONNECTED); return rc; }
/* * Called when a volume is sucessfully unmounted for UMS enable */ static void _cb_volstopped_for_ums_enable(volume_t *v, void *arg) { int rc; char *devdir_path; #if DEBUG_VOLMGR LOG_VOL("_cb_volstopped_for_ums_enable(%s):", v->mount_point); #endif devdir_path = blkdev_get_devpath(v->dev->disk); if ((rc = ums_enable(devdir_path, v->ums_path)) < 0) { free(devdir_path); LOGE("Error enabling ums (%d)", rc); return; } free(devdir_path); volume_setstate(v, volstate_ums); pthread_mutex_unlock(&v->lock); }
static int handle_mmc_event(struct uevent *event) { if (event->action == action_add) { media_t *media; char serial[80]; char *type; /* * Pull card information from sysfs */ type = get_uevent_param(event, "MMC_TYPE"); if (strcmp(type, "SD") && strcmp(type, "MMC")) return 0; read_sysfs_var(serial, sizeof(serial), event->path, "serial"); if (!(media = media_create(event->path, get_uevent_param(event, "MMC_NAME"), serial, media_mmc))) { LOGE("Unable to allocate new media (%s)", strerror(errno)); return -1; } LOGI("New MMC card '%s' (serial %u) added @ %s", media->name, media->serial, media->devpath); } else if (event->action == action_remove) { media_t *media; if (!(media = media_lookup_by_path(event->path, false))) { LOGE("Unable to lookup media '%s'", event->path); return -1; } LOGI("MMC card '%s' (serial %u) @ %s removed", media->name, media->serial, media->devpath); media_destroy(media); } else { #if DEBUG_UEVENT LOG_VOL("No handler implemented for action %d", event->action); #endif } return 0; }
static int loopback_stop(struct devmapping *dm) { char devname[255]; int device_fd; int rc = 0; LOG_VOL("loopback_stop():"); device_fd = open(dm->type_data.loop.loop_dev, O_RDONLY); if (device_fd < 0) { LOG_ERROR("Failed to open loop (%d)", errno); return -errno; } if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) { LOG_ERROR("Failed to destroy loop (%d)", errno); rc = -errno; } close(device_fd); return rc; }
static int mmc_bootstrap_controller(char *sysfs_path) { DIR *d; struct dirent *de; #if DEBUG_BOOTSTRAP LOG_VOL("bootstrap_controller(%s):", sysfs_path); #endif if (!(d = opendir(sysfs_path))) { LOG_ERROR("Unable to open '%s' (%s)", sysfs_path, strerror(errno)); return -errno; } while ((de = readdir(d))) { char tmp[255]; if (de->d_name[0] == '.') continue; if ((!strcmp(de->d_name, "uevent")) || (!strcmp(de->d_name, "subsystem")) || (!strcmp(de->d_name, "device")) || (!strcmp(de->d_name, "power")) || (!strcmp(de->d_name, "slot_name"))) { continue; } sprintf(tmp, "%s/%s", sysfs_path, de->d_name); if (mmc_bootstrap_card(tmp) < 0) LOG_ERROR("Error bootstrapping card '%s' (%s)", tmp, strerror(errno)); } // while closedir(d); return 0; }
// vol->lock must be held! static int _volmgr_consider_disk_and_vol(volume_t *vol, blkdev_t *dev) { int rc = 0; #if DEBUG_VOLMGR LOG_VOL("volmgr_consider_disk_and_vol(%s, %d:%d):", vol->mount_point, dev->major, dev->minor); #endif if (vol->state == volstate_unknown || vol->state == volstate_mounted || vol->state == volstate_mounted_ro) { LOGE("Cannot consider volume '%s' because it is in state '%d", vol->mount_point, vol->state); return -EADDRINUSE; } if (vol->state == volstate_formatting) { LOG_VOL("Evaluating dev '%s' for formattable filesystems for '%s'", dev->devpath, vol->mount_point); /* * Since we only support creating 1 partition (right now), * we can just lookup the target by devno */ blkdev_t *part; if (vol->media_type == media_mmc) part = blkdev_lookup_by_devno(dev->major, ALIGN_MMC_MINOR(dev->minor) + 1); else part = blkdev_lookup_by_devno(dev->major, 1); if (!part) { if (vol->media_type == media_mmc) part = blkdev_lookup_by_devno(dev->major, ALIGN_MMC_MINOR(dev->minor)); else part = blkdev_lookup_by_devno(dev->major, 0); if (!part) { LOGE("Unable to find device to format"); return -ENODEV; } } if ((rc = format_partition(part, vol->media_type == media_devmapper ? FORMAT_TYPE_EXT2 : FORMAT_TYPE_FAT32)) < 0) { LOGE("format failed (%d)", rc); return rc; } } LOGI("Evaluating dev '%s' for mountable filesystems for '%s'", dev->devpath, vol->mount_point); if (dev->nr_parts == 0) { rc = _volmgr_start(vol, dev); #if DEBUG_VOLMGR LOG_VOL("_volmgr_start(%s, %d:%d) rc = %d", vol->mount_point, dev->major, dev->minor, rc); #endif } else { /* * Device has multiple partitions * This is where interesting partition policies could be implemented. * For now just try them in sequence until one succeeds */ rc = -ENODEV; int i; for (i = 0; i < dev->nr_parts; i++) { blkdev_t *part; if (vol->media_type == media_mmc) part = blkdev_lookup_by_devno(dev->major, ALIGN_MMC_MINOR(dev->minor) + (i+1)); else part = blkdev_lookup_by_devno(dev->major, (i+1)); if (!part) { LOGE("Error - unable to lookup partition for blkdev %d:%d", dev->major, dev->minor); continue; } rc = _volmgr_start(vol, part); #if DEBUG_VOLMGR LOG_VOL("_volmgr_start(%s, %d:%d) rc = %d", vol->mount_point, part->major, part->minor, rc); #endif if (!rc || rc == -EBUSY) break; } if (rc == -ENODEV) { // Assert to make sure each partition had a backing blkdev LOGE("Internal consistency error"); return 0; } } if (rc == -ENODATA) { LOGE("Device %d:%d contains no usable filesystems", dev->major, dev->minor); rc = 0; } return rc; }