/**ltl * 功能: 将目标设备加入到列表中 * 参数: t ->映射表 * ti ->映射目标 * path ->映射目标<major:minor> * start-> 映射目标相对低层设备的起始偏移量(类似磁盘分区的起始地址) * len -> 此目标设备在dm设备的长度 * mode -> rw * result-> 底层设备对象 * 返回值: * 说明: */ static int __table_get_device(struct dm_table *t, struct dm_target *ti, const char *path, sector_t start, sector_t len, int mode, struct dm_dev **result) { int r; dev_t dev; struct dm_dev *dd; unsigned int major, minor; BUG_ON(!t); /* 获取主设备号和次设备号 */ if (sscanf(path, "%u:%u", &major, &minor) == 2) { /* Extract the major/minor numbers */ dev = MKDEV(major, minor); if (MAJOR(dev) != major || MINOR(dev) != minor) return -EOVERFLOW; } else { /* convert the path to a device */ if ((r = lookup_device(path, &dev))) /* 根据设备路径/dev/sdb获取<major:minor> */ return r; } /* 在列表中查找映射目标 */ dd = find_device(&t->devices, dev); if (!dd) { dd = kmalloc(sizeof(*dd), GFP_KERNEL); if (!dd) return -ENOMEM; dd->mode = mode; dd->bdev = NULL; /* 打开设备 */ if ((r = open_dev(dd, dev, t->md))) { kfree(dd); return r; } format_dev_t(dd->name, dev); /* 主设备号次设备号 */ atomic_set(&dd->count, 0); /* 将目标设备插入到映射表中 */ list_add(&dd->list, &t->devices); } else if (dd->mode != (mode | dd->mode)) { r = upgrade_mode(dd, mode, t->md); if (r) return r; } atomic_inc(&dd->count); /* 检查区域是否超过设备 */ if (!check_device_area(dd, start, len)) { DMWARN("device %s too small for target", path); dm_put_device(ti, dd); return -EINVAL; } *result = dd; return 0; }
/* * Add a device to the list, or just increment the usage count if * it's already present. */ static int __table_get_device(struct dm_table *t, struct dm_target *ti, const char *path, sector_t start, sector_t len, int mode, struct dm_dev **result) { int r; dev_t dev; struct dm_dev *dd; unsigned int major, minor; if (!t) BUG(); if (sscanf(path, "%u:%u", &major, &minor) == 2) { /* Extract the major/minor numbers */ dev = MKDEV(major, minor); if (MAJOR(dev) != major || MINOR(dev) != minor) return -EOVERFLOW; } else { /* convert the path to a device */ if ((r = lookup_device(path, &dev))) return r; } dd = find_device(&t->devices, dev); if (!dd) { dd = kmalloc(sizeof(*dd), GFP_KERNEL); if (!dd) return -ENOMEM; dd->mode = mode; dd->bdev = NULL; if ((r = open_dev(dd, dev))) { kfree(dd); return r; } atomic_set(&dd->count, 0); list_add(&dd->list, &t->devices); } else if (dd->mode != (mode | dd->mode)) { r = upgrade_mode(dd, mode); if (r) return r; } atomic_inc(&dd->count); if (!check_device_area(dd, start, len)) { DMWARN("device %s too small for target", path); dm_put_device(ti, dd); return -EINVAL; } *result = dd; return 0; }