static struct subsystem block_subsys;
+static DECLARE_MUTEX(block_subsys_sem);
+
/*
* Can be deleted altogether. Later.
*
- * Modified under both block_subsys.rwsem and major_names_lock.
*/
static struct blk_major_name {
struct blk_major_name *next;
char name[16];
} *major_names[MAX_PROBE_HASH];
-static spinlock_t major_names_lock = SPIN_LOCK_UNLOCKED;
-
/* index in the above - for now: assume no multimajor ranges */
static inline int major_to_index(int major)
{
return major % MAX_PROBE_HASH;
}
+#ifdef CONFIG_PROC_FS
/* get block device names in somewhat random order */
int get_blkdev_list(char *p)
{
len = sprintf(p, "\nBlock devices:\n");
- down_read(&block_subsys.rwsem);
+ down(&block_subsys_sem);
for (i = 0; i < ARRAY_SIZE(major_names); i++) {
for (n = major_names[i]; n; n = n->next)
len += sprintf(p+len, "%3d %s\n",
n->major, n->name);
}
- up_read(&block_subsys.rwsem);
+ up(&block_subsys_sem);
return len;
}
+#endif
int register_blkdev(unsigned int major, const char *name)
{
struct blk_major_name **n, *p;
int index, ret = 0;
- unsigned long flags;
- down_write(&block_subsys.rwsem);
+ down(&block_subsys_sem);
/* temporary */
if (major == 0) {
p->next = NULL;
index = major_to_index(major);
- spin_lock_irqsave(&major_names_lock, flags);
for (n = &major_names[index]; *n; n = &(*n)->next) {
if ((*n)->major == major)
break;
*n = p;
else
ret = -EBUSY;
- spin_unlock_irqrestore(&major_names_lock, flags);
if (ret < 0) {
printk("register_blkdev: cannot get major %d for %s\n",
kfree(p);
}
out:
- up_write(&block_subsys.rwsem);
+ up(&block_subsys_sem);
return ret;
}
struct blk_major_name **n;
struct blk_major_name *p = NULL;
int index = major_to_index(major);
- unsigned long flags;
int ret = 0;
- down_write(&block_subsys.rwsem);
- spin_lock_irqsave(&major_names_lock, flags);
+ down(&block_subsys_sem);
for (n = &major_names[index]; *n; n = &(*n)->next)
if ((*n)->major == major)
break;
p = *n;
*n = p->next;
}
- spin_unlock_irqrestore(&major_names_lock, flags);
- up_write(&block_subsys.rwsem);
+ up(&block_subsys_sem);
kfree(p);
return ret;
struct list_head *p;
loff_t l = *pos;
- down_read(&block_subsys.rwsem);
+ down(&block_subsys_sem);
list_for_each(p, &block_subsys.kset.list)
if (!l--)
return list_entry(p, struct gendisk, kobj.entry);
static void part_stop(struct seq_file *part, void *v)
{
- up_read(&block_subsys.rwsem);
+ up(&block_subsys_sem);
}
static int show_partition(struct seq_file *part, void *v)
return NULL;
}
-int __init device_init(void)
+static int __init genhd_device_init(void)
{
bdev_map = kobj_map_init(base_probe, &block_subsys);
blk_dev_init();
return 0;
}
-subsys_initcall(device_init);
+subsys_initcall(genhd_device_init);
/*
* kobject & sysfs bindings for block devices
*/
-
-struct disk_attribute {
- struct attribute attr;
- ssize_t (*show)(struct gendisk *, char *);
-};
-
static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr,
char *page)
{
return ((ktype == &ktype_block) || (ktype == &ktype_part));
}
+static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+ int num_envp, char *buffer, int buffer_size)
+{
+ struct device *dev = NULL;
+ struct kobj_type *ktype = get_ktype(kobj);
+ int length = 0;
+ int i = 0;
+
+ /* get physical device backing disk or partition */
+ if (ktype == &ktype_block) {
+ struct gendisk *disk = container_of(kobj, struct gendisk, kobj);
+ dev = disk->driverfs_dev;
+ } else if (ktype == &ktype_part) {
+ struct gendisk *disk = container_of(kobj->parent, struct gendisk, kobj);
+ dev = disk->driverfs_dev;
+ }
+
+ if (dev) {
+ /* add physical device, backing this device */
+ char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+
+ add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "PHYSDEVPATH=%s", path);
+ kfree(path);
+
+ /* add bus name of physical device */
+ if (dev->bus)
+ add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVBUS=%s", dev->bus->name);
+
+ /* add driver name of physical device */
+ if (dev->driver)
+ add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVDRIVER=%s", dev->driver->name);
+
+ envp[i] = NULL;
+ }
+
+ return 0;
+}
+
static struct kset_hotplug_ops block_hotplug_ops = {
- .filter = block_hotplug_filter,
+ .filter = block_hotplug_filter,
+ .hotplug = block_hotplug,
};
/* declare block_subsys. */
loff_t k = *pos;
struct list_head *p;
- down_read(&block_subsys.rwsem);
+ down(&block_subsys_sem);
list_for_each(p, &block_subsys.kset.list)
if (!k--)
return list_entry(p, struct gendisk, kobj.entry);
static void diskstats_stop(struct seq_file *part, void *v)
{
- up_read(&block_subsys.rwsem);
+ up(&block_subsys_sem);
}
static int diskstats_show(struct seq_file *s, void *v)
{
int res = 0;
struct block_device *bdev = bdget_disk(disk, index);
- if (bdev)
+ if (bdev) {
res = __invalidate_device(bdev, 1);
- bdput(bdev);
+ bdput(bdev);
+ }
return res;
}