diff -Nuar linux-2.6.25.orig/drivers/base/class.c linux-2.6.25/drivers/base/class.c --- linux-2.6.25.orig/drivers/base/class.c 2008-04-17 11:49:44.000000000 +0900 +++ linux-2.6.25/drivers/base/class.c 2008-07-04 19:35:53.000000000 +0900 @@ -18,6 +18,7 @@ #include #include #include +#include #include "base.h" #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) @@ -602,6 +603,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); @@ -750,8 +753,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.25.orig/fs/Kconfig linux-2.6.25/fs/Kconfig --- linux-2.6.25.orig/fs/Kconfig 2008-07-04 16:54:05.000000000 +0900 +++ linux-2.6.25/fs/Kconfig 2008-07-04 19:32:04.000000000 +0900 @@ -1001,6 +1001,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.25.orig/fs/Makefile linux-2.6.25/fs/Makefile --- linux-2.6.25.orig/fs/Makefile 2008-07-04 16:54:05.000000000 +0900 +++ linux-2.6.25/fs/Makefile 2008-07-04 19:32:04.000000000 +0900 @@ -114,6 +114,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.25.orig/fs/ndevfs/Makefile linux-2.6.25/fs/ndevfs/Makefile --- linux-2.6.25.orig/fs/ndevfs/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.25/fs/ndevfs/Makefile 2008-07-04 19:32:04.000000000 +0900 @@ -0,0 +1,4 @@ +ndevfs-objs := inode.o + +obj-$(CONFIG_NDEV_FS) += ndevfs.o + diff -Nuar linux-2.6.25.orig/fs/ndevfs/inode.c linux-2.6.25/fs/ndevfs/inode.c --- linux-2.6.25.orig/fs/ndevfs/inode.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.25/fs/ndevfs/inode.c 2008-07-04 19:32:04.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.25.orig/fs/partitions/check.c linux-2.6.25/fs/partitions/check.c --- linux-2.6.25.orig/fs/partitions/check.c 2008-04-17 11:49:44.000000000 +0900 +++ linux-2.6.25/fs/partitions/check.c 2008-07-04 20:04:44.000000000 +0900 @@ -19,6 +19,7 @@ #include #include #include +#include #include "check.h" @@ -112,7 +113,7 @@ #endif NULL }; - + /* * disk_name() is used by partition check code and the genhd driver. * It formats the devicename of the indicated disk into @@ -331,6 +332,7 @@ p->start_sect = 0; p->nr_sects = 0; part_stat_set_all(p, 0); + ndevfs_remove(kobject_name(&p->dev.kobj)); kobject_put(p->holder_dir); device_del(&p->dev); put_device(&p->dev); @@ -387,6 +389,7 @@ /* suppress uevent if the disk supresses it */ if (!disk->dev.uevent_suppress) kobject_uevent(&p->dev.kobj, KOBJ_ADD); + ndevfs_create(kobject_name(&p->dev.kobj), MKDEV(disk->major, disk->first_minor + p->partno), 0); } /* Not exported, helper to add_disk(). */ @@ -421,6 +424,8 @@ } #endif disk_sysfs_add_subdirs(disk); + ndevfs_create(kobject_name(&disk->dev.kobj), + MKDEV(disk->major, disk->first_minor), 0); /* No minors to use for partitions */ if (disk->minors == 1) @@ -532,6 +537,7 @@ kobject_put(disk->holder_dir); kobject_put(disk->slave_dir); disk->driverfs_dev = NULL; + ndevfs_remove(kobject_name(&disk->dev.kobj)); #ifndef CONFIG_SYSFS_DEPRECATED sysfs_remove_link(block_depr, disk->dev.bus_id); #endif diff -Nuar linux-2.6.25.orig/include/linux/ndevfs.h linux-2.6.25/include/linux/ndevfs.h --- linux-2.6.25.orig/include/linux/ndevfs.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.25/include/linux/ndevfs.h 2008-07-04 19:32:04.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