diff -Nuar linux-2.6.23.orig/drivers/base/class.c linux-2.6.23/drivers/base/class.c --- linux-2.6.23.orig/drivers/base/class.c 2007-10-10 05:31:38.000000000 +0900 +++ linux-2.6.23/drivers/base/class.c 2007-10-24 13:58:44.000000000 +0900 @@ -17,6 +17,7 @@ #include #include #include +#include #include "base.h" #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) @@ -615,6 +616,8 @@ error = class_device_create_file(class_dev, &class_devt_attr); if (error) goto out4; + + ndevfs_create(class_dev->class_id, class_dev->devt, 1); } error = class_device_add_attrs(class_dev); @@ -761,8 +764,10 @@ } sysfs_remove_link(&class_dev->kobj, "subsystem"); class_device_remove_file(class_dev, &class_uevent_attr); - if (MAJOR(class_dev->devt)) + if (MAJOR(class_dev->devt)) { class_device_remove_file(class_dev, &class_devt_attr); + ndevfs_remove(class_dev->class_id); + } class_device_remove_attrs(class_dev); class_device_remove_groups(class_dev); diff -Nuar linux-2.6.23.orig/fs/Kconfig linux-2.6.23/fs/Kconfig --- linux-2.6.23.orig/fs/Kconfig 2007-10-22 13:29:48.000000000 +0900 +++ linux-2.6.23/fs/Kconfig 2007-10-24 13:55:25.000000000 +0900 @@ -1025,6 +1025,9 @@ Both sysfs and configfs can and should exist together on the same system. One is not a replacement for the other. +config NDEV_FS + bool "Nano Device File System" + endmenu menu "Layered filesystems" diff -Nuar linux-2.6.23.orig/fs/Makefile linux-2.6.23/fs/Makefile --- linux-2.6.23.orig/fs/Makefile 2007-10-22 13:29:48.000000000 +0900 +++ linux-2.6.23/fs/Makefile 2007-10-24 13:55:25.000000000 +0900 @@ -113,6 +113,7 @@ obj-$(CONFIG_XFS_FS) += xfs/ obj-$(CONFIG_9P_FS) += 9p/ obj-$(CONFIG_AFS_FS) += afs/ +obj-$(CONFIG_NDEV_FS) += ndevfs/ obj-$(CONFIG_BEFS_FS) += befs/ obj-$(CONFIG_HOSTFS) += hostfs/ obj-$(CONFIG_HPPFS) += hppfs/ diff -Nuar linux-2.6.23.orig/fs/ndevfs/Makefile linux-2.6.23/fs/ndevfs/Makefile --- linux-2.6.23.orig/fs/ndevfs/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.23/fs/ndevfs/Makefile 2007-10-24 13:55:25.000000000 +0900 @@ -0,0 +1,4 @@ +ndevfs-objs := inode.o + +obj-$(CONFIG_NDEV_FS) += ndevfs.o + diff -Nuar linux-2.6.23.orig/fs/ndevfs/inode.c linux-2.6.23/fs/ndevfs/inode.c --- linux-2.6.23.orig/fs/ndevfs/inode.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.23/fs/ndevfs/inode.c 2007-10-24 13:55:25.000000000 +0900 @@ -0,0 +1,257 @@ +/* + * inode.c - part of ndevfs, a tiny little device file system + * + * Copyright (C) 2004,2005 Greg Kroah-Hartman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * Written for all of the people out there who just hate userspace solutions. + * + */ + +/* uncomment to get debug messages */ +#define DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAGIC 0x64756d62 + +struct entry { + struct list_head node; + struct dentry *dentry; + char name[BUS_ID_SIZE]; +}; +static LIST_HEAD(entries); + +static struct vfsmount *mount; +static int mount_count; + +static struct file_operations stupid_file_ops = { + .read = do_sync_read, + .aio_read = generic_file_aio_read, + .write = do_sync_write, + .aio_write = generic_file_aio_write, + .mmap = generic_file_mmap, + .fsync = simple_sync_file, + .llseek = generic_file_llseek, +}; + +static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev) +{ + struct inode *inode = new_inode(sb); + + if (inode) { + inode->i_mode = mode; + inode->i_uid = 0; + inode->i_gid = 0; + inode->i_blocks = 0; + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + switch (mode & S_IFMT) { + default: + init_special_inode(inode, mode, dev); + break; + case S_IFREG: + inode->i_fop = &stupid_file_ops; + break; + case S_IFDIR: + inode->i_op = &simple_dir_inode_operations; + inode->i_fop = &simple_dir_operations; + + /* directory inodes start off with i_nlink == 2 (for "." entry) */ + inode->i_nlink++; + break; + } + } + return inode; +} + +/* SMP-safe */ +static int mknod(struct inode *dir, struct dentry *dentry, + int mode, dev_t dev) +{ + struct inode *inode = get_inode(dir->i_sb, mode, dev); + int error = -EPERM; + + if (dentry->d_inode) + return -EEXIST; + + if (inode) { + d_instantiate(dentry, inode); + dget(dentry); + error = 0; + } + return error; +} + +static inline int positive(struct dentry *dentry) +{ + return dentry->d_inode && !d_unhashed(dentry); +} + +static int fill_super(struct super_block *sb, void *data, int silent) +{ + static struct tree_descr files[] = {{""}}; + + return simple_fill_super(sb, MAGIC, files); +} + +static int get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) +{ + return get_sb_single(fs_type, flags, data, fill_super, mnt); +} + +static struct file_system_type fs_type = { + .owner = THIS_MODULE, + .name = "ndevfs", + .get_sb = get_sb, + .kill_sb = kill_litter_super, +}; + +static void remove(struct dentry *dentry) +{ + struct dentry *parent; + + if (!dentry) + return; + + parent = dentry->d_parent; + if (!parent || !parent->d_inode) + return; + + mutex_lock(&parent->d_inode->i_mutex); + if (positive(dentry)) { + if (dentry->d_inode) { + if (S_ISDIR(dentry->d_inode->i_mode)) + simple_rmdir(parent->d_inode, dentry); + else + simple_unlink(parent->d_inode, dentry); + dput(dentry); + } + } + mutex_unlock(&parent->d_inode->i_mutex); + simple_release_fs(&mount, &mount_count); +} + +/** + * ndevfs_create - create a device node in ndevfs + * + * @name: the name to create + * @dev: the dev_t of the node + * @is_char: if the node is a char device or not + */ +void ndevfs_create(const char *name, dev_t dev, int is_char) +{ + struct dentry *parent; + struct dentry *dentry; + struct entry *entry; + int err; + int mode = S_IRUSR | S_IWUSR; + + //pr_debug("ndevfs: creating file '%s' with major %d and minor %d\n", + // name, MAJOR(dev), MINOR(dev)); + + if (is_char) + mode |= S_IFCHR; + else + mode |= S_IFBLK; + + err = simple_pin_fs(&fs_type, &mount, &mount_count); + if (err) + return; + + /* everything is at the root fs, no directories allowed */ + if (mount && mount->mnt_sb) { + parent = mount->mnt_sb->s_root; + } else { + pr_debug("%s: no parent?\n", __FUNCTION__); + goto error; + } + + mutex_lock(&parent->d_inode->i_mutex); + dentry = lookup_one_len(name, parent, strlen(name)); + if (!IS_ERR(dentry)) + err = mknod(parent->d_inode, dentry, mode, dev); + else + err = PTR_ERR(dentry); + mutex_unlock(&parent->d_inode->i_mutex); + + if (err) + goto error; + + entry = kmalloc(sizeof(struct entry), GFP_KERNEL); + if (!entry) { + remove(dentry); + err = -ENOMEM; + goto error; + } + entry->dentry = dentry; + strcpy(&entry->name[0], name); + list_add(&entry->node, &entries); + return; + +error: + pr_debug("%s failed with error %d\n", __FUNCTION__, err); + simple_release_fs(&mount, &mount_count); +} +EXPORT_SYMBOL_GPL(ndevfs_create); + +/** + * ndevfs_remove - removes the node from the fs + * + * @name: the name to remove. + */ +void ndevfs_remove(const char *name) +{ + struct entry *entry; + struct dentry *dentry = NULL; + + //pr_debug("ndevfs: removing file '%s'\n", name); + + list_for_each_entry(entry, &entries, node) { + if (strcmp(name, &entry->name[0]) == 0) { + dentry = entry->dentry; + break; + } + } + if (!dentry) { + pr_debug("%s: can't find %s\n", __FUNCTION__, name); + return; + } + remove (dentry); +} +EXPORT_SYMBOL_GPL(ndevfs_remove); + +static int __init ndevfs_init(void) +{ + //return register_filesystem(&fs_type); + + int r = register_filesystem(&fs_type); + ndevfs_create("null", MKDEV(1, 3), 1); + ndevfs_create("console", MKDEV(5, 1), 1); + ndevfs_create("fb0", MKDEV(29, 0), 1); + ndevfs_create("tty0", MKDEV(4, 0), 1); + ndevfs_create("tty8", MKDEV(4, 8), 1); + ndevfs_create("ppp", MKDEV(108, 0), 1); + return r; +} + +static void __exit ndevfs_exit(void) +{ + simple_release_fs(&mount, &mount_count); + unregister_filesystem(&fs_type); +} + +core_initcall(ndevfs_init); +module_exit(ndevfs_exit); +MODULE_LICENSE("GPL"); diff -Nuar linux-2.6.23.orig/fs/partitions/check.c linux-2.6.23/fs/partitions/check.c --- linux-2.6.23.orig/fs/partitions/check.c 2007-10-10 05:31:38.000000000 +0900 +++ linux-2.6.23/fs/partitions/check.c 2007-10-24 13:55:25.000000000 +0900 @@ -18,6 +18,7 @@ #include #include #include +#include #include "check.h" @@ -362,6 +363,7 @@ p->ios[0] = p->ios[1] = 0; p->sectors[0] = p->sectors[1] = 0; sysfs_remove_link(&p->kobj, "subsystem"); + ndevfs_remove(kobject_name(&p->kobj)); kobject_unregister(p->holder_dir); kobject_uevent(&p->kobj, KOBJ_REMOVE); kobject_del(&p->kobj); @@ -391,6 +393,7 @@ kobject_add(&p->kobj); if (!disk->part_uevent_suppress) kobject_uevent(&p->kobj, KOBJ_ADD); + ndevfs_create(kobject_name(&p->kobj), MKDEV(disk->major, disk->first_minor + p->partno), 0); sysfs_create_link(&p->kobj, &block_subsys.kobj, "subsystem"); if (flags & ADDPART_FLAG_WHOLEDISK) { static struct attribute addpartattr = { @@ -489,7 +492,9 @@ kobject_del(&disk->kobj); return; } - disk_sysfs_add_subdirs(disk); + disk_sysfs_add_subdirs(disk); + ndevfs_create(kobject_name(&disk->kobj), + MKDEV(disk->major, disk->first_minor), 0); /* No minors to use for partitions */ if (disk->minors == 1) @@ -613,6 +618,7 @@ put_device(disk->driverfs_dev); disk->driverfs_dev = NULL; } + ndevfs_remove(kobject_name(&disk->kobj)); sysfs_remove_link(&disk->kobj, "subsystem"); kobject_del(&disk->kobj); } diff -Nuar linux-2.6.23.orig/include/linux/ndevfs.h linux-2.6.23/include/linux/ndevfs.h --- linux-2.6.23.orig/include/linux/ndevfs.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.23/include/linux/ndevfs.h 2007-10-24 13:55:25.000000000 +0900 @@ -0,0 +1,12 @@ +#ifndef _NDEVFS_H_ +#define _NDEVFS_H_ + +#if defined(CONFIG_NDEV_FS) +extern void ndevfs_create(const char *name, dev_t dev, int is_char); +extern void ndevfs_remove(const char *name); +#else +static inline void ndevfs_create(const char *name, dev_t dev, int is_char) {} +static inline void ndevfs_remove(const char *name) {} +#endif + +#endif