lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 24 Jan 2008 23:33:07 -0800
From:	Greg Kroah-Hartman <gregkh@...e.de>
To:	linux-kernel@...r.kernel.org
Cc:	Kay Sievers <kay.sievers@...y.org>,
	Greg Kroah-Hartman <gregkh@...e.de>
Subject: [PATCH 158/196] Driver core: convert block from raw kobjects to core devices

From: Kay Sievers <kay.sievers@...y.org>

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@...y.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@...e.de>
---
 block/genhd.c              |  416 +++++++++++++++++++-------------------------
 block/ll_rw_blk.c          |    4 +-
 drivers/base/class.c       |    7 +
 drivers/base/core.c        |   20 ++-
 drivers/block/aoe/aoeblk.c |   51 +++---
 drivers/block/nbd.c        |   15 +-
 drivers/ide/ide-probe.c    |    2 +-
 drivers/md/dm.c            |    4 +-
 drivers/md/md.c            |    8 +-
 fs/block_dev.c             |    8 +-
 fs/partitions/check.c      |  315 +++++++++++----------------------
 include/linux/genhd.h      |   37 +++--
 init/do_mounts.c           |  108 +-----------
 13 files changed, 385 insertions(+), 610 deletions(-)

diff --git a/block/genhd.c b/block/genhd.c
index 69aa738..5e4ab4b 100644
--- a/block/genhd.c
+++ b/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;
+	return sprintf(buf, "%d\n",
+		       (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0));
 }
 
-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)
+static ssize_t disk_size_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
-	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",
-		       (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0));
+	struct gendisk *disk = dev_to_disk(dev);
 
+	return sprintf(buf, "%llu\n", (unsigned long long)get_capacity(disk));
 }
-static ssize_t disk_size_read(struct gendisk * disk, char *page)
-{
-	return sprintf(page, "%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);
+
+	return sprintf(buf, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0);
+}
 
-static ssize_t disk_fail_store(struct gendisk * disk,
+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 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 kobject * kobj)
+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);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 8b91994..3887b2a 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -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);
 	}
 }
diff --git a/drivers/base/class.c b/drivers/base/class.c
index ba6745b..624b331 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -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);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 13cae18..06e8738 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -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);
 }
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index ad00b3d..826d123 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -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
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index b4c0888..ba9b17e 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -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;
 }
 
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 2994523..0cb3d2b 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -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)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 88c0fd6..f2d24eb 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -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)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c503086..f79efb3 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -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;
 }
 
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 993f78c..e48a630 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -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;
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 9184215..97f3f5f 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -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_uevent_store(struct hd_struct * p,
-				 const char *page, size_t count)
+static ssize_t part_size_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
-	kobject_uevent(&p->kobj, KOBJ_ADD);
-	return count;
+	struct hd_struct *p = dev_to_part(dev);
+	return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects);
 }
-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)
+
+static ssize_t part_stat_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
-	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 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
+static struct device_attribute dev_attr_fail =
+	__ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
 #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 struct attribute *part_attrs[] = {
+	&dev_attr_start.attr,
+	&dev_attr_size.attr,
+	&dev_attr_stat.attr,
 #ifdef CONFIG_FAIL_MAKE_REQUEST
-	&part_attr_fail.attr,
+	&dev_attr_fail.attr,
 #endif
-	NULL,
+	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);
+		err = sysfs_create_file(&p->dev.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_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);
 }
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index a47b802..1dbea0a 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -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
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 4efa1e5..2ae5b84 100644
--- a/init/do_mounts.c
+++ b/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);
+fail:
+	return 0;
 done:
-#ifdef CONFIG_SYSFS
-	sys_umount("/sys", 0);
-out:
-	if (!mkdir_err)
-		sys_rmdir("/sys");
-#endif
 	return res;
-fail:
-	res = 0;
-	goto done;
 }
 
 static int __init root_dev_setup(char *line)
-- 
1.5.3.8

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ