Driver core: convert block from raw kobjects to core devices
This moves the block devices to /sys/class/block. It will create a flat list of all block devices, with the disks and partitions in one directory. For compatibility /sys/block is created and contains symlinks to the disks. /sys/class/block |-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1 |-- sda10 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10 |-- sda5 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5 |-- sda6 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6 |-- sda7 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7 |-- sda8 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8 |-- sda9 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9 `-- sr0 -> ../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0 /sys/block/ |-- sda -> ../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda `-- sr0 -> ../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0 Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
09f82ea928
Коммит
edfaa7c365
418
block/genhd.c
418
block/genhd.c
|
@ -17,9 +17,10 @@
|
|||
#include <linux/buffer_head.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
struct kset *block_kset;
|
||||
static struct kset_uevent_ops block_uevent_ops;
|
||||
static DEFINE_MUTEX(block_subsys_lock);
|
||||
static DEFINE_MUTEX(block_class_lock);
|
||||
#ifndef CONFIG_SYSFS_DEPRECATED
|
||||
struct kobject *block_depr;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Can be deleted altogether. Later.
|
||||
|
@ -38,19 +39,17 @@ static inline int major_to_index(int major)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
void blkdev_show(struct seq_file *f, off_t offset)
|
||||
{
|
||||
struct blk_major_name *dp;
|
||||
|
||||
if (offset < BLKDEV_MAJOR_HASH_SIZE) {
|
||||
mutex_lock(&block_subsys_lock);
|
||||
mutex_lock(&block_class_lock);
|
||||
for (dp = major_names[offset]; dp; dp = dp->next)
|
||||
seq_printf(f, "%3d %s\n", dp->major, dp->name);
|
||||
mutex_unlock(&block_subsys_lock);
|
||||
mutex_unlock(&block_class_lock);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
int register_blkdev(unsigned int major, const char *name)
|
||||
|
@ -58,7 +57,7 @@ int register_blkdev(unsigned int major, const char *name)
|
|||
struct blk_major_name **n, *p;
|
||||
int index, ret = 0;
|
||||
|
||||
mutex_lock(&block_subsys_lock);
|
||||
mutex_lock(&block_class_lock);
|
||||
|
||||
/* temporary */
|
||||
if (major == 0) {
|
||||
|
@ -103,7 +102,7 @@ int register_blkdev(unsigned int major, const char *name)
|
|||
kfree(p);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&block_subsys_lock);
|
||||
mutex_unlock(&block_class_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -115,7 +114,7 @@ void unregister_blkdev(unsigned int major, const char *name)
|
|||
struct blk_major_name *p = NULL;
|
||||
int index = major_to_index(major);
|
||||
|
||||
mutex_lock(&block_subsys_lock);
|
||||
mutex_lock(&block_class_lock);
|
||||
for (n = &major_names[index]; *n; n = &(*n)->next)
|
||||
if ((*n)->major == major)
|
||||
break;
|
||||
|
@ -125,7 +124,7 @@ void unregister_blkdev(unsigned int major, const char *name)
|
|||
p = *n;
|
||||
*n = p->next;
|
||||
}
|
||||
mutex_unlock(&block_subsys_lock);
|
||||
mutex_unlock(&block_class_lock);
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
|
@ -138,29 +137,30 @@ static struct kobj_map *bdev_map;
|
|||
* range must be nonzero
|
||||
* The hash chain is sorted on range, so that subranges can override.
|
||||
*/
|
||||
void blk_register_region(dev_t dev, unsigned long range, struct module *module,
|
||||
void blk_register_region(dev_t devt, unsigned long range, struct module *module,
|
||||
struct kobject *(*probe)(dev_t, int *, void *),
|
||||
int (*lock)(dev_t, void *), void *data)
|
||||
{
|
||||
kobj_map(bdev_map, dev, range, module, probe, lock, data);
|
||||
kobj_map(bdev_map, devt, range, module, probe, lock, data);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(blk_register_region);
|
||||
|
||||
void blk_unregister_region(dev_t dev, unsigned long range)
|
||||
void blk_unregister_region(dev_t devt, unsigned long range)
|
||||
{
|
||||
kobj_unmap(bdev_map, dev, range);
|
||||
kobj_unmap(bdev_map, devt, range);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(blk_unregister_region);
|
||||
|
||||
static struct kobject *exact_match(dev_t dev, int *part, void *data)
|
||||
static struct kobject *exact_match(dev_t devt, int *part, void *data)
|
||||
{
|
||||
struct gendisk *p = data;
|
||||
return &p->kobj;
|
||||
|
||||
return &p->dev.kobj;
|
||||
}
|
||||
|
||||
static int exact_lock(dev_t dev, void *data)
|
||||
static int exact_lock(dev_t devt, void *data)
|
||||
{
|
||||
struct gendisk *p = data;
|
||||
|
||||
|
@ -195,8 +195,6 @@ void unlink_gendisk(struct gendisk *disk)
|
|||
disk->minors);
|
||||
}
|
||||
|
||||
#define to_disk(obj) container_of(obj,struct gendisk,kobj)
|
||||
|
||||
/**
|
||||
* get_gendisk - get partitioning information for a given device
|
||||
* @dev: device to get partitioning information for
|
||||
|
@ -204,10 +202,12 @@ void unlink_gendisk(struct gendisk *disk)
|
|||
* This function gets the structure containing partitioning
|
||||
* information for the given device @dev.
|
||||
*/
|
||||
struct gendisk *get_gendisk(dev_t dev, int *part)
|
||||
struct gendisk *get_gendisk(dev_t devt, int *part)
|
||||
{
|
||||
struct kobject *kobj = kobj_lookup(bdev_map, dev, part);
|
||||
return kobj ? to_disk(kobj) : NULL;
|
||||
struct kobject *kobj = kobj_lookup(bdev_map, devt, part);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
|
||||
return kobj ? dev_to_disk(dev) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -217,13 +217,17 @@ struct gendisk *get_gendisk(dev_t dev, int *part)
|
|||
*/
|
||||
void __init printk_all_partitions(void)
|
||||
{
|
||||
int n;
|
||||
struct device *dev;
|
||||
struct gendisk *sgp;
|
||||
char buf[BDEVNAME_SIZE];
|
||||
int n;
|
||||
|
||||
mutex_lock(&block_subsys_lock);
|
||||
mutex_lock(&block_class_lock);
|
||||
/* For each block device... */
|
||||
list_for_each_entry(sgp, &block_kset->list, kobj.entry) {
|
||||
char buf[BDEVNAME_SIZE];
|
||||
list_for_each_entry(dev, &block_class.devices, node) {
|
||||
if (dev->type != &disk_type)
|
||||
continue;
|
||||
sgp = dev_to_disk(dev);
|
||||
/*
|
||||
* Don't show empty devices or things that have been surpressed
|
||||
*/
|
||||
|
@ -256,38 +260,46 @@ void __init printk_all_partitions(void)
|
|||
sgp->major, n + 1 + sgp->first_minor,
|
||||
(unsigned long long)sgp->part[n]->nr_sects >> 1,
|
||||
disk_name(sgp, n + 1, buf));
|
||||
} /* partition subloop */
|
||||
} /* Block device loop */
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&block_subsys_lock);
|
||||
return;
|
||||
mutex_unlock(&block_class_lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
/* iterator */
|
||||
static void *part_start(struct seq_file *part, loff_t *pos)
|
||||
{
|
||||
struct list_head *p;
|
||||
loff_t l = *pos;
|
||||
loff_t k = *pos;
|
||||
struct device *dev;
|
||||
|
||||
mutex_lock(&block_subsys_lock);
|
||||
list_for_each(p, &block_kset->list)
|
||||
if (!l--)
|
||||
return list_entry(p, struct gendisk, kobj.entry);
|
||||
mutex_lock(&block_class_lock);
|
||||
list_for_each_entry(dev, &block_class.devices, node) {
|
||||
if (dev->type != &disk_type)
|
||||
continue;
|
||||
if (!k--)
|
||||
return dev_to_disk(dev);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *part_next(struct seq_file *part, void *v, loff_t *pos)
|
||||
{
|
||||
struct list_head *p = ((struct gendisk *)v)->kobj.entry.next;
|
||||
struct gendisk *gp = v;
|
||||
struct device *dev;
|
||||
++*pos;
|
||||
return p==&block_kset->list ? NULL :
|
||||
list_entry(p, struct gendisk, kobj.entry);
|
||||
list_for_each_entry(dev, &gp->dev.node, node) {
|
||||
if (&dev->node == &block_class.devices)
|
||||
return NULL;
|
||||
if (dev->type == &disk_type)
|
||||
return dev_to_disk(dev);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void part_stop(struct seq_file *part, void *v)
|
||||
{
|
||||
mutex_unlock(&block_subsys_lock);
|
||||
mutex_unlock(&block_class_lock);
|
||||
}
|
||||
|
||||
static int show_partition(struct seq_file *part, void *v)
|
||||
|
@ -296,7 +308,7 @@ static int show_partition(struct seq_file *part, void *v)
|
|||
int n;
|
||||
char buf[BDEVNAME_SIZE];
|
||||
|
||||
if (&sgp->kobj.entry == block_kset->list.next)
|
||||
if (&sgp->dev.node == block_class.devices.next)
|
||||
seq_puts(part, "major minor #blocks name\n\n");
|
||||
|
||||
/* Don't show non-partitionable removeable devices or empty devices */
|
||||
|
@ -326,109 +338,81 @@ static int show_partition(struct seq_file *part, void *v)
|
|||
}
|
||||
|
||||
struct seq_operations partitions_op = {
|
||||
.start =part_start,
|
||||
.next = part_next,
|
||||
.stop = part_stop,
|
||||
.show = show_partition
|
||||
.start = part_start,
|
||||
.next = part_next,
|
||||
.stop = part_stop,
|
||||
.show = show_partition
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
extern int blk_dev_init(void);
|
||||
|
||||
static struct kobject *base_probe(dev_t dev, int *part, void *data)
|
||||
static struct kobject *base_probe(dev_t devt, int *part, void *data)
|
||||
{
|
||||
if (request_module("block-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0)
|
||||
if (request_module("block-major-%d-%d", MAJOR(devt), MINOR(devt)) > 0)
|
||||
/* Make old-style 2.4 aliases work */
|
||||
request_module("block-major-%d", MAJOR(dev));
|
||||
request_module("block-major-%d", MAJOR(devt));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __init genhd_device_init(void)
|
||||
{
|
||||
bdev_map = kobj_map_init(base_probe, &block_subsys_lock);
|
||||
class_register(&block_class);
|
||||
bdev_map = kobj_map_init(base_probe, &block_class_lock);
|
||||
blk_dev_init();
|
||||
block_kset = kset_create_and_add("block", &block_uevent_ops, NULL);
|
||||
if (!block_kset) {
|
||||
printk(KERN_WARNING "%s: kset_create error\n", __FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SYSFS_DEPRECATED
|
||||
/* create top-level block dir */
|
||||
block_depr = kobject_create_and_add("block", NULL);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(genhd_device_init);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* kobject & sysfs bindings for block devices
|
||||
*/
|
||||
static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *page)
|
||||
static ssize_t disk_range_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct gendisk *disk = to_disk(kobj);
|
||||
struct disk_attribute *disk_attr =
|
||||
container_of(attr,struct disk_attribute,attr);
|
||||
ssize_t ret = -EIO;
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
|
||||
if (disk_attr->show)
|
||||
ret = disk_attr->show(disk,page);
|
||||
return ret;
|
||||
return sprintf(buf, "%d\n", disk->minors);
|
||||
}
|
||||
|
||||
static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * attr,
|
||||
const char *page, size_t count)
|
||||
static ssize_t disk_removable_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct gendisk *disk = to_disk(kobj);
|
||||
struct disk_attribute *disk_attr =
|
||||
container_of(attr,struct disk_attribute,attr);
|
||||
ssize_t ret = 0;
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
|
||||
if (disk_attr->store)
|
||||
ret = disk_attr->store(disk, page, count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sysfs_ops disk_sysfs_ops = {
|
||||
.show = &disk_attr_show,
|
||||
.store = &disk_attr_store,
|
||||
};
|
||||
|
||||
static ssize_t disk_uevent_store(struct gendisk * disk,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
kobject_uevent(&disk->kobj, KOBJ_ADD);
|
||||
return count;
|
||||
}
|
||||
static ssize_t disk_dev_read(struct gendisk * disk, char *page)
|
||||
{
|
||||
dev_t base = MKDEV(disk->major, disk->first_minor);
|
||||
return print_dev_t(page, base);
|
||||
}
|
||||
static ssize_t disk_range_read(struct gendisk * disk, char *page)
|
||||
{
|
||||
return sprintf(page, "%d\n", disk->minors);
|
||||
}
|
||||
static ssize_t disk_removable_read(struct gendisk * disk, char *page)
|
||||
{
|
||||
return sprintf(page, "%d\n",
|
||||
return sprintf(buf, "%d\n",
|
||||
(disk->flags & GENHD_FL_REMOVABLE ? 1 : 0));
|
||||
}
|
||||
|
||||
}
|
||||
static ssize_t disk_size_read(struct gendisk * disk, char *page)
|
||||
static ssize_t disk_size_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk));
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
|
||||
return sprintf(buf, "%llu\n", (unsigned long long)get_capacity(disk));
|
||||
}
|
||||
static ssize_t disk_capability_read(struct gendisk *disk, char *page)
|
||||
|
||||
static ssize_t disk_capability_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(page, "%x\n", disk->flags);
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
|
||||
return sprintf(buf, "%x\n", disk->flags);
|
||||
}
|
||||
static ssize_t disk_stats_read(struct gendisk * disk, char *page)
|
||||
|
||||
static ssize_t disk_stat_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
|
||||
preempt_disable();
|
||||
disk_round_stats(disk);
|
||||
preempt_enable();
|
||||
return sprintf(page,
|
||||
return sprintf(buf,
|
||||
"%8lu %8lu %8llu %8u "
|
||||
"%8lu %8lu %8llu %8u "
|
||||
"%8u %8u %8u"
|
||||
|
@ -445,40 +429,21 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page)
|
|||
jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
|
||||
jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
|
||||
}
|
||||
static struct disk_attribute disk_attr_uevent = {
|
||||
.attr = {.name = "uevent", .mode = S_IWUSR },
|
||||
.store = disk_uevent_store
|
||||
};
|
||||
static struct disk_attribute disk_attr_dev = {
|
||||
.attr = {.name = "dev", .mode = S_IRUGO },
|
||||
.show = disk_dev_read
|
||||
};
|
||||
static struct disk_attribute disk_attr_range = {
|
||||
.attr = {.name = "range", .mode = S_IRUGO },
|
||||
.show = disk_range_read
|
||||
};
|
||||
static struct disk_attribute disk_attr_removable = {
|
||||
.attr = {.name = "removable", .mode = S_IRUGO },
|
||||
.show = disk_removable_read
|
||||
};
|
||||
static struct disk_attribute disk_attr_size = {
|
||||
.attr = {.name = "size", .mode = S_IRUGO },
|
||||
.show = disk_size_read
|
||||
};
|
||||
static struct disk_attribute disk_attr_capability = {
|
||||
.attr = {.name = "capability", .mode = S_IRUGO },
|
||||
.show = disk_capability_read
|
||||
};
|
||||
static struct disk_attribute disk_attr_stat = {
|
||||
.attr = {.name = "stat", .mode = S_IRUGO },
|
||||
.show = disk_stats_read
|
||||
};
|
||||
|
||||
#ifdef CONFIG_FAIL_MAKE_REQUEST
|
||||
static ssize_t disk_fail_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
|
||||
static ssize_t disk_fail_store(struct gendisk * disk,
|
||||
return sprintf(buf, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0);
|
||||
}
|
||||
|
||||
static ssize_t disk_fail_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
int i;
|
||||
|
||||
if (count > 0 && sscanf(buf, "%d", &i) > 0) {
|
||||
|
@ -490,134 +455,100 @@ static ssize_t disk_fail_store(struct gendisk * disk,
|
|||
|
||||
return count;
|
||||
}
|
||||
static ssize_t disk_fail_read(struct gendisk * disk, char *page)
|
||||
{
|
||||
return sprintf(page, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0);
|
||||
}
|
||||
static struct disk_attribute disk_attr_fail = {
|
||||
.attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR },
|
||||
.store = disk_fail_store,
|
||||
.show = disk_fail_read
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static struct attribute * default_attrs[] = {
|
||||
&disk_attr_uevent.attr,
|
||||
&disk_attr_dev.attr,
|
||||
&disk_attr_range.attr,
|
||||
&disk_attr_removable.attr,
|
||||
&disk_attr_size.attr,
|
||||
&disk_attr_stat.attr,
|
||||
&disk_attr_capability.attr,
|
||||
static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL);
|
||||
static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL);
|
||||
static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL);
|
||||
static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL);
|
||||
static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL);
|
||||
#ifdef CONFIG_FAIL_MAKE_REQUEST
|
||||
&disk_attr_fail.attr,
|
||||
static struct device_attribute dev_attr_fail =
|
||||
__ATTR(make-it-fail, S_IRUGO|S_IWUSR, disk_fail_show, disk_fail_store);
|
||||
#endif
|
||||
NULL,
|
||||
|
||||
static struct attribute *disk_attrs[] = {
|
||||
&dev_attr_range.attr,
|
||||
&dev_attr_removable.attr,
|
||||
&dev_attr_size.attr,
|
||||
&dev_attr_capability.attr,
|
||||
&dev_attr_stat.attr,
|
||||
#ifdef CONFIG_FAIL_MAKE_REQUEST
|
||||
&dev_attr_fail.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static void disk_release(struct kobject * kobj)
|
||||
static struct attribute_group disk_attr_group = {
|
||||
.attrs = disk_attrs,
|
||||
};
|
||||
|
||||
static struct attribute_group *disk_attr_groups[] = {
|
||||
&disk_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void disk_release(struct device *dev)
|
||||
{
|
||||
struct gendisk *disk = to_disk(kobj);
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
|
||||
kfree(disk->random);
|
||||
kfree(disk->part);
|
||||
free_disk_stats(disk);
|
||||
kfree(disk);
|
||||
}
|
||||
|
||||
static struct kobj_type ktype_block = {
|
||||
.release = disk_release,
|
||||
.sysfs_ops = &disk_sysfs_ops,
|
||||
.default_attrs = default_attrs,
|
||||
struct class block_class = {
|
||||
.name = "block",
|
||||
};
|
||||
|
||||
extern struct kobj_type ktype_part;
|
||||
|
||||
static int block_uevent_filter(struct kset *kset, struct kobject *kobj)
|
||||
{
|
||||
struct kobj_type *ktype = get_ktype(kobj);
|
||||
|
||||
return ((ktype == &ktype_block) || (ktype == &ktype_part));
|
||||
}
|
||||
|
||||
static int block_uevent(struct kset *kset, struct kobject *kobj,
|
||||
struct kobj_uevent_env *env)
|
||||
{
|
||||
struct kobj_type *ktype = get_ktype(kobj);
|
||||
struct device *physdev;
|
||||
struct gendisk *disk;
|
||||
struct hd_struct *part;
|
||||
|
||||
if (ktype == &ktype_block) {
|
||||
disk = container_of(kobj, struct gendisk, kobj);
|
||||
add_uevent_var(env, "MINOR=%u", disk->first_minor);
|
||||
} else if (ktype == &ktype_part) {
|
||||
disk = container_of(kobj->parent, struct gendisk, kobj);
|
||||
part = container_of(kobj, struct hd_struct, kobj);
|
||||
add_uevent_var(env, "MINOR=%u",
|
||||
disk->first_minor + part->partno);
|
||||
} else
|
||||
return 0;
|
||||
|
||||
add_uevent_var(env, "MAJOR=%u", disk->major);
|
||||
|
||||
/* add physical device, backing this device */
|
||||
physdev = disk->driverfs_dev;
|
||||
if (physdev) {
|
||||
char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
|
||||
|
||||
add_uevent_var(env, "PHYSDEVPATH=%s", path);
|
||||
kfree(path);
|
||||
|
||||
if (physdev->bus)
|
||||
add_uevent_var(env, "PHYSDEVBUS=%s", physdev->bus->name);
|
||||
|
||||
if (physdev->driver)
|
||||
add_uevent_var(env, physdev->driver->name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct kset_uevent_ops block_uevent_ops = {
|
||||
.filter = block_uevent_filter,
|
||||
.uevent = block_uevent,
|
||||
struct device_type disk_type = {
|
||||
.name = "disk",
|
||||
.groups = disk_attr_groups,
|
||||
.release = disk_release,
|
||||
};
|
||||
|
||||
/*
|
||||
* aggregate disk stat collector. Uses the same stats that the sysfs
|
||||
* entries do, above, but makes them available through one seq_file.
|
||||
* Watching a few disks may be efficient through sysfs, but watching
|
||||
* all of them will be more efficient through this interface.
|
||||
*
|
||||
* The output looks suspiciously like /proc/partitions with a bunch of
|
||||
* extra fields.
|
||||
*/
|
||||
|
||||
/* iterator */
|
||||
static void *diskstats_start(struct seq_file *part, loff_t *pos)
|
||||
{
|
||||
loff_t k = *pos;
|
||||
struct list_head *p;
|
||||
struct device *dev;
|
||||
|
||||
mutex_lock(&block_subsys_lock);
|
||||
list_for_each(p, &block_kset->list)
|
||||
mutex_lock(&block_class_lock);
|
||||
list_for_each_entry(dev, &block_class.devices, node) {
|
||||
if (dev->type != &disk_type)
|
||||
continue;
|
||||
if (!k--)
|
||||
return list_entry(p, struct gendisk, kobj.entry);
|
||||
return dev_to_disk(dev);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos)
|
||||
{
|
||||
struct list_head *p = ((struct gendisk *)v)->kobj.entry.next;
|
||||
struct gendisk *gp = v;
|
||||
struct device *dev;
|
||||
|
||||
++*pos;
|
||||
return p==&block_kset->list ? NULL :
|
||||
list_entry(p, struct gendisk, kobj.entry);
|
||||
list_for_each_entry(dev, &gp->dev.node, node) {
|
||||
if (&dev->node == &block_class.devices)
|
||||
return NULL;
|
||||
if (dev->type == &disk_type)
|
||||
return dev_to_disk(dev);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void diskstats_stop(struct seq_file *part, void *v)
|
||||
{
|
||||
mutex_unlock(&block_subsys_lock);
|
||||
mutex_unlock(&block_class_lock);
|
||||
}
|
||||
|
||||
static int diskstats_show(struct seq_file *s, void *v)
|
||||
|
@ -627,7 +558,7 @@ static int diskstats_show(struct seq_file *s, void *v)
|
|||
int n = 0;
|
||||
|
||||
/*
|
||||
if (&sgp->kobj.entry == block_kset->list.next)
|
||||
if (&gp->dev.kobj.entry == block_class.devices.next)
|
||||
seq_puts(s, "major minor name"
|
||||
" rio rmerge rsect ruse wio wmerge "
|
||||
"wsect wuse running use aveq"
|
||||
|
@ -681,7 +612,7 @@ static void media_change_notify_thread(struct work_struct *work)
|
|||
* set enviroment vars to indicate which event this is for
|
||||
* so that user space will know to go check the media status.
|
||||
*/
|
||||
kobject_uevent_env(&gd->kobj, KOBJ_CHANGE, envp);
|
||||
kobject_uevent_env(&gd->dev.kobj, KOBJ_CHANGE, envp);
|
||||
put_device(gd->driverfs_dev);
|
||||
}
|
||||
|
||||
|
@ -692,6 +623,25 @@ void genhd_media_change_notify(struct gendisk *disk)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(genhd_media_change_notify);
|
||||
|
||||
dev_t blk_lookup_devt(const char *name)
|
||||
{
|
||||
struct device *dev;
|
||||
dev_t devt = MKDEV(0, 0);
|
||||
|
||||
mutex_lock(&block_class_lock);
|
||||
list_for_each_entry(dev, &block_class.devices, node) {
|
||||
if (strcmp(dev->bus_id, name) == 0) {
|
||||
devt = dev->devt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&block_class_lock);
|
||||
|
||||
return devt;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(blk_lookup_devt);
|
||||
|
||||
struct gendisk *alloc_disk(int minors)
|
||||
{
|
||||
return alloc_disk_node(minors, -1);
|
||||
|
@ -719,10 +669,10 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
|
|||
}
|
||||
}
|
||||
disk->minors = minors;
|
||||
disk->kobj.kset = block_kset;
|
||||
disk->kobj.ktype = &ktype_block;
|
||||
kobject_init(&disk->kobj);
|
||||
rand_initialize_disk(disk);
|
||||
disk->dev.class = &block_class;
|
||||
disk->dev.type = &disk_type;
|
||||
device_initialize(&disk->dev);
|
||||
INIT_WORK(&disk->async_notify,
|
||||
media_change_notify_thread);
|
||||
}
|
||||
|
@ -742,7 +692,7 @@ struct kobject *get_disk(struct gendisk *disk)
|
|||
owner = disk->fops->owner;
|
||||
if (owner && !try_module_get(owner))
|
||||
return NULL;
|
||||
kobj = kobject_get(&disk->kobj);
|
||||
kobj = kobject_get(&disk->dev.kobj);
|
||||
if (kobj == NULL) {
|
||||
module_put(owner);
|
||||
return NULL;
|
||||
|
@ -756,7 +706,7 @@ EXPORT_SYMBOL(get_disk);
|
|||
void put_disk(struct gendisk *disk)
|
||||
{
|
||||
if (disk)
|
||||
kobject_put(&disk->kobj);
|
||||
kobject_put(&disk->dev.kobj);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(put_disk);
|
||||
|
|
|
@ -4182,7 +4182,7 @@ int blk_register_queue(struct gendisk *disk)
|
|||
if (!q || !q->request_fn)
|
||||
return -ENXIO;
|
||||
|
||||
q->kobj.parent = kobject_get(&disk->kobj);
|
||||
q->kobj.parent = kobject_get(&disk->dev.kobj);
|
||||
|
||||
ret = kobject_add(&q->kobj);
|
||||
if (ret < 0)
|
||||
|
@ -4209,6 +4209,6 @@ void blk_unregister_queue(struct gendisk *disk)
|
|||
|
||||
kobject_uevent(&q->kobj, KOBJ_REMOVE);
|
||||
kobject_del(&q->kobj);
|
||||
kobject_put(&disk->kobj);
|
||||
kobject_put(&disk->dev.kobj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/kdev_t.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/genhd.h>
|
||||
#include "base.h"
|
||||
|
||||
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
|
||||
|
@ -149,7 +150,13 @@ int class_register(struct class * cls)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
/* let the block class directory show up in the root of sysfs */
|
||||
if (cls != &block_class)
|
||||
cls->subsys.kobj.kset = class_kset;
|
||||
#else
|
||||
cls->subsys.kobj.kset = class_kset;
|
||||
#endif
|
||||
cls->subsys.kobj.ktype = &class_ktype;
|
||||
|
||||
error = kset_register(&cls->subsys);
|
||||
|
|
|
@ -671,14 +671,15 @@ static int device_add_class_symlinks(struct device *dev)
|
|||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
/* stacked class devices need a symlink in the class directory */
|
||||
if (dev->kobj.parent != &dev->class->subsys.kobj) {
|
||||
if (dev->kobj.parent != &dev->class->subsys.kobj &&
|
||||
dev->type != &part_type) {
|
||||
error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
|
||||
dev->bus_id);
|
||||
if (error)
|
||||
goto out_subsys;
|
||||
}
|
||||
|
||||
if (dev->parent) {
|
||||
if (dev->parent && dev->type != &part_type) {
|
||||
struct device *parent = dev->parent;
|
||||
char *class_name;
|
||||
|
||||
|
@ -707,10 +708,11 @@ static int device_add_class_symlinks(struct device *dev)
|
|||
return 0;
|
||||
|
||||
out_device:
|
||||
if (dev->parent)
|
||||
if (dev->parent && dev->type != &part_type)
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
out_busid:
|
||||
if (dev->kobj.parent != &dev->class->subsys.kobj)
|
||||
if (dev->kobj.parent != &dev->class->subsys.kobj &&
|
||||
dev->type != &part_type)
|
||||
sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
|
||||
#else
|
||||
/* link in the class directory pointing to the device */
|
||||
|
@ -719,7 +721,7 @@ out_busid:
|
|||
if (error)
|
||||
goto out_subsys;
|
||||
|
||||
if (dev->parent) {
|
||||
if (dev->parent && dev->type != &part_type) {
|
||||
error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
|
||||
"device");
|
||||
if (error)
|
||||
|
@ -743,7 +745,7 @@ static void device_remove_class_symlinks(struct device *dev)
|
|||
return;
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if (dev->parent) {
|
||||
if (dev->parent && dev->type != &part_type) {
|
||||
char *class_name;
|
||||
|
||||
class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
|
@ -754,10 +756,11 @@ static void device_remove_class_symlinks(struct device *dev)
|
|||
sysfs_remove_link(&dev->kobj, "device");
|
||||
}
|
||||
|
||||
if (dev->kobj.parent != &dev->class->subsys.kobj)
|
||||
if (dev->kobj.parent != &dev->class->subsys.kobj &&
|
||||
dev->type != &part_type)
|
||||
sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
|
||||
#else
|
||||
if (dev->parent)
|
||||
if (dev->parent && dev->type != &part_type)
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
|
||||
sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
|
||||
|
@ -925,6 +928,7 @@ struct device * get_device(struct device * dev)
|
|||
*/
|
||||
void put_device(struct device * dev)
|
||||
{
|
||||
/* might_sleep(); */
|
||||
if (dev)
|
||||
kobject_put(&dev->kobj);
|
||||
}
|
||||
|
|
|
@ -15,8 +15,10 @@
|
|||
|
||||
static struct kmem_cache *buf_pool_cache;
|
||||
|
||||
static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
|
||||
static ssize_t aoedisk_show_state(struct device *dev,
|
||||
struct device_attribute *attr, char *page)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
struct aoedev *d = disk->private_data;
|
||||
|
||||
return snprintf(page, PAGE_SIZE,
|
||||
|
@ -26,50 +28,47 @@ static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
|
|||
(d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : "");
|
||||
/* I'd rather see nopen exported so we can ditch closewait */
|
||||
}
|
||||
static ssize_t aoedisk_show_mac(struct gendisk * disk, char *page)
|
||||
static ssize_t aoedisk_show_mac(struct device *dev,
|
||||
struct device_attribute *attr, char *page)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
struct aoedev *d = disk->private_data;
|
||||
|
||||
return snprintf(page, PAGE_SIZE, "%012llx\n",
|
||||
(unsigned long long)mac_addr(d->addr));
|
||||
}
|
||||
static ssize_t aoedisk_show_netif(struct gendisk * disk, char *page)
|
||||
static ssize_t aoedisk_show_netif(struct device *dev,
|
||||
struct device_attribute *attr, char *page)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
struct aoedev *d = disk->private_data;
|
||||
|
||||
return snprintf(page, PAGE_SIZE, "%s\n", d->ifp->name);
|
||||
}
|
||||
/* firmware version */
|
||||
static ssize_t aoedisk_show_fwver(struct gendisk * disk, char *page)
|
||||
static ssize_t aoedisk_show_fwver(struct device *dev,
|
||||
struct device_attribute *attr, char *page)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
struct aoedev *d = disk->private_data;
|
||||
|
||||
return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver);
|
||||
}
|
||||
|
||||
static struct disk_attribute disk_attr_state = {
|
||||
.attr = {.name = "state", .mode = S_IRUGO },
|
||||
.show = aoedisk_show_state
|
||||
};
|
||||
static struct disk_attribute disk_attr_mac = {
|
||||
.attr = {.name = "mac", .mode = S_IRUGO },
|
||||
.show = aoedisk_show_mac
|
||||
};
|
||||
static struct disk_attribute disk_attr_netif = {
|
||||
.attr = {.name = "netif", .mode = S_IRUGO },
|
||||
.show = aoedisk_show_netif
|
||||
};
|
||||
static struct disk_attribute disk_attr_fwver = {
|
||||
.attr = {.name = "firmware-version", .mode = S_IRUGO },
|
||||
.show = aoedisk_show_fwver
|
||||
static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL);
|
||||
static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL);
|
||||
static DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL);
|
||||
static struct device_attribute dev_attr_firmware_version = {
|
||||
.attr = { .name = "firmware-version", .mode = S_IRUGO, .owner = THIS_MODULE },
|
||||
.show = aoedisk_show_fwver,
|
||||
};
|
||||
|
||||
static struct attribute *aoe_attrs[] = {
|
||||
&disk_attr_state.attr,
|
||||
&disk_attr_mac.attr,
|
||||
&disk_attr_netif.attr,
|
||||
&disk_attr_fwver.attr,
|
||||
NULL
|
||||
&dev_attr_state.attr,
|
||||
&dev_attr_mac.attr,
|
||||
&dev_attr_netif.attr,
|
||||
&dev_attr_firmware_version.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group attr_group = {
|
||||
|
@ -79,12 +78,12 @@ static const struct attribute_group attr_group = {
|
|||
static int
|
||||
aoedisk_add_sysfs(struct aoedev *d)
|
||||
{
|
||||
return sysfs_create_group(&d->gd->kobj, &attr_group);
|
||||
return sysfs_create_group(&d->gd->dev.kobj, &attr_group);
|
||||
}
|
||||
void
|
||||
aoedisk_rm_sysfs(struct aoedev *d)
|
||||
{
|
||||
sysfs_remove_group(&d->gd->kobj, &attr_group);
|
||||
sysfs_remove_group(&d->gd->dev.kobj, &attr_group);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -375,14 +375,17 @@ harderror:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static ssize_t pid_show(struct gendisk *disk, char *page)
|
||||
static ssize_t pid_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(page, "%ld\n",
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
|
||||
return sprintf(buf, "%ld\n",
|
||||
(long) ((struct nbd_device *)disk->private_data)->pid);
|
||||
}
|
||||
|
||||
static struct disk_attribute pid_attr = {
|
||||
.attr = { .name = "pid", .mode = S_IRUGO },
|
||||
static struct device_attribute pid_attr = {
|
||||
.attr = { .name = "pid", .mode = S_IRUGO, .owner = THIS_MODULE },
|
||||
.show = pid_show,
|
||||
};
|
||||
|
||||
|
@ -394,7 +397,7 @@ static int nbd_do_it(struct nbd_device *lo)
|
|||
BUG_ON(lo->magic != LO_MAGIC);
|
||||
|
||||
lo->pid = current->pid;
|
||||
ret = sysfs_create_file(&lo->disk->kobj, &pid_attr.attr);
|
||||
ret = sysfs_create_file(&lo->disk->dev.kobj, &pid_attr.attr);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "nbd: sysfs_create_file failed!");
|
||||
return ret;
|
||||
|
@ -403,7 +406,7 @@ static int nbd_do_it(struct nbd_device *lo)
|
|||
while ((req = nbd_read_stat(lo)) != NULL)
|
||||
nbd_end_request(req);
|
||||
|
||||
sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr);
|
||||
sysfs_remove_file(&lo->disk->dev.kobj, &pid_attr.attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1173,7 +1173,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data)
|
|||
{
|
||||
struct gendisk *p = data;
|
||||
*part &= (1 << PARTN_BITS) - 1;
|
||||
return &p->kobj;
|
||||
return &p->dev.kobj;
|
||||
}
|
||||
|
||||
static int exact_lock(dev_t dev, void *data)
|
||||
|
|
|
@ -1109,7 +1109,7 @@ static void event_callback(void *context)
|
|||
list_splice_init(&md->uevent_list, &uevents);
|
||||
spin_unlock_irqrestore(&md->uevent_lock, flags);
|
||||
|
||||
dm_send_uevents(&uevents, &md->disk->kobj);
|
||||
dm_send_uevents(&uevents, &md->disk->dev.kobj);
|
||||
|
||||
atomic_inc(&md->event_nr);
|
||||
wake_up(&md->eventq);
|
||||
|
@ -1530,7 +1530,7 @@ out:
|
|||
*---------------------------------------------------------------*/
|
||||
void dm_kobject_uevent(struct mapped_device *md)
|
||||
{
|
||||
kobject_uevent(&md->disk->kobj, KOBJ_CHANGE);
|
||||
kobject_uevent(&md->disk->dev.kobj, KOBJ_CHANGE);
|
||||
}
|
||||
|
||||
uint32_t dm_next_uevent_seq(struct mapped_device *md)
|
||||
|
|
|
@ -1396,9 +1396,9 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
|
|||
goto fail;
|
||||
|
||||
if (rdev->bdev->bd_part)
|
||||
ko = &rdev->bdev->bd_part->kobj;
|
||||
ko = &rdev->bdev->bd_part->dev.kobj;
|
||||
else
|
||||
ko = &rdev->bdev->bd_disk->kobj;
|
||||
ko = &rdev->bdev->bd_disk->dev.kobj;
|
||||
if ((err = sysfs_create_link(&rdev->kobj, ko, "block"))) {
|
||||
kobject_del(&rdev->kobj);
|
||||
goto fail;
|
||||
|
@ -3083,7 +3083,7 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
|
|||
add_disk(disk);
|
||||
mddev->gendisk = disk;
|
||||
mutex_unlock(&disks_mutex);
|
||||
error = kobject_init_and_add(&mddev->kobj, &md_ktype, &disk->kobj,
|
||||
error = kobject_init_and_add(&mddev->kobj, &md_ktype, &disk->dev.kobj,
|
||||
"%s", "md");
|
||||
if (error)
|
||||
printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
|
||||
|
@ -3361,7 +3361,7 @@ static int do_md_run(mddev_t * mddev)
|
|||
|
||||
mddev->changed = 1;
|
||||
md_new_event(mddev);
|
||||
kobject_uevent(&mddev->gendisk->kobj, KOBJ_CHANGE);
|
||||
kobject_uevent(&mddev->gendisk->dev.kobj, KOBJ_CHANGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -738,9 +738,9 @@ EXPORT_SYMBOL(bd_release);
|
|||
static struct kobject *bdev_get_kobj(struct block_device *bdev)
|
||||
{
|
||||
if (bdev->bd_contains != bdev)
|
||||
return kobject_get(&bdev->bd_part->kobj);
|
||||
return kobject_get(&bdev->bd_part->dev.kobj);
|
||||
else
|
||||
return kobject_get(&bdev->bd_disk->kobj);
|
||||
return kobject_get(&bdev->bd_disk->dev.kobj);
|
||||
}
|
||||
|
||||
static struct kobject *bdev_get_holder(struct block_device *bdev)
|
||||
|
@ -1176,7 +1176,7 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part)
|
|||
ret = -ENXIO;
|
||||
goto out_first;
|
||||
}
|
||||
kobject_get(&p->kobj);
|
||||
kobject_get(&p->dev.kobj);
|
||||
bdev->bd_part = p;
|
||||
bd_set_size(bdev, (loff_t) p->nr_sects << 9);
|
||||
}
|
||||
|
@ -1299,7 +1299,7 @@ static int __blkdev_put(struct block_device *bdev, int for_part)
|
|||
module_put(owner);
|
||||
|
||||
if (bdev->bd_contains != bdev) {
|
||||
kobject_put(&bdev->bd_part->kobj);
|
||||
kobject_put(&bdev->bd_part->dev.kobj);
|
||||
bdev->bd_part = NULL;
|
||||
}
|
||||
bdev->bd_disk = NULL;
|
||||
|
|
|
@ -195,96 +195,45 @@ check_partition(struct gendisk *hd, struct block_device *bdev)
|
|||
return ERR_PTR(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* sysfs bindings for partitions
|
||||
*/
|
||||
|
||||
struct part_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct hd_struct *,char *);
|
||||
ssize_t (*store)(struct hd_struct *,const char *, size_t);
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
part_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
|
||||
static ssize_t part_start_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hd_struct * p = container_of(kobj,struct hd_struct,kobj);
|
||||
struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr);
|
||||
ssize_t ret = 0;
|
||||
if (part_attr->show)
|
||||
ret = part_attr->show(p, page);
|
||||
return ret;
|
||||
}
|
||||
static ssize_t
|
||||
part_attr_store(struct kobject * kobj, struct attribute * attr,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct hd_struct * p = container_of(kobj,struct hd_struct,kobj);
|
||||
struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr);
|
||||
ssize_t ret = 0;
|
||||
struct hd_struct *p = dev_to_part(dev);
|
||||
|
||||
if (part_attr->store)
|
||||
ret = part_attr->store(p, page, count);
|
||||
return ret;
|
||||
return sprintf(buf, "%llu\n",(unsigned long long)p->start_sect);
|
||||
}
|
||||
|
||||
static struct sysfs_ops part_sysfs_ops = {
|
||||
.show = part_attr_show,
|
||||
.store = part_attr_store,
|
||||
};
|
||||
static ssize_t part_size_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hd_struct *p = dev_to_part(dev);
|
||||
return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects);
|
||||
}
|
||||
|
||||
static ssize_t part_uevent_store(struct hd_struct * p,
|
||||
const char *page, size_t count)
|
||||
static ssize_t part_stat_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
kobject_uevent(&p->kobj, KOBJ_ADD);
|
||||
return count;
|
||||
}
|
||||
static ssize_t part_dev_read(struct hd_struct * p, char *page)
|
||||
{
|
||||
struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj);
|
||||
dev_t dev = MKDEV(disk->major, disk->first_minor + p->partno);
|
||||
return print_dev_t(page, dev);
|
||||
}
|
||||
static ssize_t part_start_read(struct hd_struct * p, char *page)
|
||||
{
|
||||
return sprintf(page, "%llu\n",(unsigned long long)p->start_sect);
|
||||
}
|
||||
static ssize_t part_size_read(struct hd_struct * p, char *page)
|
||||
{
|
||||
return sprintf(page, "%llu\n",(unsigned long long)p->nr_sects);
|
||||
}
|
||||
static ssize_t part_stat_read(struct hd_struct * p, char *page)
|
||||
{
|
||||
return sprintf(page, "%8u %8llu %8u %8llu\n",
|
||||
struct hd_struct *p = dev_to_part(dev);
|
||||
|
||||
return sprintf(buf, "%8u %8llu %8u %8llu\n",
|
||||
p->ios[0], (unsigned long long)p->sectors[0],
|
||||
p->ios[1], (unsigned long long)p->sectors[1]);
|
||||
}
|
||||
static struct part_attribute part_attr_uevent = {
|
||||
.attr = {.name = "uevent", .mode = S_IWUSR },
|
||||
.store = part_uevent_store
|
||||
};
|
||||
static struct part_attribute part_attr_dev = {
|
||||
.attr = {.name = "dev", .mode = S_IRUGO },
|
||||
.show = part_dev_read
|
||||
};
|
||||
static struct part_attribute part_attr_start = {
|
||||
.attr = {.name = "start", .mode = S_IRUGO },
|
||||
.show = part_start_read
|
||||
};
|
||||
static struct part_attribute part_attr_size = {
|
||||
.attr = {.name = "size", .mode = S_IRUGO },
|
||||
.show = part_size_read
|
||||
};
|
||||
static struct part_attribute part_attr_stat = {
|
||||
.attr = {.name = "stat", .mode = S_IRUGO },
|
||||
.show = part_stat_read
|
||||
};
|
||||
|
||||
#ifdef CONFIG_FAIL_MAKE_REQUEST
|
||||
static ssize_t part_fail_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hd_struct *p = dev_to_part(dev);
|
||||
|
||||
static ssize_t part_fail_store(struct hd_struct * p,
|
||||
return sprintf(buf, "%d\n", p->make_it_fail);
|
||||
}
|
||||
|
||||
static ssize_t part_fail_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct hd_struct *p = dev_to_part(dev);
|
||||
int i;
|
||||
|
||||
if (count > 0 && sscanf(buf, "%d", &i) > 0)
|
||||
|
@ -292,49 +241,52 @@ static ssize_t part_fail_store(struct hd_struct * p,
|
|||
|
||||
return count;
|
||||
}
|
||||
static ssize_t part_fail_read(struct hd_struct * p, char *page)
|
||||
{
|
||||
return sprintf(page, "%d\n", p->make_it_fail);
|
||||
}
|
||||
static struct part_attribute part_attr_fail = {
|
||||
.attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR },
|
||||
.store = part_fail_store,
|
||||
.show = part_fail_read
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static struct attribute * default_attrs[] = {
|
||||
&part_attr_uevent.attr,
|
||||
&part_attr_dev.attr,
|
||||
&part_attr_start.attr,
|
||||
&part_attr_size.attr,
|
||||
&part_attr_stat.attr,
|
||||
static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL);
|
||||
static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
|
||||
static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL);
|
||||
#ifdef CONFIG_FAIL_MAKE_REQUEST
|
||||
&part_attr_fail.attr,
|
||||
static struct device_attribute dev_attr_fail =
|
||||
__ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
|
||||
#endif
|
||||
NULL,
|
||||
|
||||
static struct attribute *part_attrs[] = {
|
||||
&dev_attr_start.attr,
|
||||
&dev_attr_size.attr,
|
||||
&dev_attr_stat.attr,
|
||||
#ifdef CONFIG_FAIL_MAKE_REQUEST
|
||||
&dev_attr_fail.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
extern struct kset *block_kset;
|
||||
static struct attribute_group part_attr_group = {
|
||||
.attrs = part_attrs,
|
||||
};
|
||||
|
||||
static void part_release(struct kobject *kobj)
|
||||
static struct attribute_group *part_attr_groups[] = {
|
||||
&part_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void part_release(struct device *dev)
|
||||
{
|
||||
struct hd_struct * p = container_of(kobj,struct hd_struct,kobj);
|
||||
struct hd_struct *p = dev_to_part(dev);
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
struct kobj_type ktype_part = {
|
||||
struct device_type part_type = {
|
||||
.name = "partition",
|
||||
.groups = part_attr_groups,
|
||||
.release = part_release,
|
||||
.default_attrs = default_attrs,
|
||||
.sysfs_ops = &part_sysfs_ops,
|
||||
};
|
||||
|
||||
static inline void partition_sysfs_add_subdir(struct hd_struct *p)
|
||||
{
|
||||
struct kobject *k;
|
||||
|
||||
k = kobject_get(&p->kobj);
|
||||
k = kobject_get(&p->dev.kobj);
|
||||
p->holder_dir = kobject_create_and_add("holders", k);
|
||||
kobject_put(k);
|
||||
}
|
||||
|
@ -343,7 +295,7 @@ static inline void disk_sysfs_add_subdirs(struct gendisk *disk)
|
|||
{
|
||||
struct kobject *k;
|
||||
|
||||
k = kobject_get(&disk->kobj);
|
||||
k = kobject_get(&disk->dev.kobj);
|
||||
disk->holder_dir = kobject_create_and_add("holders", k);
|
||||
disk->slave_dir = kobject_create_and_add("slaves", k);
|
||||
kobject_put(k);
|
||||
|
@ -352,6 +304,7 @@ static inline void disk_sysfs_add_subdirs(struct gendisk *disk)
|
|||
void delete_partition(struct gendisk *disk, int part)
|
||||
{
|
||||
struct hd_struct *p = disk->part[part-1];
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
if (!p->nr_sects)
|
||||
|
@ -361,113 +314,55 @@ void delete_partition(struct gendisk *disk, int part)
|
|||
p->nr_sects = 0;
|
||||
p->ios[0] = p->ios[1] = 0;
|
||||
p->sectors[0] = p->sectors[1] = 0;
|
||||
sysfs_remove_link(&p->kobj, "subsystem");
|
||||
kobject_unregister(p->holder_dir);
|
||||
kobject_uevent(&p->kobj, KOBJ_REMOVE);
|
||||
kobject_del(&p->kobj);
|
||||
kobject_put(&p->kobj);
|
||||
device_del(&p->dev);
|
||||
put_device(&p->dev);
|
||||
}
|
||||
|
||||
void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags)
|
||||
{
|
||||
struct hd_struct *p;
|
||||
int err;
|
||||
|
||||
p = kzalloc(sizeof(*p), GFP_KERNEL);
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
|
||||
p->start_sect = start;
|
||||
p->nr_sects = len;
|
||||
p->partno = part;
|
||||
p->policy = disk->policy;
|
||||
|
||||
if (isdigit(disk->kobj.k_name[strlen(disk->kobj.k_name)-1]))
|
||||
kobject_set_name(&p->kobj, "%sp%d",
|
||||
kobject_name(&disk->kobj), part);
|
||||
if (isdigit(disk->dev.bus_id[strlen(disk->dev.bus_id)-1]))
|
||||
snprintf(p->dev.bus_id, BUS_ID_SIZE,
|
||||
"%sp%d", disk->dev.bus_id, part);
|
||||
else
|
||||
kobject_set_name(&p->kobj, "%s%d",
|
||||
kobject_name(&disk->kobj),part);
|
||||
p->kobj.parent = &disk->kobj;
|
||||
p->kobj.ktype = &ktype_part;
|
||||
kobject_init(&p->kobj);
|
||||
kobject_add(&p->kobj);
|
||||
if (!disk->part_uevent_suppress)
|
||||
kobject_uevent(&p->kobj, KOBJ_ADD);
|
||||
sysfs_create_link(&p->kobj, &block_kset->kobj, "subsystem");
|
||||
snprintf(p->dev.bus_id, BUS_ID_SIZE,
|
||||
"%s%d", disk->dev.bus_id, part);
|
||||
|
||||
device_initialize(&p->dev);
|
||||
p->dev.devt = MKDEV(disk->major, disk->first_minor + part);
|
||||
p->dev.class = &block_class;
|
||||
p->dev.type = &part_type;
|
||||
p->dev.parent = &disk->dev;
|
||||
disk->part[part-1] = p;
|
||||
|
||||
/* delay uevent until 'holders' subdir is created */
|
||||
p->dev.uevent_suppress = 1;
|
||||
device_add(&p->dev);
|
||||
partition_sysfs_add_subdir(p);
|
||||
p->dev.uevent_suppress = 0;
|
||||
if (flags & ADDPART_FLAG_WHOLEDISK) {
|
||||
static struct attribute addpartattr = {
|
||||
.name = "whole_disk",
|
||||
.mode = S_IRUSR | S_IRGRP | S_IROTH,
|
||||
};
|
||||
|
||||
sysfs_create_file(&p->kobj, &addpartattr);
|
||||
}
|
||||
partition_sysfs_add_subdir(p);
|
||||
disk->part[part-1] = p;
|
||||
}
|
||||
|
||||
static char *make_block_name(struct gendisk *disk)
|
||||
{
|
||||
char *name;
|
||||
static char *block_str = "block:";
|
||||
int size;
|
||||
char *s;
|
||||
|
||||
size = strlen(block_str) + strlen(disk->disk_name) + 1;
|
||||
name = kmalloc(size, GFP_KERNEL);
|
||||
if (!name)
|
||||
return NULL;
|
||||
strcpy(name, block_str);
|
||||
strcat(name, disk->disk_name);
|
||||
/* ewww... some of these buggers have / in name... */
|
||||
s = strchr(name, '/');
|
||||
if (s)
|
||||
*s = '!';
|
||||
return name;
|
||||
}
|
||||
|
||||
static int disk_sysfs_symlinks(struct gendisk *disk)
|
||||
{
|
||||
struct device *target = get_device(disk->driverfs_dev);
|
||||
int err;
|
||||
char *disk_name = NULL;
|
||||
|
||||
if (target) {
|
||||
disk_name = make_block_name(disk);
|
||||
if (!disk_name) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
err = sysfs_create_link(&disk->kobj, &target->kobj, "device");
|
||||
if (err)
|
||||
goto err_out_disk_name;
|
||||
|
||||
err = sysfs_create_link(&target->kobj, &disk->kobj, disk_name);
|
||||
if (err)
|
||||
goto err_out_dev_link;
|
||||
err = sysfs_create_file(&p->dev.kobj, &addpartattr);
|
||||
}
|
||||
|
||||
err = sysfs_create_link(&disk->kobj, &block_kset->kobj,
|
||||
"subsystem");
|
||||
if (err)
|
||||
goto err_out_disk_name_lnk;
|
||||
|
||||
kfree(disk_name);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_disk_name_lnk:
|
||||
if (target) {
|
||||
sysfs_remove_link(&target->kobj, disk_name);
|
||||
err_out_dev_link:
|
||||
sysfs_remove_link(&disk->kobj, "device");
|
||||
err_out_disk_name:
|
||||
kfree(disk_name);
|
||||
err_out:
|
||||
put_device(target);
|
||||
}
|
||||
return err;
|
||||
/* suppress uevent if the disk supresses it */
|
||||
if (!disk->dev.uevent_suppress)
|
||||
kobject_uevent(&p->dev.kobj, KOBJ_ADD);
|
||||
}
|
||||
|
||||
/* Not exported, helper to add_disk(). */
|
||||
|
@ -479,19 +374,29 @@ void register_disk(struct gendisk *disk)
|
|||
struct hd_struct *p;
|
||||
int err;
|
||||
|
||||
kobject_set_name(&disk->kobj, "%s", disk->disk_name);
|
||||
/* ewww... some of these buggers have / in name... */
|
||||
s = strchr(disk->kobj.k_name, '/');
|
||||
disk->dev.parent = disk->driverfs_dev;
|
||||
disk->dev.devt = MKDEV(disk->major, disk->first_minor);
|
||||
|
||||
strlcpy(disk->dev.bus_id, disk->disk_name, KOBJ_NAME_LEN);
|
||||
/* ewww... some of these buggers have / in the name... */
|
||||
s = strchr(disk->dev.bus_id, '/');
|
||||
if (s)
|
||||
*s = '!';
|
||||
if ((err = kobject_add(&disk->kobj)))
|
||||
|
||||
/* delay uevents, until we scanned partition table */
|
||||
disk->dev.uevent_suppress = 1;
|
||||
|
||||
if (device_add(&disk->dev))
|
||||
return;
|
||||
err = disk_sysfs_symlinks(disk);
|
||||
#ifndef CONFIG_SYSFS_DEPRECATED
|
||||
err = sysfs_create_link(block_depr, &disk->dev.kobj,
|
||||
kobject_name(&disk->dev.kobj));
|
||||
if (err) {
|
||||
kobject_del(&disk->kobj);
|
||||
device_del(&disk->dev);
|
||||
return;
|
||||
}
|
||||
disk_sysfs_add_subdirs(disk);
|
||||
#endif
|
||||
disk_sysfs_add_subdirs(disk);
|
||||
|
||||
/* No minors to use for partitions */
|
||||
if (disk->minors == 1)
|
||||
|
@ -505,25 +410,23 @@ void register_disk(struct gendisk *disk)
|
|||
if (!bdev)
|
||||
goto exit;
|
||||
|
||||
/* scan partition table, but suppress uevents */
|
||||
bdev->bd_invalidated = 1;
|
||||
disk->part_uevent_suppress = 1;
|
||||
err = blkdev_get(bdev, FMODE_READ, 0);
|
||||
disk->part_uevent_suppress = 0;
|
||||
if (err < 0)
|
||||
goto exit;
|
||||
blkdev_put(bdev);
|
||||
|
||||
exit:
|
||||
/* announce disk after possible partitions are already created */
|
||||
kobject_uevent(&disk->kobj, KOBJ_ADD);
|
||||
/* announce disk after possible partitions are created */
|
||||
disk->dev.uevent_suppress = 0;
|
||||
kobject_uevent(&disk->dev.kobj, KOBJ_ADD);
|
||||
|
||||
/* announce possible partitions */
|
||||
for (i = 1; i < disk->minors; i++) {
|
||||
p = disk->part[i-1];
|
||||
if (!p || !p->nr_sects)
|
||||
continue;
|
||||
kobject_uevent(&p->kobj, KOBJ_ADD);
|
||||
kobject_uevent(&p->dev.kobj, KOBJ_ADD);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,19 +505,11 @@ void del_gendisk(struct gendisk *disk)
|
|||
disk_stat_set_all(disk, 0);
|
||||
disk->stamp = 0;
|
||||
|
||||
kobject_uevent(&disk->kobj, KOBJ_REMOVE);
|
||||
kobject_unregister(disk->holder_dir);
|
||||
kobject_unregister(disk->slave_dir);
|
||||
if (disk->driverfs_dev) {
|
||||
char *disk_name = make_block_name(disk);
|
||||
sysfs_remove_link(&disk->kobj, "device");
|
||||
if (disk_name) {
|
||||
sysfs_remove_link(&disk->driverfs_dev->kobj, disk_name);
|
||||
kfree(disk_name);
|
||||
}
|
||||
put_device(disk->driverfs_dev);
|
||||
disk->driverfs_dev = NULL;
|
||||
}
|
||||
sysfs_remove_link(&disk->kobj, "subsystem");
|
||||
kobject_del(&disk->kobj);
|
||||
disk->driverfs_dev = NULL;
|
||||
#ifndef CONFIG_SYSFS_DEPRECATED
|
||||
sysfs_remove_link(block_depr, disk->dev.bus_id);
|
||||
#endif
|
||||
device_del(&disk->dev);
|
||||
}
|
||||
|
|
|
@ -10,9 +10,19 @@
|
|||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/kdev_t.h>
|
||||
|
||||
#ifdef CONFIG_BLOCK
|
||||
|
||||
#define kobj_to_dev(k) container_of(k, struct device, kobj)
|
||||
#define dev_to_disk(device) container_of(device, struct gendisk, dev)
|
||||
#define dev_to_part(device) container_of(device, struct hd_struct, dev)
|
||||
|
||||
extern struct device_type disk_type;
|
||||
extern struct device_type part_type;
|
||||
extern struct kobject *block_depr;
|
||||
extern struct class block_class;
|
||||
|
||||
enum {
|
||||
/* These three have identical behaviour; use the second one if DOS FDISK gets
|
||||
confused about extended/logical partitions starting past cylinder 1023. */
|
||||
|
@ -84,7 +94,7 @@ struct partition {
|
|||
struct hd_struct {
|
||||
sector_t start_sect;
|
||||
sector_t nr_sects;
|
||||
struct kobject kobj;
|
||||
struct device dev;
|
||||
struct kobject *holder_dir;
|
||||
unsigned ios[2], sectors[2]; /* READs and WRITEs */
|
||||
int policy, partno;
|
||||
|
@ -117,15 +127,14 @@ struct gendisk {
|
|||
* disks that can't be partitioned. */
|
||||
char disk_name[32]; /* name of major driver */
|
||||
struct hd_struct **part; /* [indexed by minor] */
|
||||
int part_uevent_suppress;
|
||||
struct block_device_operations *fops;
|
||||
struct request_queue *queue;
|
||||
void *private_data;
|
||||
sector_t capacity;
|
||||
|
||||
int flags;
|
||||
struct device *driverfs_dev;
|
||||
struct kobject kobj;
|
||||
struct device *driverfs_dev; // FIXME: remove
|
||||
struct device dev;
|
||||
struct kobject *holder_dir;
|
||||
struct kobject *slave_dir;
|
||||
|
||||
|
@ -143,13 +152,6 @@ struct gendisk {
|
|||
struct work_struct async_notify;
|
||||
};
|
||||
|
||||
/* Structure for sysfs attributes on block devices */
|
||||
struct disk_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct gendisk *, char *);
|
||||
ssize_t (*store)(struct gendisk *, const char *, size_t);
|
||||
};
|
||||
|
||||
/*
|
||||
* Macros to operate on percpu disk statistics:
|
||||
*
|
||||
|
@ -411,7 +413,8 @@ struct unixware_disklabel {
|
|||
#define ADDPART_FLAG_RAID 1
|
||||
#define ADDPART_FLAG_WHOLEDISK 2
|
||||
|
||||
char *disk_name (struct gendisk *hd, int part, char *buf);
|
||||
extern dev_t blk_lookup_devt(const char *name);
|
||||
extern char *disk_name (struct gendisk *hd, int part, char *buf);
|
||||
|
||||
extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
|
||||
extern void add_partition(struct gendisk *, int, sector_t, sector_t, int);
|
||||
|
@ -423,12 +426,12 @@ extern struct gendisk *alloc_disk(int minors);
|
|||
extern struct kobject *get_disk(struct gendisk *disk);
|
||||
extern void put_disk(struct gendisk *disk);
|
||||
extern void genhd_media_change_notify(struct gendisk *disk);
|
||||
extern void blk_register_region(dev_t dev, unsigned long range,
|
||||
extern void blk_register_region(dev_t devt, unsigned long range,
|
||||
struct module *module,
|
||||
struct kobject *(*probe)(dev_t, int *, void *),
|
||||
int (*lock)(dev_t, void *),
|
||||
void *data);
|
||||
extern void blk_unregister_region(dev_t dev, unsigned long range);
|
||||
extern void blk_unregister_region(dev_t devt, unsigned long range);
|
||||
|
||||
static inline struct block_device *bdget_disk(struct gendisk *disk, int index)
|
||||
{
|
||||
|
@ -441,6 +444,12 @@ static inline struct block_device *bdget_disk(struct gendisk *disk, int index)
|
|||
|
||||
static inline void printk_all_partitions(void) { }
|
||||
|
||||
static inline dev_t blk_lookup_devt(const char *name)
|
||||
{
|
||||
dev_t devt = MKDEV(0, 0);
|
||||
return devt;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BLOCK */
|
||||
|
||||
#endif
|
||||
|
|
110
init/do_mounts.c
110
init/do_mounts.c
|
@ -55,69 +55,6 @@ static int __init readwrite(char *str)
|
|||
__setup("ro", readonly);
|
||||
__setup("rw", readwrite);
|
||||
|
||||
static dev_t try_name(char *name, int part)
|
||||
{
|
||||
char path[64];
|
||||
char buf[32];
|
||||
int range;
|
||||
dev_t res;
|
||||
char *s;
|
||||
int len;
|
||||
int fd;
|
||||
unsigned int maj, min;
|
||||
|
||||
/* read device number from .../dev */
|
||||
|
||||
sprintf(path, "/sys/block/%s/dev", name);
|
||||
fd = sys_open(path, 0, 0);
|
||||
if (fd < 0)
|
||||
goto fail;
|
||||
len = sys_read(fd, buf, 32);
|
||||
sys_close(fd);
|
||||
if (len <= 0 || len == 32 || buf[len - 1] != '\n')
|
||||
goto fail;
|
||||
buf[len - 1] = '\0';
|
||||
if (sscanf(buf, "%u:%u", &maj, &min) == 2) {
|
||||
/*
|
||||
* Try the %u:%u format -- see print_dev_t()
|
||||
*/
|
||||
res = MKDEV(maj, min);
|
||||
if (maj != MAJOR(res) || min != MINOR(res))
|
||||
goto fail;
|
||||
} else {
|
||||
/*
|
||||
* Nope. Try old-style "0321"
|
||||
*/
|
||||
res = new_decode_dev(simple_strtoul(buf, &s, 16));
|
||||
if (*s)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* if it's there and we are not looking for a partition - that's it */
|
||||
if (!part)
|
||||
return res;
|
||||
|
||||
/* otherwise read range from .../range */
|
||||
sprintf(path, "/sys/block/%s/range", name);
|
||||
fd = sys_open(path, 0, 0);
|
||||
if (fd < 0)
|
||||
goto fail;
|
||||
len = sys_read(fd, buf, 32);
|
||||
sys_close(fd);
|
||||
if (len <= 0 || len == 32 || buf[len - 1] != '\n')
|
||||
goto fail;
|
||||
buf[len - 1] = '\0';
|
||||
range = simple_strtoul(buf, &s, 10);
|
||||
if (*s)
|
||||
goto fail;
|
||||
|
||||
/* if partition is within range - we got it */
|
||||
if (part < range)
|
||||
return res + part;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a name into device number. We accept the following variants:
|
||||
*
|
||||
|
@ -129,12 +66,10 @@ fail:
|
|||
* 5) /dev/<disk_name>p<decimal> - same as the above, that form is
|
||||
* used when disk name of partitioned disk ends on a digit.
|
||||
*
|
||||
* If name doesn't have fall into the categories above, we return 0.
|
||||
* Sysfs is used to check if something is a disk name - it has
|
||||
* all known disks under bus/block/devices. If the disk name
|
||||
* contains slashes, name of sysfs node has them replaced with
|
||||
* bangs. try_name() does the actual checks, assuming that sysfs
|
||||
* is mounted on rootfs /sys.
|
||||
* If name doesn't have fall into the categories above, we return (0,0).
|
||||
* block_class is used to check if something is a disk name. If the disk
|
||||
* name contains slashes, the device name has them replaced with
|
||||
* bangs.
|
||||
*/
|
||||
|
||||
dev_t name_to_dev_t(char *name)
|
||||
|
@ -142,13 +77,6 @@ dev_t name_to_dev_t(char *name)
|
|||
char s[32];
|
||||
char *p;
|
||||
dev_t res = 0;
|
||||
int part;
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
int mkdir_err = sys_mkdir("/sys", 0700);
|
||||
if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0)
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
if (strncmp(name, "/dev/", 5) != 0) {
|
||||
unsigned maj, min;
|
||||
|
@ -164,6 +92,7 @@ dev_t name_to_dev_t(char *name)
|
|||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
name += 5;
|
||||
res = Root_NFS;
|
||||
if (strcmp(name, "nfs") == 0)
|
||||
|
@ -178,35 +107,14 @@ dev_t name_to_dev_t(char *name)
|
|||
for (p = s; *p; p++)
|
||||
if (*p == '/')
|
||||
*p = '!';
|
||||
res = try_name(s, 0);
|
||||
res = blk_lookup_devt(s);
|
||||
if (res)
|
||||
goto done;
|
||||
|
||||
while (p > s && isdigit(p[-1]))
|
||||
p--;
|
||||
if (p == s || !*p || *p == '0')
|
||||
goto fail;
|
||||
part = simple_strtoul(p, NULL, 10);
|
||||
*p = '\0';
|
||||
res = try_name(s, part);
|
||||
if (res)
|
||||
goto done;
|
||||
|
||||
if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
|
||||
goto fail;
|
||||
p[-1] = '\0';
|
||||
res = try_name(s, part);
|
||||
done:
|
||||
#ifdef CONFIG_SYSFS
|
||||
sys_umount("/sys", 0);
|
||||
out:
|
||||
if (!mkdir_err)
|
||||
sys_rmdir("/sys");
|
||||
#endif
|
||||
return res;
|
||||
fail:
|
||||
res = 0;
|
||||
goto done;
|
||||
return 0;
|
||||
done:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int __init root_dev_setup(char *line)
|
||||
|
|
Загрузка…
Ссылка в новой задаче