Esempio n. 1
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;
}
static int handle_block_event(struct uevent *event)
{
    char mediapath[255];
    media_t *media;
    int n;
    int maj, min;
    blkdev_t *blkdev;

    /*
     * Look for backing media for this block device
     */
    if (!strncmp(get_uevent_param(event, "DEVPATH"),
                 "/devices/virtual/",
                 strlen("/devices/virtual/"))) {
        n = 0;
    } else if (!strcmp(get_uevent_param(event, "DEVTYPE"), "disk"))
        n = 2;
    else if (!strcmp(get_uevent_param(event, "DEVTYPE"), "partition"))
        n = 3;
    else {
        LOGE("Bad blockdev type '%s'", get_uevent_param(event, "DEVTYPE"));
        return -EINVAL;
    }

    truncate_sysfs_path(event->path, n, mediapath, sizeof(mediapath));

    if (!(media = media_lookup_by_path(mediapath, false))) {
#if DEBUG_UEVENT
        LOG_VOL("No backend media found @ device path '%s'", mediapath);
#endif
        return 0;
    }

    maj = atoi(get_uevent_param(event, "MAJOR"));
    min = atoi(get_uevent_param(event, "MINOR"));

    if (event->action == action_add) {
        blkdev_t *disk;

        /*
         * If there isn't a disk already its because *we*
         * are the disk
         */
        if (media->media_type == media_mmc)
            disk = blkdev_lookup_by_devno(maj, ALIGN_MMC_MINOR(min));
        else
            disk = blkdev_lookup_by_devno(maj, 0);

        if (!(blkdev = blkdev_create(disk,
                                     event->path,
                                     maj,
                                     min,
                                     media,
                                     get_uevent_param(event, "DEVTYPE")))) {
            LOGE("Unable to allocate new blkdev (%s)", strerror(errno));
            return -1;
        }

        blkdev_refresh(blkdev);

        /*
         * Add the blkdev to media
         */
        int rc;
        if ((rc = media_add_blkdev(media, blkdev)) < 0) {
            LOGE("Unable to add blkdev to card (%d)", rc);
            return rc;
        }

        LOGI("New blkdev %d.%d on media %s, media path %s, Dpp %d",
                blkdev->major, blkdev->minor, media->name, mediapath,
                blkdev_get_num_pending_partitions(blkdev->disk));

        if (blkdev_get_num_pending_partitions(blkdev->disk) == 0) {
            if ((rc = volmgr_consider_disk(blkdev->disk)) < 0) {
                if (rc == -EBUSY) {
                    LOGI("Volmgr not ready to handle device");
                } else {
                    LOGE("Volmgr failed to handle device (%d)", rc);
                    return rc;
                }
            }
        }
    } else if (event->action == action_remove) {
        if (!(blkdev = blkdev_lookup_by_devno(maj, min)))
            return 0;

        LOGI("Destroying blkdev %d.%d @ %s on media %s", blkdev->major,
                blkdev->minor, blkdev->devpath, media->name);
        volmgr_notify_eject(blkdev, _cb_blkdev_ok_to_destroy);

    } else if (event->action == action_change) {
        if (!(blkdev = blkdev_lookup_by_devno(maj, min)))
            return 0;

        LOGI("Modified blkdev %d.%d @ %s on media %s", blkdev->major,
                blkdev->minor, blkdev->devpath, media->name);
        
        blkdev_refresh(blkdev);
    } else  {
#if DEBUG_UEVENT
        LOG_VOL("No handler implemented for action %d", event->action);
#endif
    }
    return 0;
}