diff -Nuarp linux-2.6.30.orig/drivers/base/core.c linux-2.6.30/drivers/base/core.c --- linux-2.6.30.orig/drivers/base/core.c 2009-06-10 12:05:27.000000000 +0900 +++ linux-2.6.30/drivers/base/core.c 2009-06-22 13:19:17.000000000 +0900 @@ -22,6 +22,7 @@ #include #include #include +#include #include "base.h" #include "power/power.h" @@ -430,8 +431,10 @@ struct kset *devices_kset; 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 @@ int device_create_file(struct device *de */ 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 -Nuarp linux-2.6.30.orig/fs/Kconfig linux-2.6.30/fs/Kconfig --- linux-2.6.30.orig/fs/Kconfig 2009-06-22 12:59:20.000000000 +0900 +++ linux-2.6.30/fs/Kconfig 2009-06-22 13:19:17.000000000 +0900 @@ -266,4 +266,7 @@ endif source "fs/nls/Kconfig" source "fs/dlm/Kconfig" +config NDEV_FS + bool "Nano Device File System" + endmenu diff -Nuarp linux-2.6.30.orig/fs/Makefile linux-2.6.30/fs/Makefile --- linux-2.6.30.orig/fs/Makefile 2009-06-22 12:59:20.000000000 +0900 +++ linux-2.6.30/fs/Makefile 2009-06-22 13:20:03.000000000 +0900 @@ -3,7 +3,7 @@ # # 14 Sep 2000, Christoph Hellwig # Rewritten to use lists instead of if-statements. -# +# obj-y := open.o read_write.o file_table.o super.o \ char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \ @@ -61,7 +61,7 @@ obj-y += devpts/ obj-$(CONFIG_PROFILING) += dcookies.o obj-$(CONFIG_DLM) += dlm/ - + # Do not add any filesystems before this line obj-$(CONFIG_FSCACHE) += fscache/ obj-$(CONFIG_REISERFS_FS) += reiserfs/ @@ -115,6 +115,7 @@ obj-$(CONFIG_JFS_FS) += jfs/ obj-$(CONFIG_XFS_FS) += xfs/ obj-$(CONFIG_9P_FS) += 9p/ obj-$(CONFIG_AFS_FS) += afs/ +obj-$(CONFIG_NDEV_FS) += ndevfs/ obj-$(CONFIG_NILFS2_FS) += nilfs2/ obj-$(CONFIG_BEFS_FS) += befs/ obj-$(CONFIG_HOSTFS) += hostfs/ diff -Nuarp linux-2.6.30.orig/fs/ndevfs/Makefile linux-2.6.30/fs/ndevfs/Makefile --- linux-2.6.30.orig/fs/ndevfs/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.30/fs/ndevfs/Makefile 2009-06-22 13:19:17.000000000 +0900 @@ -0,0 +1,4 @@ +ndevfs-objs := inode.o + +obj-$(CONFIG_NDEV_FS) += ndevfs.o + diff -Nuarp linux-2.6.30.orig/fs/ndevfs/inode.c linux-2.6.30/fs/ndevfs/inode.c --- linux-2.6.30.orig/fs/ndevfs/inode.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.30/fs/ndevfs/inode.c 2009-06-22 13:19:17.000000000 +0900 @@ -0,0 +1,263 @@ +/* + * 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); + ndevfs_create("sg0", MKDEV(21, 0), 1); + ndevfs_create("sg1", MKDEV(21, 1), 1); + ndevfs_create("sg2", MKDEV(21, 2), 1); + ndevfs_create("sg3", MKDEV(21, 3), 1); + ndevfs_create("sg4", MKDEV(21, 4), 1); + ndevfs_create("sg5", MKDEV(21, 5), 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 -Nuarp linux-2.6.30.orig/fs/partitions/check.c linux-2.6.30/fs/partitions/check.c --- linux-2.6.30.orig/fs/partitions/check.c 2009-06-10 12:05:27.000000000 +0900 +++ linux-2.6.30/fs/partitions/check.c 2009-06-22 13:20:43.000000000 +0900 @@ -20,6 +20,7 @@ #include #include #include +#include #include "check.h" @@ -113,7 +114,7 @@ static int (*check_part[])(struct parsed #endif NULL }; - + /* * disk_name() is used by partition check code and the genhd driver. * It formats the devicename of the indicated disk into @@ -321,6 +322,7 @@ static void delete_partition_rcu_cb(stru part->start_sect = 0; part->nr_sects = 0; part_stat_set_all(part, 0); + ndevfs_remove(kobject_name(&part_to_dev(part)->kobj)); put_device(part_to_dev(part)); } @@ -428,6 +430,7 @@ struct hd_struct *add_partition(struct g /* suppress uevent if the disk supresses it */ if (!dev_get_uevent_suppress(pdev)) kobject_uevent(&pdev->kobj, KOBJ_ADD); + ndevfs_create(kobject_name(&pdev->kobj), MKDEV(disk->major, disk->first_minor + p->partno), 0); return p; @@ -473,7 +476,8 @@ void register_disk(struct gendisk *disk) #endif disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj); disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); - + ndevfs_create(kobject_name(&ddev->kobj), + MKDEV(disk->major, disk->first_minor), 0); /* No minors to use for partitions */ if (!disk_partitionable(disk)) goto exit; @@ -630,6 +634,7 @@ void del_gendisk(struct gendisk *disk) kobject_put(disk->part0.holder_dir); kobject_put(disk->slave_dir); disk->driverfs_dev = NULL; + ndevfs_remove(kobject_name(&disk_to_dev(disk)->kobj)); #ifndef CONFIG_SYSFS_DEPRECATED sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk))); #endif diff -Nuarp linux-2.6.30.orig/include/linux/ndevfs.h linux-2.6.30/include/linux/ndevfs.h --- linux-2.6.30.orig/include/linux/ndevfs.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.30/include/linux/ndevfs.h 2009-06-22 13:19:17.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