--- /dev/null
+What:          /sys/dev
+Date:          April 2008
+KernelVersion: 2.6.26
+Contact:       Dan Williams <dan.j.williams@intel.com>
+Description:   The /sys/dev tree provides a method to look up the sysfs
+               path for a device using the information returned from
+               stat(2).  There are two directories, 'block' and 'char',
+               beneath /sys/dev containing symbolic links with names of
+               the form "<major>:<minor>".  These links point to the
+               corresponding sysfs path for the given device.
+
+               Example:
+               $ readlink /sys/dev/block/8:32
+               ../../block/sdc
+
+               Entries in /sys/dev/char and /sys/dev/block will be
+               dynamically created and destroyed as devices enter and
+               leave the system.
+
+Users:         mdadm <linux-raid@vger.kernel.org>
 
 
 int (*platform_notify)(struct device *dev) = NULL;
 int (*platform_notify_remove)(struct device *dev) = NULL;
+static struct kobject *dev_kobj;
+struct kobject *sysfs_dev_char_kobj;
+struct kobject *sysfs_dev_block_kobj;
 
 #ifdef CONFIG_BLOCK
 static inline int device_is_not_partition(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(dev_set_name);
 
+/**
+ * device_to_dev_kobj - select a /sys/dev/ directory for the device
+ * @dev: device
+ *
+ * By default we select char/ for new entries.  Setting class->dev_obj
+ * to NULL prevents an entry from being created.  class->dev_kobj must
+ * be set (or cleared) before any devices are registered to the class
+ * otherwise device_create_sys_dev_entry() and
+ * device_remove_sys_dev_entry() will disagree about the the presence
+ * of the link.
+ */
+static struct kobject *device_to_dev_kobj(struct device *dev)
+{
+       struct kobject *kobj;
+
+       if (dev->class)
+               kobj = dev->class->dev_kobj;
+       else
+               kobj = sysfs_dev_char_kobj;
+
+       return kobj;
+}
+
+static int device_create_sys_dev_entry(struct device *dev)
+{
+       struct kobject *kobj = device_to_dev_kobj(dev);
+       int error = 0;
+       char devt_str[15];
+
+       if (kobj) {
+               format_dev_t(devt_str, dev->devt);
+               error = sysfs_create_link(kobj, &dev->kobj, devt_str);
+       }
+
+       return error;
+}
+
+static void device_remove_sys_dev_entry(struct device *dev)
+{
+       struct kobject *kobj = device_to_dev_kobj(dev);
+       char devt_str[15];
+
+       if (kobj) {
+               format_dev_t(devt_str, dev->devt);
+               sysfs_remove_link(kobj, devt_str);
+       }
+}
+
 /**
  * device_add - add device to device hierarchy.
  * @dev: device.
                error = device_create_file(dev, &devt_attr);
                if (error)
                        goto ueventattrError;
+
+               error = device_create_sys_dev_entry(dev);
+               if (error)
+                       goto devtattrError;
        }
 
        error = device_add_class_symlinks(dev);
  AttrsError:
        device_remove_class_symlinks(dev);
  SymlinkError:
+       if (MAJOR(dev->devt))
+               device_remove_sys_dev_entry(dev);
+ devtattrError:
        if (MAJOR(dev->devt))
                device_remove_file(dev, &devt_attr);
  ueventattrError:
        device_pm_remove(dev);
        if (parent)
                klist_del(&dev->knode_parent);
-       if (MAJOR(dev->devt))
+       if (MAJOR(dev->devt)) {
+               device_remove_sys_dev_entry(dev);
                device_remove_file(dev, &devt_attr);
+       }
        if (dev->class) {
                device_remove_class_symlinks(dev);
 
        devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
        if (!devices_kset)
                return -ENOMEM;
+       dev_kobj = kobject_create_and_add("dev", NULL);
+       if (!dev_kobj)
+               goto dev_kobj_err;
+       sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
+       if (!sysfs_dev_block_kobj)
+               goto block_kobj_err;
+       sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
+       if (!sysfs_dev_char_kobj)
+               goto char_kobj_err;
+
        return 0;
+
+ char_kobj_err:
+       kobject_put(sysfs_dev_block_kobj);
+ block_kobj_err:
+       kobject_put(dev_kobj);
+ dev_kobj_err:
+       kset_unregister(devices_kset);
+       return -ENOMEM;
 }
 
 EXPORT_SYMBOL_GPL(device_for_each_child);
                        dev->driver->shutdown(dev);
                }
        }
+       kobject_put(sysfs_dev_char_kobj);
+       kobject_put(sysfs_dev_block_kobj);
+       kobject_put(dev_kobj);
 }
 
        struct semaphore        sem; /* locks children, devices, interfaces */
        struct class_attribute          *class_attrs;
        struct device_attribute         *dev_attrs;
+       struct kobject                  *dev_kobj;
 
        int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
 
        struct pm_ops *pm;
 };
 
+extern struct kobject *sysfs_dev_block_kobj;
+extern struct kobject *sysfs_dev_char_kobj;
 extern int __must_check class_register(struct class *class);
 extern void class_unregister(struct class *class);
 extern int class_for_each_device(struct class *class, void *data,