/** * blk_alloc_devt - allocate a dev_t for a partition * @part: partition to allocate dev_t for * @devt: out parameter for resulting dev_t * * Allocate a dev_t for block device. * * RETURNS: * 0 on success, allocated dev_t is returned in *@devt. -errno on * failure. * * CONTEXT: * Might sleep. */ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) { struct gendisk *disk = part_to_disk(part); int idx, rc; /* in consecutive minor range? */ if (part->partno < disk->minors) { *devt = MKDEV(disk->major, disk->first_minor + part->partno); return 0; } /* allocate ext devt */ do { if (!idr_pre_get(&ext_devt_idr, GFP_KERNEL)) return -ENOMEM; rc = idr_get_new(&ext_devt_idr, part, &idx); } while (rc == -EAGAIN); if (rc) return rc; if (idx > MAX_EXT_DEVT) { idr_remove(&ext_devt_idr, idx); return -EBUSY; } *devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx)); return 0; }
/** * devt_from_partuuid - looks up the dev_t of a partition by its UUID * @uuid: min 36 byte char array containing a hex ascii UUID * * The function will return the first partition which contains a matching * UUID value in its partition_meta_info struct. This does not search * by filesystem UUIDs. * * If @uuid is followed by a "/PARTNROFF=%d", then the number will be * extracted and used as an offset from the partition identified by the UUID. * * Returns the matching dev_t on success or 0 on failure. */ static dev_t devt_from_partuuid(char *uuid_str) { dev_t res = 0; struct device *dev = NULL; u8 uuid[16]; struct gendisk *disk; struct hd_struct *part; int offset = 0; if (strlen(uuid_str) < 36) goto done; /* Check for optional partition number offset attributes. */ if (uuid_str[36]) { char c = 0; /* Explicitly fail on poor PARTUUID syntax. */ if (sscanf(&uuid_str[36], "/PARTNROFF=%d%c", &offset, &c) != 1) { printk(KERN_ERR "VFS: PARTUUID= is invalid.\n" "Expected PARTUUID=<valid-uuid-id>[/PARTNROFF=%%d]\n"); if (root_wait) printk(KERN_ERR "Disabling rootwait; root= is invalid.\n"); root_wait = 0; goto done; } } /* Pack the requested UUID in the expected format. */ part_pack_uuid(uuid_str, uuid); dev = class_find_device(&block_class, NULL, uuid, &match_dev_by_uuid); if (!dev) goto done; res = dev->devt; /* Attempt to find the partition by offset. */ if (!offset) goto no_offset; res = 0; disk = part_to_disk(dev_to_part(dev)); part = disk_get_part(disk, dev_to_part(dev)->partno + offset); if (part) { res = part_devt(part); put_device(part_to_dev(part)); } no_offset: put_device(dev); done: return res; }
/** * devt_from_partuuid - looks up the dev_t of a partition by its UUID * @uuid: char array containing ascii UUID * * The function will return the first partition which contains a matching * UUID value in its partition_meta_info struct. This does not search * by filesystem UUIDs. * * If @uuid is followed by a "/PARTNROFF=%d", then the number will be * extracted and used as an offset from the partition identified by the UUID. * * Returns the matching dev_t on success or 0 on failure. */ static dev_t devt_from_partuuid(const char *uuid_str) { dev_t res = 0; struct uuidcmp cmp; struct device *dev = NULL; struct gendisk *disk; struct hd_struct *part; int offset = 0; bool clear_root_wait = false; char *slash; cmp.uuid = uuid_str; slash = strchr(uuid_str, '/'); /* Check for optional partition number offset attributes. */ if (slash) { char c = 0; /* Explicitly fail on poor PARTUUID syntax. */ if (sscanf(slash + 1, "PARTNROFF=%d%c", &offset, &c) != 1) { clear_root_wait = true; goto done; } cmp.len = slash - uuid_str; } else { cmp.len = strlen(uuid_str); } if (!cmp.len) { clear_root_wait = true; goto done; } dev = class_find_device(&block_class, NULL, &cmp, &match_dev_by_uuid); if (!dev) goto done; res = dev->devt; /* Attempt to find the partition by offset. */ if (!offset) goto no_offset; res = 0; disk = part_to_disk(dev_to_part(dev)); part = disk_get_part(disk, dev_to_part(dev)->partno + offset); if (part) { res = part_devt(part); put_device(part_to_dev(part)); } no_offset: put_device(dev); done: if (clear_root_wait) { pr_err("VFS: PARTUUID= is invalid.\n" "Expected PARTUUID=<valid-uuid-id>[/PARTNROFF=%%d]\n"); if (root_wait) pr_err("Disabling rootwait; root= is invalid.\n"); root_wait = 0; } return res; }