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);
}
Beispiel #3
0
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;
    }
}
Beispiel #4
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
}
Beispiel #6
0
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;
}
Beispiel #8
0
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
}
Beispiel #11
0
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);
}
Beispiel #12
0
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;
}
Beispiel #13
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;
}
Beispiel #14
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);
}
Beispiel #15
0
/*
 * 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;
}
Beispiel #16
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;
}
Beispiel #18
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);
}
Beispiel #19
0
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);
}
Beispiel #20
0
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;
}
Beispiel #22
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;
}
Beispiel #25
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;
}
Beispiel #29
0
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;   
}
Beispiel #30
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;
}