// 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; }