diff -Nuar linux-2.6.27.orig/drivers/base/core.c linux-2.6.27/drivers/base/core.c --- linux-2.6.27.orig/drivers/base/core.c 2008-10-10 07:13:53.000000000 +0900 +++ linux-2.6.27/drivers/base/core.c 2008-10-13 16:27:07.000000000 +0900 @@ -22,6 +22,7 @@ #include #include #include +#include #include "base.h" #include "power/power.h" @@ -430,8 +431,10 @@ int device_create_file(struct device *dev, struct device_attribute *attr) { int error = 0; - if (dev) + if (dev) { error = sysfs_create_file(&dev->kobj, &attr->attr); + //if (dev->class && MAJOR(dev->devt)) ndevfs_create(dev->bus_id, dev->devt, 1); // for char devices + } return error; } @@ -442,8 +445,10 @@ */ void device_remove_file(struct device *dev, struct device_attribute *attr) { - if (dev) + if (dev) { sysfs_remove_file(&dev->kobj, &attr->attr); + //if (dev->class && MAJOR(dev->devt)) ndevfs_remove(dev->bus_id); // for char devicess + } } /** diff -Nuar linux-2.6.27.orig/fs/Kconfig linux-2.6.27/fs/Kconfig --- linux-2.6.27.orig/fs/Kconfig 2008-10-13 16:31:50.000000000 +0900 +++ linux-2.6.27/fs/Kconfig 2008-10-13 16:25:40.000000000 +0900 @@ -979,6 +979,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 "Miscellaneous filesystems" diff -Nuar linux-2.6.27.orig/fs/Makefile linux-2.6.27/fs/Makefile --- linux-2.6.27.orig/fs/Makefile 2008-10-13 16:31:50.000000000 +0900 +++ linux-2.6.27/fs/Makefile 2008-10-13 16:25:40.000000000 +0900 @@ -117,6 +117,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.27.orig/fs/ndevfs/Makefile linux-2.6.27/fs/ndevfs/Makefile --- linux-2.6.27.orig/fs/ndevfs/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.27/fs/ndevfs/Makefile 2008-10-13 16:25:40.000000000 +0900 @@ -0,0 +1,4 @@ +ndevfs-objs := inode.o + +obj-$(CONFIG_NDEV_FS) += ndevfs.o + diff -Nuar linux-2.6.27.orig/fs/ndevfs/inode.c linux-2.6.27/fs/ndevfs/inode.c --- linux-2.6.27.orig/fs/ndevfs/inode.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.27/fs/ndevfs/inode.c 2008-10-13 16:25:40.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.27.orig/fs/partitions/check.c linux-2.6.27/fs/partitions/check.c --- linux-2.6.27.orig/fs/partitions/check.c 2008-10-10 07:13:53.000000000 +0900 +++ linux-2.6.27/fs/partitions/check.c 2008-10-13 16:28:03.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); @@ -392,6 +394,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); return 0; @@ -437,6 +440,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) @@ -558,6 +563,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.27.orig/include/linux/ndevfs.h linux-2.6.27/include/linux/ndevfs.h --- linux-2.6.27.orig/include/linux/ndevfs.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.27/include/linux/ndevfs.h 2008-10-13 16:25:40.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