Nobody seems to have any outstanding work against devfs, so... --- 25-akpm/fs/devfs/base.c | 2889 ++++++++++++++++---------------- 25-akpm/fs/devfs/util.c | 2 25-akpm/include/linux/devfs_fs.h | 30 25-akpm/include/linux/devfs_fs_kernel.h | 26 4 files changed, 1482 insertions(+), 1465 deletions(-) diff -puN fs/devfs/base.c~Lindent-devfs fs/devfs/base.c --- 25/fs/devfs/base.c~Lindent-devfs 2004-03-24 02:43:40.242748136 -0800 +++ 25-akpm/fs/devfs/base.c 2004-03-24 02:43:40.263744944 -0800 @@ -710,8 +710,8 @@ #define DEBUG_UNREGISTER 0x0000004 #define DEBUG_FREE 0x0000008 #define DEBUG_SET_FLAGS 0x0000010 -#define DEBUG_S_READ 0x0000100 /* Break */ -#define DEBUG_I_LOOKUP 0x0001000 /* Break */ +#define DEBUG_S_READ 0x0000100 /* Break */ +#define DEBUG_I_LOOKUP 0x0001000 /* Break */ #define DEBUG_I_CREATE 0x0002000 #define DEBUG_I_GET 0x0004000 #define DEBUG_I_CHANGE 0x0008000 @@ -719,8 +719,8 @@ #define DEBUG_I_RLINK 0x0020000 #define DEBUG_I_FLINK 0x0040000 #define DEBUG_I_MKNOD 0x0080000 -#define DEBUG_F_READDIR 0x0100000 /* Break */ -#define DEBUG_D_DELETE 0x1000000 /* Break */ +#define DEBUG_F_READDIR 0x0100000 /* Break */ +#define DEBUG_D_DELETE 0x1000000 /* Break */ #define DEBUG_D_RELEASE 0x2000000 #define DEBUG_D_IPUT 0x4000000 #define DEBUG_ALL 0xfffffff @@ -753,88 +753,80 @@ typedef struct devfs_entry *devfs_handle_t; -struct directory_type -{ - rwlock_t lock; /* Lock for searching(R)/updating(W) */ - struct devfs_entry *first; - struct devfs_entry *last; - unsigned char no_more_additions:1; +struct directory_type { + rwlock_t lock; /* Lock for searching(R)/updating(W) */ + struct devfs_entry *first; + struct devfs_entry *last; + unsigned char no_more_additions:1; }; -struct symlink_type -{ - unsigned int length; /* Not including the NULL-termimator */ - char *linkname; /* This is NULL-terminated */ +struct symlink_type { + unsigned int length; /* Not including the NULL-termimator */ + char *linkname; /* This is NULL-terminated */ }; -struct devfs_inode /* This structure is for "persistent" inode storage */ -{ - struct dentry *dentry; - struct timespec atime; - struct timespec mtime; - struct timespec ctime; - unsigned int ino; /* Inode number as seen in the VFS */ - uid_t uid; - gid_t gid; +struct devfs_inode { /* This structure is for "persistent" inode storage */ + struct dentry *dentry; + struct timespec atime; + struct timespec mtime; + struct timespec ctime; + unsigned int ino; /* Inode number as seen in the VFS */ + uid_t uid; + gid_t gid; }; -struct devfs_entry -{ +struct devfs_entry { #ifdef CONFIG_DEVFS_DEBUG - unsigned int magic_number; + unsigned int magic_number; #endif - void *info; - atomic_t refcount; /* When this drops to zero, it's unused */ - union - { - struct directory_type dir; - dev_t dev; - struct symlink_type symlink; - const char *name; /* Only used for (mode == 0) */ - } - u; - struct devfs_entry *prev; /* Previous entry in the parent directory */ - struct devfs_entry *next; /* Next entry in the parent directory */ - struct devfs_entry *parent; /* The parent directory */ - struct devfs_inode inode; - umode_t mode; - unsigned short namelen; /* I think 64k+ filenames are a way off... */ - unsigned char vfs:1;/* Whether the VFS may delete the entry */ - char name[1]; /* This is just a dummy: the allocated array - is bigger. This is NULL-terminated */ + void *info; + atomic_t refcount; /* When this drops to zero, it's unused */ + union { + struct directory_type dir; + dev_t dev; + struct symlink_type symlink; + const char *name; /* Only used for (mode == 0) */ + } u; + struct devfs_entry *prev; /* Previous entry in the parent directory */ + struct devfs_entry *next; /* Next entry in the parent directory */ + struct devfs_entry *parent; /* The parent directory */ + struct devfs_inode inode; + umode_t mode; + unsigned short namelen; /* I think 64k+ filenames are a way off... */ + unsigned char vfs:1; /* Whether the VFS may delete the entry */ + char name[1]; /* This is just a dummy: the allocated array + is bigger. This is NULL-terminated */ }; /* The root of the device tree */ static struct devfs_entry *root_entry; -struct devfsd_buf_entry -{ - struct devfs_entry *de; /* The name is generated with this */ - unsigned short type; /* The type of event */ - umode_t mode; - uid_t uid; - gid_t gid; - struct devfsd_buf_entry *next; +struct devfsd_buf_entry { + struct devfs_entry *de; /* The name is generated with this */ + unsigned short type; /* The type of event */ + umode_t mode; + uid_t uid; + gid_t gid; + struct devfsd_buf_entry *next; }; -struct fs_info /* This structure is for the mounted devfs */ -{ - struct super_block *sb; - spinlock_t devfsd_buffer_lock; /* Lock when inserting/deleting events */ - struct devfsd_buf_entry *devfsd_first_event; - struct devfsd_buf_entry *devfsd_last_event; - volatile int devfsd_sleeping; - volatile struct task_struct *devfsd_task; - volatile pid_t devfsd_pgrp; - volatile struct file *devfsd_file; - struct devfsd_notify_struct *devfsd_info; - volatile unsigned long devfsd_event_mask; - atomic_t devfsd_overrun_count; - wait_queue_head_t devfsd_wait_queue; /* Wake devfsd on input */ - wait_queue_head_t revalidate_wait_queue; /* Wake when devfsd sleeps */ +struct fs_info { /* This structure is for the mounted devfs */ + struct super_block *sb; + spinlock_t devfsd_buffer_lock; /* Lock when inserting/deleting events */ + struct devfsd_buf_entry *devfsd_first_event; + struct devfsd_buf_entry *devfsd_last_event; + volatile int devfsd_sleeping; + volatile struct task_struct *devfsd_task; + volatile pid_t devfsd_pgrp; + volatile struct file *devfsd_file; + struct devfsd_notify_struct *devfsd_info; + volatile unsigned long devfsd_event_mask; + atomic_t devfsd_overrun_count; + wait_queue_head_t devfsd_wait_queue; /* Wake devfsd on input */ + wait_queue_head_t revalidate_wait_queue; /* Wake when devfsd sleeps */ }; -static struct fs_info fs_info = {.devfsd_buffer_lock = SPIN_LOCK_UNLOCKED}; +static struct fs_info fs_info = {.devfsd_buffer_lock = SPIN_LOCK_UNLOCKED }; static kmem_cache_t *devfsd_buf_cache; #ifdef CONFIG_DEVFS_DEBUG static unsigned int devfs_debug_init __initdata = DEBUG_NONE; @@ -844,7 +836,7 @@ static unsigned int stat_num_entries; static unsigned int stat_num_bytes; #endif static unsigned char poison_array[8] = - {0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a}; + { 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a }; #ifdef CONFIG_DEVFS_MOUNT static unsigned int boot_options = OPTION_MOUNT; @@ -853,75 +845,77 @@ static unsigned int boot_options = OPTIO #endif /* Forward function declarations */ -static devfs_handle_t _devfs_walk_path (struct devfs_entry *dir, - const char *name, int namelen, - int traverse_symlink); -static ssize_t devfsd_read (struct file *file, char *buf, size_t len, - loff_t *ppos); -static int devfsd_ioctl (struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); -static int devfsd_close (struct inode *inode, struct file *file); +static devfs_handle_t _devfs_walk_path(struct devfs_entry *dir, + const char *name, int namelen, + int traverse_symlink); +static ssize_t devfsd_read(struct file *file, char *buf, size_t len, + loff_t * ppos); +static int devfsd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static int devfsd_close(struct inode *inode, struct file *file); #ifdef CONFIG_DEVFS_DEBUG -static ssize_t stat_read (struct file *file, char *buf, size_t len, - loff_t *ppos); -static struct file_operations stat_fops = -{ - .read = stat_read, +static ssize_t stat_read(struct file *file, char *buf, size_t len, + loff_t * ppos); +static struct file_operations stat_fops = { + .read = stat_read, }; #endif - /* Devfs daemon file operations */ -static struct file_operations devfsd_fops = -{ - .read = devfsd_read, - .ioctl = devfsd_ioctl, - .release = devfsd_close, +static struct file_operations devfsd_fops = { + .read = devfsd_read, + .ioctl = devfsd_ioctl, + .release = devfsd_close, }; - /* Support functions follow */ - /** * devfs_get - Get a reference to a devfs entry. * @de: The devfs entry. */ -static struct devfs_entry *devfs_get (struct devfs_entry *de) +static struct devfs_entry *devfs_get(struct devfs_entry *de) { - VERIFY_ENTRY (de); - if (de) atomic_inc (&de->refcount); - return de; -} /* End Function devfs_get */ + VERIFY_ENTRY(de); + if (de) + atomic_inc(&de->refcount); + return de; +} /* End Function devfs_get */ /** * devfs_put - Put (release) a reference to a devfs entry. * @de: The handle to the devfs entry. */ -static void devfs_put (devfs_handle_t de) +static void devfs_put(devfs_handle_t de) { - if (!de) return; - VERIFY_ENTRY (de); - if (de->info == POISON_PTR) OOPS ("(%p): poisoned pointer\n", de); - if ( !atomic_dec_and_test (&de->refcount) ) return; - if (de == root_entry) OOPS ("(%p): root entry being freed\n", de); - DPRINTK (DEBUG_FREE, "(%s): de: %p, parent: %p \"%s\"\n", - de->name, de, de->parent, - de->parent ? de->parent->name : "no parent"); - if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname); - WRITE_ENTRY_MAGIC (de, 0); + if (!de) + return; + VERIFY_ENTRY(de); + if (de->info == POISON_PTR) + OOPS("(%p): poisoned pointer\n", de); + if (!atomic_dec_and_test(&de->refcount)) + return; + if (de == root_entry) + OOPS("(%p): root entry being freed\n", de); + DPRINTK(DEBUG_FREE, "(%s): de: %p, parent: %p \"%s\"\n", + de->name, de, de->parent, + de->parent ? de->parent->name : "no parent"); + if (S_ISLNK(de->mode)) + kfree(de->u.symlink.linkname); + WRITE_ENTRY_MAGIC(de, 0); #ifdef CONFIG_DEVFS_DEBUG - spin_lock (&stat_lock); - --stat_num_entries; - stat_num_bytes -= sizeof *de + de->namelen; - if ( S_ISLNK (de->mode) ) stat_num_bytes -= de->u.symlink.length + 1; - spin_unlock (&stat_lock); + spin_lock(&stat_lock); + --stat_num_entries; + stat_num_bytes -= sizeof *de + de->namelen; + if (S_ISLNK(de->mode)) + stat_num_bytes -= de->u.symlink.length + 1; + spin_unlock(&stat_lock); #endif - de->info = POISON_PTR; - kfree (de); -} /* End Function devfs_put */ + de->info = POISON_PTR; + kfree(de); +} /* End Function devfs_put */ /** * _devfs_search_dir - Search for a devfs entry in a directory. @@ -934,26 +928,25 @@ static void devfs_put (devfs_handle_t de * An implicit devfs_get() is performed on the returned entry. */ -static struct devfs_entry *_devfs_search_dir (struct devfs_entry *dir, - const char *name, - unsigned int namelen) -{ - struct devfs_entry *curr; - - if ( !S_ISDIR (dir->mode) ) - { - PRINTK ("(%s): not a directory\n", dir->name); - return NULL; - } - for (curr = dir->u.dir.first; curr != NULL; curr = curr->next) - { - if (curr->namelen != namelen) continue; - if (memcmp (curr->name, name, namelen) == 0) break; - /* Not found: try the next one */ - } - return devfs_get (curr); -} /* End Function _devfs_search_dir */ +static struct devfs_entry *_devfs_search_dir(struct devfs_entry *dir, + const char *name, + unsigned int namelen) +{ + struct devfs_entry *curr; + if (!S_ISDIR(dir->mode)) { + PRINTK("(%s): not a directory\n", dir->name); + return NULL; + } + for (curr = dir->u.dir.first; curr != NULL; curr = curr->next) { + if (curr->namelen != namelen) + continue; + if (memcmp(curr->name, name, namelen) == 0) + break; + /* Not found: try the next one */ + } + return devfs_get(curr); +} /* End Function _devfs_search_dir */ /** * _devfs_alloc_entry - Allocate a devfs entry. @@ -965,36 +958,38 @@ static struct devfs_entry *_devfs_search * %NULL. */ -static struct devfs_entry *_devfs_alloc_entry (const char *name, - unsigned int namelen, - umode_t mode) -{ - struct devfs_entry *new; - static unsigned long inode_counter = FIRST_INODE; - static spinlock_t counter_lock = SPIN_LOCK_UNLOCKED; - - if ( name && (namelen < 1) ) namelen = strlen (name); - if ( ( new = kmalloc (sizeof *new + namelen, GFP_KERNEL) ) == NULL ) - return NULL; - memset (new, 0, sizeof *new + namelen); /* Will set '\0' on name */ - new->mode = mode; - if ( S_ISDIR (mode) ) rwlock_init (&new->u.dir.lock); - atomic_set (&new->refcount, 1); - spin_lock (&counter_lock); - new->inode.ino = inode_counter++; - spin_unlock (&counter_lock); - if (name) memcpy (new->name, name, namelen); - new->namelen = namelen; - WRITE_ENTRY_MAGIC (new, MAGIC_VALUE); +static struct devfs_entry *_devfs_alloc_entry(const char *name, + unsigned int namelen, + umode_t mode) +{ + struct devfs_entry *new; + static unsigned long inode_counter = FIRST_INODE; + static spinlock_t counter_lock = SPIN_LOCK_UNLOCKED; + + if (name && (namelen < 1)) + namelen = strlen(name); + if ((new = kmalloc(sizeof *new + namelen, GFP_KERNEL)) == NULL) + return NULL; + memset(new, 0, sizeof *new + namelen); /* Will set '\0' on name */ + new->mode = mode; + if (S_ISDIR(mode)) + rwlock_init(&new->u.dir.lock); + atomic_set(&new->refcount, 1); + spin_lock(&counter_lock); + new->inode.ino = inode_counter++; + spin_unlock(&counter_lock); + if (name) + memcpy(new->name, name, namelen); + new->namelen = namelen; + WRITE_ENTRY_MAGIC(new, MAGIC_VALUE); #ifdef CONFIG_DEVFS_DEBUG - spin_lock (&stat_lock); - ++stat_num_entries; - stat_num_bytes += sizeof *new + namelen; - spin_unlock (&stat_lock); + spin_lock(&stat_lock); + ++stat_num_entries; + stat_num_bytes += sizeof *new + namelen; + spin_unlock(&stat_lock); #endif - return new; -} /* End Function _devfs_alloc_entry */ - + return new; +} /* End Function _devfs_alloc_entry */ /** * _devfs_append_entry - Append a devfs entry to a directory's child list. @@ -1009,43 +1004,48 @@ static struct devfs_entry *_devfs_alloc_ * On failure, an implicit devfs_put() is performed on %de. */ -static int _devfs_append_entry (devfs_handle_t dir, devfs_handle_t de, - devfs_handle_t *old_de) +static int _devfs_append_entry(devfs_handle_t dir, devfs_handle_t de, + devfs_handle_t * old_de) { - int retval; + int retval; - if (old_de) *old_de = NULL; - if ( !S_ISDIR (dir->mode) ) - { - PRINTK ("(%s): dir: \"%s\" is not a directory\n", de->name, dir->name); - devfs_put (de); - return -ENOTDIR; - } - write_lock (&dir->u.dir.lock); - if (dir->u.dir.no_more_additions) retval = -ENOENT; - else - { - struct devfs_entry *old; - - old = _devfs_search_dir (dir, de->name, de->namelen); - if (old_de) *old_de = old; - else devfs_put (old); - if (old == NULL) - { - de->parent = dir; - de->prev = dir->u.dir.last; - /* Append to the directory's list of children */ - if (dir->u.dir.first == NULL) dir->u.dir.first = de; - else dir->u.dir.last->next = de; - dir->u.dir.last = de; - retval = 0; - } - else retval = -EEXIST; - } - write_unlock (&dir->u.dir.lock); - if (retval) devfs_put (de); - return retval; -} /* End Function _devfs_append_entry */ + if (old_de) + *old_de = NULL; + if (!S_ISDIR(dir->mode)) { + PRINTK("(%s): dir: \"%s\" is not a directory\n", de->name, + dir->name); + devfs_put(de); + return -ENOTDIR; + } + write_lock(&dir->u.dir.lock); + if (dir->u.dir.no_more_additions) + retval = -ENOENT; + else { + struct devfs_entry *old; + + old = _devfs_search_dir(dir, de->name, de->namelen); + if (old_de) + *old_de = old; + else + devfs_put(old); + if (old == NULL) { + de->parent = dir; + de->prev = dir->u.dir.last; + /* Append to the directory's list of children */ + if (dir->u.dir.first == NULL) + dir->u.dir.first = de; + else + dir->u.dir.last->next = de; + dir->u.dir.last = de; + retval = 0; + } else + retval = -EEXIST; + } + write_unlock(&dir->u.dir.lock); + if (retval) + devfs_put(de); + return retval; +} /* End Function _devfs_append_entry */ /** * _devfs_get_root_entry - Get the root devfs entry. @@ -1067,7 +1067,7 @@ static struct devfs_entry *_devfs_get_ro return root_entry; new = _devfs_alloc_entry(NULL, 0, MODE_DIR); - if (new == NULL ) + if (new == NULL) return NULL; spin_lock(&root_lock); @@ -1080,7 +1080,7 @@ static struct devfs_entry *_devfs_get_ro spin_unlock(&root_lock); return root_entry; -} /* End Function _devfs_get_root_entry */ +} /* End Function _devfs_get_root_entry */ /** * _devfs_descend - Descend down a tree using the next component name. @@ -1096,142 +1096,134 @@ static struct devfs_entry *_devfs_get_ro * An implicit devfs_get() is performed on the returned entry. */ -static struct devfs_entry *_devfs_descend (struct devfs_entry *dir, - const char *name, int namelen, - int *next_pos) -{ - const char *stop, *ptr; - struct devfs_entry *entry; - - if ( (namelen >= 3) && (strncmp (name, "../", 3) == 0) ) - { /* Special-case going to parent directory */ - *next_pos = 3; - return devfs_get (dir->parent); - } - stop = name + namelen; - /* Search for a possible '/' */ - for (ptr = name; (ptr < stop) && (*ptr != '/'); ++ptr); - *next_pos = ptr - name; - read_lock (&dir->u.dir.lock); - entry = _devfs_search_dir (dir, name, *next_pos); - read_unlock (&dir->u.dir.lock); - return entry; -} /* End Function _devfs_descend */ - - -static devfs_handle_t _devfs_make_parent_for_leaf (struct devfs_entry *dir, - const char *name, - int namelen, int *leaf_pos) -{ - int next_pos = 0; - - if (dir == NULL) dir = _devfs_get_root_entry (); - if (dir == NULL) return NULL; - devfs_get (dir); - /* Search for possible trailing component and ignore it */ - for (--namelen; (namelen > 0) && (name[namelen] != '/'); --namelen); - *leaf_pos = (name[namelen] == '/') ? (namelen + 1) : 0; - for (; namelen > 0; name += next_pos, namelen -= next_pos) - { - struct devfs_entry *de, *old = NULL; - - if ( ( de = _devfs_descend (dir, name, namelen, &next_pos) ) == NULL ) - { - de = _devfs_alloc_entry (name, next_pos, MODE_DIR); - devfs_get (de); - if ( !de || _devfs_append_entry (dir, de, &old) ) - { - devfs_put (de); - if ( !old || !S_ISDIR (old->mode) ) - { - devfs_put (old); - devfs_put (dir); - return NULL; +static struct devfs_entry *_devfs_descend(struct devfs_entry *dir, + const char *name, int namelen, + int *next_pos) +{ + const char *stop, *ptr; + struct devfs_entry *entry; + + if ((namelen >= 3) && (strncmp(name, "../", 3) == 0)) { /* Special-case going to parent directory */ + *next_pos = 3; + return devfs_get(dir->parent); + } + stop = name + namelen; + /* Search for a possible '/' */ + for (ptr = name; (ptr < stop) && (*ptr != '/'); ++ptr) ; + *next_pos = ptr - name; + read_lock(&dir->u.dir.lock); + entry = _devfs_search_dir(dir, name, *next_pos); + read_unlock(&dir->u.dir.lock); + return entry; +} /* End Function _devfs_descend */ + +static devfs_handle_t _devfs_make_parent_for_leaf(struct devfs_entry *dir, + const char *name, + int namelen, int *leaf_pos) +{ + int next_pos = 0; + + if (dir == NULL) + dir = _devfs_get_root_entry(); + if (dir == NULL) + return NULL; + devfs_get(dir); + /* Search for possible trailing component and ignore it */ + for (--namelen; (namelen > 0) && (name[namelen] != '/'); --namelen) ; + *leaf_pos = (name[namelen] == '/') ? (namelen + 1) : 0; + for (; namelen > 0; name += next_pos, namelen -= next_pos) { + struct devfs_entry *de, *old = NULL; + + if ((de = + _devfs_descend(dir, name, namelen, &next_pos)) == NULL) { + de = _devfs_alloc_entry(name, next_pos, MODE_DIR); + devfs_get(de); + if (!de || _devfs_append_entry(dir, de, &old)) { + devfs_put(de); + if (!old || !S_ISDIR(old->mode)) { + devfs_put(old); + devfs_put(dir); + return NULL; + } + de = old; /* Use the existing directory */ + } + } + if (de == dir->parent) { + devfs_put(dir); + devfs_put(de); + return NULL; } - de = old; /* Use the existing directory */ - } + devfs_put(dir); + dir = de; + if (name[next_pos] == '/') + ++next_pos; + } + return dir; +} /* End Function _devfs_make_parent_for_leaf */ + +static devfs_handle_t _devfs_prepare_leaf(devfs_handle_t * dir, + const char *name, umode_t mode) +{ + int namelen, leaf_pos; + struct devfs_entry *de; + + namelen = strlen(name); + if ((*dir = _devfs_make_parent_for_leaf(*dir, name, namelen, + &leaf_pos)) == NULL) { + PRINTK("(%s): could not create parent path\n", name); + return NULL; } - if (de == dir->parent) - { - devfs_put (dir); - devfs_put (de); - return NULL; - } - devfs_put (dir); - dir = de; - if (name[next_pos] == '/') ++next_pos; - } - return dir; -} /* End Function _devfs_make_parent_for_leaf */ - - -static devfs_handle_t _devfs_prepare_leaf (devfs_handle_t *dir, - const char *name, umode_t mode) -{ - int namelen, leaf_pos; - struct devfs_entry *de; - - namelen = strlen (name); - if ( ( *dir = _devfs_make_parent_for_leaf (*dir, name, namelen, - &leaf_pos) ) == NULL ) - { - PRINTK ("(%s): could not create parent path\n", name); - return NULL; - } - if ( ( de = _devfs_alloc_entry (name + leaf_pos, namelen - leaf_pos,mode) ) - == NULL ) - { - PRINTK ("(%s): could not allocate entry\n", name); - devfs_put (*dir); - return NULL; - } - return de; -} /* End Function _devfs_prepare_leaf */ - - -static devfs_handle_t _devfs_walk_path (struct devfs_entry *dir, - const char *name, int namelen, - int traverse_symlink) -{ - int next_pos = 0; - - if (dir == NULL) dir = _devfs_get_root_entry (); - if (dir == NULL) return NULL; - devfs_get (dir); - for (; namelen > 0; name += next_pos, namelen -= next_pos) - { - struct devfs_entry *de, *link; - - if (!S_ISDIR (dir->mode)) - { - devfs_put (dir); - return NULL; - } - - if ( ( de = _devfs_descend (dir, name, namelen, &next_pos) ) == NULL ) - { - devfs_put (dir); - return NULL; - } - if (S_ISLNK (de->mode) && traverse_symlink) - { /* Need to follow the link: this is a stack chomper */ - /* FIXME what if it puts outside of mounted tree? */ - link = _devfs_walk_path (dir, de->u.symlink.linkname, - de->u.symlink.length, TRUE); - devfs_put (de); - if (!link) - { - devfs_put (dir); + if ((de = _devfs_alloc_entry(name + leaf_pos, namelen - leaf_pos, mode)) + == NULL) { + PRINTK("(%s): could not allocate entry\n", name); + devfs_put(*dir); return NULL; - } - de = link; } - devfs_put (dir); - dir = de; - if (name[next_pos] == '/') ++next_pos; - } - return dir; -} /* End Function _devfs_walk_path */ + return de; +} /* End Function _devfs_prepare_leaf */ + +static devfs_handle_t _devfs_walk_path(struct devfs_entry *dir, + const char *name, int namelen, + int traverse_symlink) +{ + int next_pos = 0; + + if (dir == NULL) + dir = _devfs_get_root_entry(); + if (dir == NULL) + return NULL; + devfs_get(dir); + for (; namelen > 0; name += next_pos, namelen -= next_pos) { + struct devfs_entry *de, *link; + + if (!S_ISDIR(dir->mode)) { + devfs_put(dir); + return NULL; + } + + if ((de = + _devfs_descend(dir, name, namelen, &next_pos)) == NULL) { + devfs_put(dir); + return NULL; + } + if (S_ISLNK(de->mode) && traverse_symlink) { /* Need to follow the link: this is a stack chomper */ + /* FIXME what if it puts outside of mounted tree? */ + link = _devfs_walk_path(dir, de->u.symlink.linkname, + de->u.symlink.length, TRUE); + devfs_put(de); + if (!link) { + devfs_put(dir); + return NULL; + } + de = link; + } + devfs_put(dir); + dir = de; + if (name[next_pos] == '/') + ++next_pos; + } + return dir; +} /* End Function _devfs_walk_path */ /** * _devfs_find_entry - Find a devfs entry. @@ -1244,40 +1236,37 @@ static devfs_handle_t _devfs_walk_path ( * devfs_get() is performed. */ -static struct devfs_entry *_devfs_find_entry (devfs_handle_t dir, - const char *name, - int traverse_symlink) -{ - unsigned int namelen = strlen (name); - - if (name[0] == '/') - { - /* Skip leading pathname component */ - if (namelen < 2) - { - PRINTK ("(%s): too short\n", name); - return NULL; - } - for (++name, --namelen; (*name != '/') && (namelen > 0); - ++name, --namelen); - if (namelen < 2) - { - PRINTK ("(%s): too short\n", name); - return NULL; - } - ++name; - --namelen; - } - return _devfs_walk_path (dir, name, namelen, traverse_symlink); -} /* End Function _devfs_find_entry */ - -static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode) -{ - if (inode == NULL) return NULL; - VERIFY_ENTRY ( (struct devfs_entry *) inode->u.generic_ip ); - return inode->u.generic_ip; -} /* End Function get_devfs_entry_from_vfs_inode */ +static struct devfs_entry *_devfs_find_entry(devfs_handle_t dir, + const char *name, + int traverse_symlink) +{ + unsigned int namelen = strlen(name); + + if (name[0] == '/') { + /* Skip leading pathname component */ + if (namelen < 2) { + PRINTK("(%s): too short\n", name); + return NULL; + } + for (++name, --namelen; (*name != '/') && (namelen > 0); + ++name, --namelen) ; + if (namelen < 2) { + PRINTK("(%s): too short\n", name); + return NULL; + } + ++name; + --namelen; + } + return _devfs_walk_path(dir, name, namelen, traverse_symlink); +} /* End Function _devfs_find_entry */ +static struct devfs_entry *get_devfs_entry_from_vfs_inode(struct inode *inode) +{ + if (inode == NULL) + return NULL; + VERIFY_ENTRY((struct devfs_entry *)inode->u.generic_ip); + return inode->u.generic_ip; +} /* End Function get_devfs_entry_from_vfs_inode */ /** * free_dentry - Free the dentry for a device entry and invalidate inode. @@ -1287,20 +1276,21 @@ static struct devfs_entry *get_devfs_ent * parent directory. */ -static void free_dentry (struct devfs_entry *de) +static void free_dentry(struct devfs_entry *de) { - struct dentry *dentry = de->inode.dentry; - - if (!dentry) return; - spin_lock (&dcache_lock); - dget_locked (dentry); - spin_unlock (&dcache_lock); - /* Forcefully remove the inode */ - if (dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0; - d_drop (dentry); - dput (dentry); -} /* End Function free_dentry */ + struct dentry *dentry = de->inode.dentry; + if (!dentry) + return; + spin_lock(&dcache_lock); + dget_locked(dentry); + spin_unlock(&dcache_lock); + /* Forcefully remove the inode */ + if (dentry->d_inode != NULL) + dentry->d_inode->i_nlink = 0; + d_drop(dentry); + dput(dentry); +} /* End Function free_dentry */ /** * is_devfsd_or_child - Test if the current process is devfsd or one of its children. @@ -1309,25 +1299,24 @@ static void free_dentry (struct devfs_en * Returns %TRUE if devfsd or child, else %FALSE. */ -static int is_devfsd_or_child (struct fs_info *fs_info) +static int is_devfsd_or_child(struct fs_info *fs_info) { - struct task_struct *p = current; + struct task_struct *p = current; - if (p == fs_info->devfsd_task) return (TRUE); - if (process_group(p) == fs_info->devfsd_pgrp) return (TRUE); - read_lock(&tasklist_lock); - for ( ; p != &init_task; p = p->real_parent) - { if (p == fs_info->devfsd_task) - { - read_unlock (&tasklist_lock); - return (TRUE); - } - } - read_unlock (&tasklist_lock); - return (FALSE); -} /* End Function is_devfsd_or_child */ - + return (TRUE); + if (process_group(p) == fs_info->devfsd_pgrp) + return (TRUE); + read_lock(&tasklist_lock); + for (; p != &init_task; p = p->real_parent) { + if (p == fs_info->devfsd_task) { + read_unlock(&tasklist_lock); + return (TRUE); + } + } + read_unlock(&tasklist_lock); + return (FALSE); +} /* End Function is_devfsd_or_child */ /** * devfsd_queue_empty - Test if devfsd has work pending in its event queue. @@ -1336,11 +1325,10 @@ static int is_devfsd_or_child (struct fs * Returns %TRUE if the queue is empty, else %FALSE. */ -static inline int devfsd_queue_empty (struct fs_info *fs_info) +static inline int devfsd_queue_empty(struct fs_info *fs_info) { - return (fs_info->devfsd_last_event) ? FALSE : TRUE; -} /* End Function devfsd_queue_empty */ - + return (fs_info->devfsd_last_event) ? FALSE : TRUE; +} /* End Function devfsd_queue_empty */ /** * wait_for_devfsd_finished - Wait for devfsd to finish processing its event queue. @@ -1349,22 +1337,25 @@ static inline int devfsd_queue_empty (st * Returns %TRUE if no more waiting will be required, else %FALSE. */ -static int wait_for_devfsd_finished (struct fs_info *fs_info) +static int wait_for_devfsd_finished(struct fs_info *fs_info) { - DECLARE_WAITQUEUE (wait, current); - - if (fs_info->devfsd_task == NULL) return (TRUE); - if (devfsd_queue_empty (fs_info) && fs_info->devfsd_sleeping) return TRUE; - if ( is_devfsd_or_child (fs_info) ) return (FALSE); - set_current_state (TASK_UNINTERRUPTIBLE); - add_wait_queue (&fs_info->revalidate_wait_queue, &wait); - if (!devfsd_queue_empty (fs_info) || !fs_info->devfsd_sleeping) - if (fs_info->devfsd_task) schedule (); - remove_wait_queue (&fs_info->revalidate_wait_queue, &wait); - __set_current_state (TASK_RUNNING); - return (TRUE); -} /* End Function wait_for_devfsd_finished */ + DECLARE_WAITQUEUE(wait, current); + if (fs_info->devfsd_task == NULL) + return (TRUE); + if (devfsd_queue_empty(fs_info) && fs_info->devfsd_sleeping) + return TRUE; + if (is_devfsd_or_child(fs_info)) + return (FALSE); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&fs_info->revalidate_wait_queue, &wait); + if (!devfsd_queue_empty(fs_info) || !fs_info->devfsd_sleeping) + if (fs_info->devfsd_task) + schedule(); + remove_wait_queue(&fs_info->revalidate_wait_queue, &wait); + __set_current_state(TASK_RUNNING); + return (TRUE); +} /* End Function wait_for_devfsd_finished */ /** * devfsd_notify_de - Notify the devfsd daemon of a change. @@ -1379,35 +1370,37 @@ static int wait_for_devfsd_finished (str * Returns %TRUE if an event was queued and devfsd woken up, else %FALSE. */ -static int devfsd_notify_de (struct devfs_entry *de, - unsigned short type, umode_t mode, - uid_t uid, gid_t gid, struct fs_info *fs_info) -{ - struct devfsd_buf_entry *entry; - struct devfs_entry *curr; - - if ( !( fs_info->devfsd_event_mask & (1 << type) ) ) return (FALSE); - if ( ( entry = kmem_cache_alloc (devfsd_buf_cache, SLAB_KERNEL) ) == NULL ) - { - atomic_inc (&fs_info->devfsd_overrun_count); - return (FALSE); - } - for (curr = de; curr != NULL; curr = curr->parent) devfs_get (curr); - entry->de = de; - entry->type = type; - entry->mode = mode; - entry->uid = uid; - entry->gid = gid; - entry->next = NULL; - spin_lock (&fs_info->devfsd_buffer_lock); - if (!fs_info->devfsd_first_event) fs_info->devfsd_first_event = entry; - if (fs_info->devfsd_last_event) fs_info->devfsd_last_event->next = entry; - fs_info->devfsd_last_event = entry; - spin_unlock (&fs_info->devfsd_buffer_lock); - wake_up_interruptible (&fs_info->devfsd_wait_queue); - return (TRUE); -} /* End Function devfsd_notify_de */ - +static int devfsd_notify_de(struct devfs_entry *de, + unsigned short type, umode_t mode, + uid_t uid, gid_t gid, struct fs_info *fs_info) +{ + struct devfsd_buf_entry *entry; + struct devfs_entry *curr; + + if (!(fs_info->devfsd_event_mask & (1 << type))) + return (FALSE); + if ((entry = kmem_cache_alloc(devfsd_buf_cache, SLAB_KERNEL)) == NULL) { + atomic_inc(&fs_info->devfsd_overrun_count); + return (FALSE); + } + for (curr = de; curr != NULL; curr = curr->parent) + devfs_get(curr); + entry->de = de; + entry->type = type; + entry->mode = mode; + entry->uid = uid; + entry->gid = gid; + entry->next = NULL; + spin_lock(&fs_info->devfsd_buffer_lock); + if (!fs_info->devfsd_first_event) + fs_info->devfsd_first_event = entry; + if (fs_info->devfsd_last_event) + fs_info->devfsd_last_event->next = entry; + fs_info->devfsd_last_event = entry; + spin_unlock(&fs_info->devfsd_buffer_lock); + wake_up_interruptible(&fs_info->devfsd_wait_queue); + return (TRUE); +} /* End Function devfsd_notify_de */ /** * devfsd_notify - Notify the devfsd daemon of a change. @@ -1417,11 +1410,11 @@ static int devfsd_notify_de (struct devf * the event. */ -static void devfsd_notify (struct devfs_entry *de,unsigned short type) +static void devfsd_notify(struct devfs_entry *de, unsigned short type) { devfsd_notify_de(de, type, de->mode, current->euid, current->egid, &fs_info); -} +} static int devfs_mk_dev(dev_t dev, umode_t mode, const char *fmt, va_list args) { @@ -1432,15 +1425,15 @@ static int devfs_mk_dev(dev_t dev, umode n = vsnprintf(buf, sizeof(buf), fmt, args); if (n >= sizeof(buf) || !buf[0]) { printk(KERN_WARNING "%s: invalid format string %s\n", - __FUNCTION__, fmt); + __FUNCTION__, fmt); return -EINVAL; } - + de = _devfs_prepare_leaf(&dir, buf, mode); if (!de) { printk(KERN_WARNING "%s: could not prepare leaf for %s\n", - __FUNCTION__, buf); - return -ENOMEM; /* could be more accurate... */ + __FUNCTION__, buf); + return -ENOMEM; /* could be more accurate... */ } de->u.dev = dev; @@ -1448,12 +1441,12 @@ static int devfs_mk_dev(dev_t dev, umode error = _devfs_append_entry(dir, de, NULL); if (error) { printk(KERN_WARNING "%s: could not append to parent for %s\n", - __FUNCTION__, buf); + __FUNCTION__, buf); goto out; } devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED); - out: + out: devfs_put(dir); return error; } @@ -1464,7 +1457,7 @@ int devfs_mk_bdev(dev_t dev, umode_t mod if (!S_ISBLK(mode)) { printk(KERN_WARNING "%s: invalide mode (%u) for %s\n", - __FUNCTION__, mode, fmt); + __FUNCTION__, mode, fmt); return -EINVAL; } @@ -1474,14 +1467,13 @@ int devfs_mk_bdev(dev_t dev, umode_t mod EXPORT_SYMBOL(devfs_mk_bdev); - int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) { va_list args; if (!S_ISCHR(mode)) { printk(KERN_WARNING "%s: invalide mode (%u) for %s\n", - __FUNCTION__, mode, fmt); + __FUNCTION__, mode, fmt); return -EINVAL; } @@ -1491,7 +1483,6 @@ int devfs_mk_cdev(dev_t dev, umode_t mod EXPORT_SYMBOL(devfs_mk_cdev); - /** * _devfs_unhook - Unhook a device entry from its parents list * @de: The entry to unhook. @@ -1501,21 +1492,25 @@ EXPORT_SYMBOL(devfs_mk_cdev); * The caller must have a write lock on the parent directory. */ -static int _devfs_unhook (struct devfs_entry *de) +static int _devfs_unhook(struct devfs_entry *de) { - struct devfs_entry *parent; - - if ( !de || (de->prev == de) ) return FALSE; - parent = de->parent; - if (de->prev == NULL) parent->u.dir.first = de->next; - else de->prev->next = de->next; - if (de->next == NULL) parent->u.dir.last = de->prev; - else de->next->prev = de->prev; - de->prev = de; /* Indicate we're unhooked */ - de->next = NULL; /* Force early termination for */ - return TRUE; -} /* End Function _devfs_unhook */ + struct devfs_entry *parent; + if (!de || (de->prev == de)) + return FALSE; + parent = de->parent; + if (de->prev == NULL) + parent->u.dir.first = de->next; + else + de->prev->next = de->next; + if (de->next == NULL) + parent->u.dir.last = de->prev; + else + de->next->prev = de->prev; + de->prev = de; /* Indicate we're unhooked */ + de->next = NULL; /* Force early termination for */ + return TRUE; +} /* End Function _devfs_unhook */ /** * _devfs_unregister - Unregister a device entry from its parent. @@ -1526,83 +1521,83 @@ static int _devfs_unhook (struct devfs_e * unlocked by this function. */ -static void _devfs_unregister (struct devfs_entry *dir, struct devfs_entry *de) +static void _devfs_unregister(struct devfs_entry *dir, struct devfs_entry *de) { - int unhooked = _devfs_unhook (de); + int unhooked = _devfs_unhook(de); - write_unlock (&dir->u.dir.lock); - if (!unhooked) return; - devfs_get (dir); - devfsd_notify (de, DEVFSD_NOTIFY_UNREGISTERED); - free_dentry (de); - devfs_put (dir); - if ( !S_ISDIR (de->mode) ) return; - while (TRUE) /* Recursively unregister: this is a stack chomper */ - { - struct devfs_entry *child; - - write_lock (&de->u.dir.lock); - de->u.dir.no_more_additions = TRUE; - child = de->u.dir.first; - VERIFY_ENTRY (child); - _devfs_unregister (de, child); - if (!child) break; - DPRINTK (DEBUG_UNREGISTER, "(%s): child: %p refcount: %d\n", - child->name, child, atomic_read (&child->refcount) ); - devfs_put (child); - } -} /* End Function _devfs_unregister */ - -static int devfs_do_symlink (devfs_handle_t dir, const char *name, - const char *link, devfs_handle_t *handle) -{ - int err; - unsigned int linklength; - char *newlink; - struct devfs_entry *de; - - if (handle != NULL) *handle = NULL; - if (name == NULL) - { - PRINTK ("(): NULL name pointer\n"); - return -EINVAL; - } - if (link == NULL) - { - PRINTK ("(%s): NULL link pointer\n", name); - return -EINVAL; - } - linklength = strlen (link); - if ( ( newlink = kmalloc (linklength + 1, GFP_KERNEL) ) == NULL ) - return -ENOMEM; - memcpy (newlink, link, linklength); - newlink[linklength] = '\0'; - if ( ( de = _devfs_prepare_leaf (&dir, name, S_IFLNK | S_IRUGO | S_IXUGO) ) - == NULL ) - { - PRINTK ("(%s): could not prepare leaf\n", name); - kfree (newlink); - return -ENOTDIR; - } - de->info = NULL; - de->u.symlink.linkname = newlink; - de->u.symlink.length = linklength; - if ( ( err = _devfs_append_entry (dir, de, NULL) ) != 0 ) - { - PRINTK ("(%s): could not append to parent, err: %d\n", name, err); - devfs_put (dir); - return err; - } - devfs_put (dir); + write_unlock(&dir->u.dir.lock); + if (!unhooked) + return; + devfs_get(dir); + devfsd_notify(de, DEVFSD_NOTIFY_UNREGISTERED); + free_dentry(de); + devfs_put(dir); + if (!S_ISDIR(de->mode)) + return; + while (TRUE) { /* Recursively unregister: this is a stack chomper */ + struct devfs_entry *child; + + write_lock(&de->u.dir.lock); + de->u.dir.no_more_additions = TRUE; + child = de->u.dir.first; + VERIFY_ENTRY(child); + _devfs_unregister(de, child); + if (!child) + break; + DPRINTK(DEBUG_UNREGISTER, "(%s): child: %p refcount: %d\n", + child->name, child, atomic_read(&child->refcount)); + devfs_put(child); + } +} /* End Function _devfs_unregister */ + +static int devfs_do_symlink(devfs_handle_t dir, const char *name, + const char *link, devfs_handle_t * handle) +{ + int err; + unsigned int linklength; + char *newlink; + struct devfs_entry *de; + + if (handle != NULL) + *handle = NULL; + if (name == NULL) { + PRINTK("(): NULL name pointer\n"); + return -EINVAL; + } + if (link == NULL) { + PRINTK("(%s): NULL link pointer\n", name); + return -EINVAL; + } + linklength = strlen(link); + if ((newlink = kmalloc(linklength + 1, GFP_KERNEL)) == NULL) + return -ENOMEM; + memcpy(newlink, link, linklength); + newlink[linklength] = '\0'; + if ((de = _devfs_prepare_leaf(&dir, name, S_IFLNK | S_IRUGO | S_IXUGO)) + == NULL) { + PRINTK("(%s): could not prepare leaf\n", name); + kfree(newlink); + return -ENOTDIR; + } + de->info = NULL; + de->u.symlink.linkname = newlink; + de->u.symlink.length = linklength; + if ((err = _devfs_append_entry(dir, de, NULL)) != 0) { + PRINTK("(%s): could not append to parent, err: %d\n", name, + err); + devfs_put(dir); + return err; + } + devfs_put(dir); #ifdef CONFIG_DEVFS_DEBUG - spin_lock (&stat_lock); - stat_num_bytes += linklength + 1; - spin_unlock (&stat_lock); + spin_lock(&stat_lock); + stat_num_bytes += linklength + 1; + spin_unlock(&stat_lock); #endif - if (handle != NULL) *handle = de; - return 0; -} /* End Function devfs_do_symlink */ - + if (handle != NULL) + *handle = de; + return 0; +} /* End Function devfs_do_symlink */ /** * devfs_mk_symlink Create a symbolic link in the devfs namespace. @@ -1626,7 +1621,6 @@ int devfs_mk_symlink(const char *from, c return err; } - /** * devfs_mk_dir - Create a directory in the devfs namespace. * new name is relative to the root of the devfs. @@ -1668,19 +1662,18 @@ int devfs_mk_dir(const char *fmt, ...) goto out_put; } else if (error) { PRINTK("(%s): could not append to dir: %p \"%s\"\n", - buf, dir, dir->name); + buf, dir, dir->name); devfs_put(old); goto out_put; } - + devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED); - out_put: + out_put: devfs_put(dir); return error; } - void devfs_remove(const char *fmt, ...) { char buf[64]; @@ -1706,7 +1699,6 @@ void devfs_remove(const char *fmt, ...) } } - /** * devfs_generate_path - Generate a pathname for an entry, relative to the devfs root. * @de: The devfs entry. @@ -1718,90 +1710,93 @@ void devfs_remove(const char *fmt, ...) * else a negative error code. */ -static int devfs_generate_path (devfs_handle_t de, char *path, int buflen) +static int devfs_generate_path(devfs_handle_t de, char *path, int buflen) { - int pos; + int pos; #define NAMEOF(de) ( (de)->mode ? (de)->name : (de)->u.name ) - if (de == NULL) return -EINVAL; - VERIFY_ENTRY (de); - if (de->namelen >= buflen) return -ENAMETOOLONG; /* Must be first */ - path[buflen - 1] = '\0'; - if (de->parent == NULL) return buflen - 1; /* Don't prepend root */ - pos = buflen - de->namelen - 1; - memcpy (path + pos, NAMEOF (de), de->namelen); - for (de = de->parent; de->parent != NULL; de = de->parent) - { - if (pos - de->namelen - 1 < 0) return -ENAMETOOLONG; - path[--pos] = '/'; - pos -= de->namelen; - memcpy (path + pos, NAMEOF (de), de->namelen); - } - return pos; -} /* End Function devfs_generate_path */ + if (de == NULL) + return -EINVAL; + VERIFY_ENTRY(de); + if (de->namelen >= buflen) + return -ENAMETOOLONG; /* Must be first */ + path[buflen - 1] = '\0'; + if (de->parent == NULL) + return buflen - 1; /* Don't prepend root */ + pos = buflen - de->namelen - 1; + memcpy(path + pos, NAMEOF(de), de->namelen); + for (de = de->parent; de->parent != NULL; de = de->parent) { + if (pos - de->namelen - 1 < 0) + return -ENAMETOOLONG; + path[--pos] = '/'; + pos -= de->namelen; + memcpy(path + pos, NAMEOF(de), de->namelen); + } + return pos; +} /* End Function devfs_generate_path */ /** * devfs_setup - Process kernel boot options. * @str: The boot options after the "devfs=". */ -static int __init devfs_setup (char *str) +static int __init devfs_setup(char *str) { - static struct - { - char *name; - unsigned int mask; - unsigned int *opt; - } devfs_options_tab[] __initdata = - { + static struct { + char *name; + unsigned int mask; + unsigned int *opt; + } devfs_options_tab[] __initdata = { #ifdef CONFIG_DEVFS_DEBUG - {"dall", DEBUG_ALL, &devfs_debug_init}, - {"dmod", DEBUG_MODULE_LOAD, &devfs_debug_init}, - {"dreg", DEBUG_REGISTER, &devfs_debug_init}, - {"dunreg", DEBUG_UNREGISTER, &devfs_debug_init}, - {"dfree", DEBUG_FREE, &devfs_debug_init}, - {"diget", DEBUG_I_GET, &devfs_debug_init}, - {"dchange", DEBUG_SET_FLAGS, &devfs_debug_init}, - {"dsread", DEBUG_S_READ, &devfs_debug_init}, - {"dichange", DEBUG_I_CHANGE, &devfs_debug_init}, - {"dimknod", DEBUG_I_MKNOD, &devfs_debug_init}, - {"dilookup", DEBUG_I_LOOKUP, &devfs_debug_init}, - {"diunlink", DEBUG_I_UNLINK, &devfs_debug_init}, -#endif /* CONFIG_DEVFS_DEBUG */ - {"mount", OPTION_MOUNT, &boot_options}, - {NULL, 0, NULL} - }; - - while ( (*str != '\0') && !isspace (*str) ) - { - int i, found = 0, invert = 0; - - if (strncmp (str, "no", 2) == 0) - { - invert = 1; - str += 2; - } - for (i = 0; devfs_options_tab[i].name != NULL; i++) - { - int len = strlen (devfs_options_tab[i].name); - - if (strncmp (str, devfs_options_tab[i].name, len) == 0) - { - if (invert) - *devfs_options_tab[i].opt &= ~devfs_options_tab[i].mask; - else - *devfs_options_tab[i].opt |= devfs_options_tab[i].mask; - str += len; - found = 1; - break; - } + { + "dall", DEBUG_ALL, &devfs_debug_init}, { + "dmod", DEBUG_MODULE_LOAD, &devfs_debug_init}, { + "dreg", DEBUG_REGISTER, &devfs_debug_init}, { + "dunreg", DEBUG_UNREGISTER, &devfs_debug_init}, { + "dfree", DEBUG_FREE, &devfs_debug_init}, { + "diget", DEBUG_I_GET, &devfs_debug_init}, { + "dchange", DEBUG_SET_FLAGS, &devfs_debug_init}, { + "dsread", DEBUG_S_READ, &devfs_debug_init}, { + "dichange", DEBUG_I_CHANGE, &devfs_debug_init}, { + "dimknod", DEBUG_I_MKNOD, &devfs_debug_init}, { + "dilookup", DEBUG_I_LOOKUP, &devfs_debug_init}, { + "diunlink", DEBUG_I_UNLINK, &devfs_debug_init}, +#endif /* CONFIG_DEVFS_DEBUG */ + { + "mount", OPTION_MOUNT, &boot_options}, { + NULL, 0, NULL} + }; + + while ((*str != '\0') && !isspace(*str)) { + int i, found = 0, invert = 0; + + if (strncmp(str, "no", 2) == 0) { + invert = 1; + str += 2; + } + for (i = 0; devfs_options_tab[i].name != NULL; i++) { + int len = strlen(devfs_options_tab[i].name); + + if (strncmp(str, devfs_options_tab[i].name, len) == 0) { + if (invert) + *devfs_options_tab[i].opt &= + ~devfs_options_tab[i].mask; + else + *devfs_options_tab[i].opt |= + devfs_options_tab[i].mask; + str += len; + found = 1; + break; + } + } + if (!found) + return 0; /* No match */ + if (*str != ',') + return 0; /* No more options */ + ++str; } - if (!found) return 0; /* No match */ - if (*str != ',') return 0; /* No more options */ - ++str; - } - return 1; -} /* End Function devfs_setup */ + return 1; +} /* End Function devfs_setup */ __setup("devfs=", devfs_setup); @@ -1809,7 +1804,6 @@ EXPORT_SYMBOL(devfs_mk_symlink); EXPORT_SYMBOL(devfs_mk_dir); EXPORT_SYMBOL(devfs_remove); - /** * try_modload - Notify devfsd of an inode lookup by a non-devfsd process. * @parent: The parent devfs entry. @@ -1822,26 +1816,26 @@ EXPORT_SYMBOL(devfs_remove); * Returns 0 on success (event was queued), else a negative error code. */ -static int try_modload (struct devfs_entry *parent, struct fs_info *fs_info, - const char *name, unsigned namelen, - struct devfs_entry *buf) -{ - if ( !( fs_info->devfsd_event_mask & (1 << DEVFSD_NOTIFY_LOOKUP) ) ) - return -ENOENT; - if ( is_devfsd_or_child (fs_info) ) return -ENOENT; - memset (buf, 0, sizeof *buf); - atomic_set (&buf->refcount, 1); - buf->parent = parent; - buf->namelen = namelen; - buf->u.name = name; - WRITE_ENTRY_MAGIC (buf, MAGIC_VALUE); - if ( !devfsd_notify_de (buf, DEVFSD_NOTIFY_LOOKUP, 0, - current->euid, current->egid, fs_info) ) - return -ENOENT; - /* Possible success: event has been queued */ - return 0; -} /* End Function try_modload */ - +static int try_modload(struct devfs_entry *parent, struct fs_info *fs_info, + const char *name, unsigned namelen, + struct devfs_entry *buf) +{ + if (!(fs_info->devfsd_event_mask & (1 << DEVFSD_NOTIFY_LOOKUP))) + return -ENOENT; + if (is_devfsd_or_child(fs_info)) + return -ENOENT; + memset(buf, 0, sizeof *buf); + atomic_set(&buf->refcount, 1); + buf->parent = parent; + buf->namelen = namelen; + buf->u.name = name; + WRITE_ENTRY_MAGIC(buf, MAGIC_VALUE); + if (!devfsd_notify_de(buf, DEVFSD_NOTIFY_LOOKUP, 0, + current->euid, current->egid, fs_info)) + return -ENOENT; + /* Possible success: event has been queued */ + return 0; +} /* End Function try_modload */ /* Superblock operations follow */ @@ -1851,44 +1845,45 @@ static struct file_operations devfs_fops static struct file_operations devfs_dir_fops; static struct inode_operations devfs_symlink_iops; -static int devfs_notify_change (struct dentry *dentry, struct iattr *iattr) +static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr) { - int retval; - struct devfs_entry *de; - struct inode *inode = dentry->d_inode; - struct fs_info *fs_info = inode->i_sb->s_fs_info; - - de = get_devfs_entry_from_vfs_inode (inode); - if (de == NULL) return -ENODEV; - retval = inode_change_ok (inode, iattr); - if (retval != 0) return retval; - retval = inode_setattr (inode, iattr); - if (retval != 0) return retval; - DPRINTK (DEBUG_I_CHANGE, "(%d): VFS inode: %p devfs_entry: %p\n", - (int) inode->i_ino, inode, de); - DPRINTK (DEBUG_I_CHANGE, "(): mode: 0%o uid: %d gid: %d\n", - (int) inode->i_mode, (int) inode->i_uid, (int) inode->i_gid); - /* Inode is not on hash chains, thus must save permissions here rather - than in a write_inode() method */ - de->mode = inode->i_mode; - de->inode.uid = inode->i_uid; - de->inode.gid = inode->i_gid; - de->inode.atime = inode->i_atime; - de->inode.mtime = inode->i_mtime; - de->inode.ctime = inode->i_ctime; - if ( ( iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID) ) && - !is_devfsd_or_child (fs_info) ) - devfsd_notify_de (de, DEVFSD_NOTIFY_CHANGE, inode->i_mode, - inode->i_uid, inode->i_gid, fs_info); - return 0; -} /* End Function devfs_notify_change */ - -static struct super_operations devfs_sops = -{ - .drop_inode = generic_delete_inode, - .statfs = simple_statfs, -}; + int retval; + struct devfs_entry *de; + struct inode *inode = dentry->d_inode; + struct fs_info *fs_info = inode->i_sb->s_fs_info; + de = get_devfs_entry_from_vfs_inode(inode); + if (de == NULL) + return -ENODEV; + retval = inode_change_ok(inode, iattr); + if (retval != 0) + return retval; + retval = inode_setattr(inode, iattr); + if (retval != 0) + return retval; + DPRINTK(DEBUG_I_CHANGE, "(%d): VFS inode: %p devfs_entry: %p\n", + (int)inode->i_ino, inode, de); + DPRINTK(DEBUG_I_CHANGE, "(): mode: 0%o uid: %d gid: %d\n", + (int)inode->i_mode, (int)inode->i_uid, (int)inode->i_gid); + /* Inode is not on hash chains, thus must save permissions here rather + than in a write_inode() method */ + de->mode = inode->i_mode; + de->inode.uid = inode->i_uid; + de->inode.gid = inode->i_gid; + de->inode.atime = inode->i_atime; + de->inode.mtime = inode->i_mtime; + de->inode.ctime = inode->i_ctime; + if ((iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) && + !is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_CHANGE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + return 0; +} /* End Function devfs_notify_change */ + +static struct super_operations devfs_sops = { + .drop_inode = generic_delete_inode, + .statfs = simple_statfs, +}; /** * _devfs_get_vfs_inode - Get a VFS inode. @@ -1900,39 +1895,38 @@ static struct super_operations devfs_sop * performed if the inode is created. */ -static struct inode *_devfs_get_vfs_inode (struct super_block *sb, - struct devfs_entry *de, - struct dentry *dentry) -{ - struct inode *inode; - - if (de->prev == de) return NULL; /* Quick check to see if unhooked */ - if ( ( inode = new_inode (sb) ) == NULL ) - { - PRINTK ("(%s): new_inode() failed, de: %p\n", de->name, de); - return NULL; - } - if (de->parent) - { - read_lock (&de->parent->u.dir.lock); - if (de->prev != de) de->inode.dentry = dentry; /* Not unhooked */ - read_unlock (&de->parent->u.dir.lock); - } - else de->inode.dentry = dentry; /* Root: no locking needed */ - if (de->inode.dentry != dentry) - { /* Must have been unhooked */ - iput (inode); - return NULL; - } - /* FIXME where is devfs_put? */ - inode->u.generic_ip = devfs_get (de); - inode->i_ino = de->inode.ino; - DPRINTK (DEBUG_I_GET, "(%d): VFS inode: %p devfs_entry: %p\n", - (int) inode->i_ino, inode, de); - inode->i_blocks = 0; - inode->i_blksize = FAKE_BLOCK_SIZE; - inode->i_op = &devfs_iops; - inode->i_mode = de->mode; +static struct inode *_devfs_get_vfs_inode(struct super_block *sb, + struct devfs_entry *de, + struct dentry *dentry) +{ + struct inode *inode; + + if (de->prev == de) + return NULL; /* Quick check to see if unhooked */ + if ((inode = new_inode(sb)) == NULL) { + PRINTK("(%s): new_inode() failed, de: %p\n", de->name, de); + return NULL; + } + if (de->parent) { + read_lock(&de->parent->u.dir.lock); + if (de->prev != de) + de->inode.dentry = dentry; /* Not unhooked */ + read_unlock(&de->parent->u.dir.lock); + } else + de->inode.dentry = dentry; /* Root: no locking needed */ + if (de->inode.dentry != dentry) { /* Must have been unhooked */ + iput(inode); + return NULL; + } + /* FIXME where is devfs_put? */ + inode->u.generic_ip = devfs_get(de); + inode->i_ino = de->inode.ino; + DPRINTK(DEBUG_I_GET, "(%d): VFS inode: %p devfs_entry: %p\n", + (int)inode->i_ino, inode, de); + inode->i_blocks = 0; + inode->i_blksize = FAKE_BLOCK_SIZE; + inode->i_op = &devfs_iops; + inode->i_mode = de->mode; if (S_ISDIR(de->mode)) { inode->i_op = &devfs_dir_iops; inode->i_fop = &devfs_dir_fops; @@ -1945,100 +1939,107 @@ static struct inode *_devfs_get_vfs_inod init_special_inode(inode, de->mode, 0); } else { PRINTK("(%s): unknown mode %o de: %p\n", - de->name, de->mode, de); + de->name, de->mode, de); iput(inode); devfs_put(de); return NULL; } - inode->i_uid = de->inode.uid; - inode->i_gid = de->inode.gid; - inode->i_atime = de->inode.atime; - inode->i_mtime = de->inode.mtime; - inode->i_ctime = de->inode.ctime; - DPRINTK (DEBUG_I_GET, "(): mode: 0%o uid: %d gid: %d\n", - (int) inode->i_mode, (int) inode->i_uid, (int) inode->i_gid); - return inode; -} /* End Function _devfs_get_vfs_inode */ - + inode->i_uid = de->inode.uid; + inode->i_gid = de->inode.gid; + inode->i_atime = de->inode.atime; + inode->i_mtime = de->inode.mtime; + inode->i_ctime = de->inode.ctime; + DPRINTK(DEBUG_I_GET, "(): mode: 0%o uid: %d gid: %d\n", + (int)inode->i_mode, (int)inode->i_uid, (int)inode->i_gid); + return inode; +} /* End Function _devfs_get_vfs_inode */ /* File operations for device entries follow */ -static int devfs_readdir (struct file *file, void *dirent, filldir_t filldir) +static int devfs_readdir(struct file *file, void *dirent, filldir_t filldir) { - int err, count; - int stored = 0; - struct fs_info *fs_info; - struct devfs_entry *parent, *de, *next = NULL; - struct inode *inode = file->f_dentry->d_inode; - - fs_info = inode->i_sb->s_fs_info; - parent = get_devfs_entry_from_vfs_inode (file->f_dentry->d_inode); - if ( (long) file->f_pos < 0 ) return -EINVAL; - DPRINTK (DEBUG_F_READDIR, "(%s): fs_info: %p pos: %ld\n", - parent->name, fs_info, (long) file->f_pos); - switch ( (long) file->f_pos ) - { - case 0: - err = (*filldir) (dirent, "..", 2, file->f_pos, - parent_ino (file->f_dentry), DT_DIR); - if (err == -EINVAL) break; - if (err < 0) return err; - file->f_pos++; - ++stored; - /* Fall through */ - case 1: - err = (*filldir) (dirent, ".", 1, file->f_pos, inode->i_ino, DT_DIR); - if (err == -EINVAL) break; - if (err < 0) return err; - file->f_pos++; - ++stored; - /* Fall through */ - default: - /* Skip entries */ - count = file->f_pos - 2; - read_lock (&parent->u.dir.lock); - for (de = parent->u.dir.first; de && (count > 0); de = de->next) - --count; - devfs_get (de); - read_unlock (&parent->u.dir.lock); - /* Now add all remaining entries */ - while (de) - { - err = (*filldir) (dirent, de->name, de->namelen, - file->f_pos, de->inode.ino, de->mode >> 12); - if (err < 0) devfs_put (de); - else - { - file->f_pos++; - ++stored; - } - if (err == -EINVAL) break; - if (err < 0) return err; - read_lock (&parent->u.dir.lock); - next = devfs_get (de->next); - read_unlock (&parent->u.dir.lock); - devfs_put (de); - de = next; - } - break; - } - return stored; -} /* End Function devfs_readdir */ + int err, count; + int stored = 0; + struct fs_info *fs_info; + struct devfs_entry *parent, *de, *next = NULL; + struct inode *inode = file->f_dentry->d_inode; + + fs_info = inode->i_sb->s_fs_info; + parent = get_devfs_entry_from_vfs_inode(file->f_dentry->d_inode); + if ((long)file->f_pos < 0) + return -EINVAL; + DPRINTK(DEBUG_F_READDIR, "(%s): fs_info: %p pos: %ld\n", + parent->name, fs_info, (long)file->f_pos); + switch ((long)file->f_pos) { + case 0: + err = (*filldir) (dirent, "..", 2, file->f_pos, + parent_ino(file->f_dentry), DT_DIR); + if (err == -EINVAL) + break; + if (err < 0) + return err; + file->f_pos++; + ++stored; + /* Fall through */ + case 1: + err = + (*filldir) (dirent, ".", 1, file->f_pos, inode->i_ino, + DT_DIR); + if (err == -EINVAL) + break; + if (err < 0) + return err; + file->f_pos++; + ++stored; + /* Fall through */ + default: + /* Skip entries */ + count = file->f_pos - 2; + read_lock(&parent->u.dir.lock); + for (de = parent->u.dir.first; de && (count > 0); de = de->next) + --count; + devfs_get(de); + read_unlock(&parent->u.dir.lock); + /* Now add all remaining entries */ + while (de) { + err = (*filldir) (dirent, de->name, de->namelen, + file->f_pos, de->inode.ino, + de->mode >> 12); + if (err < 0) + devfs_put(de); + else { + file->f_pos++; + ++stored; + } + if (err == -EINVAL) + break; + if (err < 0) + return err; + read_lock(&parent->u.dir.lock); + next = devfs_get(de->next); + read_unlock(&parent->u.dir.lock); + devfs_put(de); + de = next; + } + break; + } + return stored; +} /* End Function devfs_readdir */ /* Open devfs specific special files */ -static int devfs_open (struct inode *inode, struct file *file) +static int devfs_open(struct inode *inode, struct file *file) { int err; int minor = MINOR(inode->i_rdev); struct file_operations *old_fops, *new_fops; switch (minor) { - case 0: /* /dev/.devfsd */ + case 0: /* /dev/.devfsd */ new_fops = fops_get(&devfsd_fops); break; #ifdef CONFIG_DEVFS_DEBUG - case 1: /* /dev/.stat */ + case 1: /* /dev/.stat */ new_fops = fops_get(&stat_fops); break; #endif @@ -2057,32 +2058,28 @@ static int devfs_open (struct inode *ino } else fops_put(old_fops); return err; -} /* End Function devfs_open */ +} /* End Function devfs_open */ -static struct file_operations devfs_fops = -{ - .open = devfs_open, +static struct file_operations devfs_fops = { + .open = devfs_open, }; -static struct file_operations devfs_dir_fops = -{ - .read = generic_read_dir, - .readdir = devfs_readdir, +static struct file_operations devfs_dir_fops = { + .read = generic_read_dir, + .readdir = devfs_readdir, }; - /* Dentry operations for device entries follow */ - /** * devfs_d_release - Callback for when a dentry is freed. * @dentry: The dentry. */ -static void devfs_d_release (struct dentry *dentry) +static void devfs_d_release(struct dentry *dentry) { - DPRINTK (DEBUG_D_RELEASE, "(%p): inode: %p\n", dentry, dentry->d_inode); -} /* End Function devfs_d_release */ + DPRINTK(DEBUG_D_RELEASE, "(%p): inode: %p\n", dentry, dentry->d_inode); +} /* End Function devfs_d_release */ /** * devfs_d_iput - Callback for when a dentry loses its inode. @@ -2090,38 +2087,37 @@ static void devfs_d_release (struct dent * @inode: The inode. */ -static void devfs_d_iput (struct dentry *dentry, struct inode *inode) +static void devfs_d_iput(struct dentry *dentry, struct inode *inode) { - struct devfs_entry *de; + struct devfs_entry *de; - de = get_devfs_entry_from_vfs_inode (inode); - DPRINTK (DEBUG_D_IPUT,"(%s): dentry: %p inode: %p de: %p de->dentry: %p\n", - de->name, dentry, inode, de, de->inode.dentry); - if ( de->inode.dentry && (de->inode.dentry != dentry) ) - OOPS ("(%s): de: %p dentry: %p de->dentry: %p\n", - de->name, de, dentry, de->inode.dentry); - de->inode.dentry = NULL; - iput (inode); - devfs_put (de); -} /* End Function devfs_d_iput */ - -static int devfs_d_delete (struct dentry *dentry); - -static struct dentry_operations devfs_dops = -{ - .d_delete = devfs_d_delete, - .d_release = devfs_d_release, - .d_iput = devfs_d_iput, + de = get_devfs_entry_from_vfs_inode(inode); + DPRINTK(DEBUG_D_IPUT, + "(%s): dentry: %p inode: %p de: %p de->dentry: %p\n", de->name, + dentry, inode, de, de->inode.dentry); + if (de->inode.dentry && (de->inode.dentry != dentry)) + OOPS("(%s): de: %p dentry: %p de->dentry: %p\n", + de->name, de, dentry, de->inode.dentry); + de->inode.dentry = NULL; + iput(inode); + devfs_put(de); +} /* End Function devfs_d_iput */ + +static int devfs_d_delete(struct dentry *dentry); + +static struct dentry_operations devfs_dops = { + .d_delete = devfs_d_delete, + .d_release = devfs_d_release, + .d_iput = devfs_d_iput, }; -static int devfs_d_revalidate_wait (struct dentry *dentry, struct nameidata *); +static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *); -static struct dentry_operations devfs_wait_dops = -{ - .d_delete = devfs_d_delete, - .d_release = devfs_d_release, - .d_iput = devfs_d_iput, - .d_revalidate = devfs_d_revalidate_wait, +static struct dentry_operations devfs_wait_dops = { + .d_delete = devfs_d_delete, + .d_release = devfs_d_release, + .d_iput = devfs_d_iput, + .d_revalidate = devfs_d_revalidate_wait, }; /** @@ -2129,653 +2125,673 @@ static struct dentry_operations devfs_wa * @dentry: The dentry. */ -static int devfs_d_delete (struct dentry *dentry) +static int devfs_d_delete(struct dentry *dentry) { - struct inode *inode = dentry->d_inode; + struct inode *inode = dentry->d_inode; - if (dentry->d_op == &devfs_wait_dops) dentry->d_op = &devfs_dops; - /* Unhash dentry if negative (has no inode) */ - if (inode == NULL) - { - DPRINTK (DEBUG_D_DELETE, "(%p): dropping negative dentry\n", dentry); - return 1; - } - return 0; -} /* End Function devfs_d_delete */ + if (dentry->d_op == &devfs_wait_dops) + dentry->d_op = &devfs_dops; + /* Unhash dentry if negative (has no inode) */ + if (inode == NULL) { + DPRINTK(DEBUG_D_DELETE, "(%p): dropping negative dentry\n", + dentry); + return 1; + } + return 0; +} /* End Function devfs_d_delete */ -struct devfs_lookup_struct -{ - devfs_handle_t de; - wait_queue_head_t wait_queue; +struct devfs_lookup_struct { + devfs_handle_t de; + wait_queue_head_t wait_queue; }; /* XXX: this doesn't handle the case where we got a negative dentry but a devfs entry has been registered in the meanwhile */ -static int devfs_d_revalidate_wait (struct dentry *dentry, struct nameidata *nd) +static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *nd) { - struct inode *dir = dentry->d_parent->d_inode; - struct fs_info *fs_info = dir->i_sb->s_fs_info; - devfs_handle_t parent = get_devfs_entry_from_vfs_inode (dir); - struct devfs_lookup_struct *lookup_info = dentry->d_fsdata; - DECLARE_WAITQUEUE (wait, current); - int need_lock; - - /* - * FIXME HACK - * - * make sure that - * d_instantiate always runs under lock - * we release i_sem lock before going to sleep - * - * unfortunately sometimes d_revalidate is called with - * and sometimes without i_sem lock held. The following checks - * attempt to deduce when we need to add (and drop resp.) lock - * here. This relies on current (2.6.2) calling coventions: - * - * lookup_hash is always run under i_sem and is passing NULL - * as nd - * - * open(...,O_CREATE,...) calls _lookup_hash under i_sem - * and sets flags to LOOKUP_OPEN|LOOKUP_CREATE - * - * all other invocations of ->d_revalidate seem to happen - * outside of i_sem - */ - need_lock = nd && - (!(nd->flags & LOOKUP_CREATE) || (nd->flags & LOOKUP_PARENT)); - - if (need_lock) - down(&dir->i_sem); - - if ( is_devfsd_or_child (fs_info) ) - { - devfs_handle_t de = lookup_info->de; + struct inode *dir = dentry->d_parent->d_inode; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + devfs_handle_t parent = get_devfs_entry_from_vfs_inode(dir); + struct devfs_lookup_struct *lookup_info = dentry->d_fsdata; + DECLARE_WAITQUEUE(wait, current); + int need_lock; + + /* + * FIXME HACK + * + * make sure that + * d_instantiate always runs under lock + * we release i_sem lock before going to sleep + * + * unfortunately sometimes d_revalidate is called with + * and sometimes without i_sem lock held. The following checks + * attempt to deduce when we need to add (and drop resp.) lock + * here. This relies on current (2.6.2) calling coventions: + * + * lookup_hash is always run under i_sem and is passing NULL + * as nd + * + * open(...,O_CREATE,...) calls _lookup_hash under i_sem + * and sets flags to LOOKUP_OPEN|LOOKUP_CREATE + * + * all other invocations of ->d_revalidate seem to happen + * outside of i_sem + */ + need_lock = nd && + (!(nd->flags & LOOKUP_CREATE) || (nd->flags & LOOKUP_PARENT)); + + if (need_lock) + down(&dir->i_sem); + + if (is_devfsd_or_child(fs_info)) { + devfs_handle_t de = lookup_info->de; + struct inode *inode; + + DPRINTK(DEBUG_I_LOOKUP, + "(%s): dentry: %p inode: %p de: %p by: \"%s\"\n", + dentry->d_name.name, dentry, dentry->d_inode, de, + current->comm); + if (dentry->d_inode) + goto out; + if (de == NULL) { + read_lock(&parent->u.dir.lock); + de = _devfs_search_dir(parent, dentry->d_name.name, + dentry->d_name.len); + read_unlock(&parent->u.dir.lock); + if (de == NULL) + goto out; + lookup_info->de = de; + } + /* Create an inode, now that the driver information is available */ + inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry); + if (!inode) + goto out; + DPRINTK(DEBUG_I_LOOKUP, + "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", + de->name, de->inode.ino, inode, de, current->comm); + d_instantiate(dentry, inode); + goto out; + } + if (lookup_info == NULL) + goto out; /* Early termination */ + read_lock(&parent->u.dir.lock); + if (dentry->d_fsdata) { + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&lookup_info->wait_queue, &wait); + read_unlock(&parent->u.dir.lock); + /* at this point it is always (hopefully) locked */ + up(&dir->i_sem); + schedule(); + down(&dir->i_sem); + /* + * This does not need nor should remove wait from wait_queue. + * Wait queue head is never reused - nothing is ever added to it + * after all waiters have been waked up and head itself disappears + * very soon after it. Moreover it is local variable on stack that + * is likely to have already disappeared so any reference to it + * at this point is buggy. + */ + + } else + read_unlock(&parent->u.dir.lock); + + out: + if (need_lock) + up(&dir->i_sem); + return 1; +} /* End Function devfs_d_revalidate_wait */ + +/* Inode operations for device entries follow */ + +static struct dentry *devfs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +{ + struct devfs_entry tmp; /* Must stay in scope until devfsd idle again */ + struct devfs_lookup_struct lookup_info; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + struct devfs_entry *parent, *de; struct inode *inode; + struct dentry *retval = NULL; - DPRINTK (DEBUG_I_LOOKUP, - "(%s): dentry: %p inode: %p de: %p by: \"%s\"\n", - dentry->d_name.name, dentry, dentry->d_inode, de, - current->comm); + /* Set up the dentry operations before anything else, to ensure cleaning + up on any error */ + dentry->d_op = &devfs_dops; + /* First try to get the devfs entry for this directory */ + parent = get_devfs_entry_from_vfs_inode(dir); + DPRINTK(DEBUG_I_LOOKUP, "(%s): dentry: %p parent: %p by: \"%s\"\n", + dentry->d_name.name, dentry, parent, current->comm); + if (parent == NULL) + return ERR_PTR(-ENOENT); + read_lock(&parent->u.dir.lock); + de = _devfs_search_dir(parent, dentry->d_name.name, dentry->d_name.len); + read_unlock(&parent->u.dir.lock); + lookup_info.de = de; + init_waitqueue_head(&lookup_info.wait_queue); + dentry->d_fsdata = &lookup_info; + if (de == NULL) { /* Try with devfsd. For any kind of failure, leave a negative dentry + so someone else can deal with it (in the case where the sysadmin + does a mknod()). It's important to do this before hashing the + dentry, so that the devfsd queue is filled before revalidates + can start */ + if (try_modload(parent, fs_info, dentry->d_name.name, dentry->d_name.len, &tmp) < 0) { /* Lookup event was not queued to devfsd */ + d_add(dentry, NULL); + return NULL; + } + } + dentry->d_op = &devfs_wait_dops; + d_add(dentry, NULL); /* Open the floodgates */ + /* Unlock directory semaphore, which will release any waiters. They + will get the hashed dentry, and may be forced to wait for + revalidation */ + up(&dir->i_sem); + wait_for_devfsd_finished(fs_info); /* If I'm not devfsd, must wait */ + down(&dir->i_sem); /* Grab it again because them's the rules */ + de = lookup_info.de; + /* If someone else has been so kind as to make the inode, we go home + early */ if (dentry->d_inode) - goto out; - if (de == NULL) - { - read_lock (&parent->u.dir.lock); - de = _devfs_search_dir (parent, dentry->d_name.name, - dentry->d_name.len); - read_unlock (&parent->u.dir.lock); - if (de == NULL) goto out; - lookup_info->de = de; + if (de == NULL) { + read_lock(&parent->u.dir.lock); + de = _devfs_search_dir(parent, dentry->d_name.name, + dentry->d_name.len); + read_unlock(&parent->u.dir.lock); + if (de == NULL) + goto out; + /* OK, there's an entry now, but no VFS inode yet */ } /* Create an inode, now that the driver information is available */ - inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry); - if (!inode) - goto out; - DPRINTK (DEBUG_I_LOOKUP, - "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", - de->name, de->inode.ino, inode, de, current->comm); - d_instantiate (dentry, inode); - goto out; - } - if (lookup_info == NULL) - goto out; /* Early termination */ - read_lock (&parent->u.dir.lock); - if (dentry->d_fsdata) - { - set_current_state (TASK_UNINTERRUPTIBLE); - add_wait_queue (&lookup_info->wait_queue, &wait); - read_unlock (&parent->u.dir.lock); - /* at this point it is always (hopefully) locked */ - up(&dir->i_sem); - schedule (); - down(&dir->i_sem); - /* - * This does not need nor should remove wait from wait_queue. - * Wait queue head is never reused - nothing is ever added to it - * after all waiters have been waked up and head itself disappears - * very soon after it. Moreover it is local variable on stack that - * is likely to have already disappeared so any reference to it - * at this point is buggy. - */ + inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry); + if (!inode) { + retval = ERR_PTR(-ENOMEM); + goto out; + } + DPRINTK(DEBUG_I_LOOKUP, + "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", de->name, + de->inode.ino, inode, de, current->comm); + d_instantiate(dentry, inode); + out: + write_lock(&parent->u.dir.lock); + dentry->d_op = &devfs_dops; + dentry->d_fsdata = NULL; + wake_up(&lookup_info.wait_queue); + write_unlock(&parent->u.dir.lock); + devfs_put(de); + return retval; +} /* End Function devfs_lookup */ + +static int devfs_unlink(struct inode *dir, struct dentry *dentry) +{ + int unhooked; + struct devfs_entry *de; + struct inode *inode = dentry->d_inode; + struct fs_info *fs_info = dir->i_sb->s_fs_info; - } - else read_unlock (&parent->u.dir.lock); + de = get_devfs_entry_from_vfs_inode(inode); + DPRINTK(DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de); + if (de == NULL) + return -ENOENT; + if (!de->vfs) + return -EPERM; + write_lock(&de->parent->u.dir.lock); + unhooked = _devfs_unhook(de); + write_unlock(&de->parent->u.dir.lock); + if (!unhooked) + return -ENOENT; + if (!is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_DELETE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + free_dentry(de); + devfs_put(de); + return 0; +} /* End Function devfs_unlink */ -out: - if (need_lock) - up(&dir->i_sem); - return 1; -} /* End Function devfs_d_revalidate_wait */ +static int devfs_symlink(struct inode *dir, struct dentry *dentry, + const char *symname) +{ + int err; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + struct devfs_entry *parent, *de; + struct inode *inode; + /* First try to get the devfs entry for this directory */ + parent = get_devfs_entry_from_vfs_inode(dir); + if (parent == NULL) + return -ENOENT; + err = devfs_do_symlink(parent, dentry->d_name.name, symname, &de); + DPRINTK(DEBUG_DISABLED, "(%s): errcode from : %d\n", + dentry->d_name.name, err); + if (err < 0) + return err; + de->vfs = TRUE; + de->inode.uid = current->euid; + de->inode.gid = current->egid; + de->inode.atime = CURRENT_TIME; + de->inode.mtime = CURRENT_TIME; + de->inode.ctime = CURRENT_TIME; + if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL) + return -ENOMEM; + DPRINTK(DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n", + dentry->d_name.name, de->inode.ino, inode, dentry); + d_instantiate(dentry, inode); + if (!is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + return 0; +} /* End Function devfs_symlink */ -/* Inode operations for device entries follow */ +static int devfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + int err; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + struct devfs_entry *parent, *de; + struct inode *inode; -static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd) + mode = (mode & ~S_IFMT) | S_IFDIR; /* VFS doesn't pass S_IFMT part */ + parent = get_devfs_entry_from_vfs_inode(dir); + if (parent == NULL) + return -ENOENT; + de = _devfs_alloc_entry(dentry->d_name.name, dentry->d_name.len, mode); + if (!de) + return -ENOMEM; + de->vfs = TRUE; + if ((err = _devfs_append_entry(parent, de, NULL)) != 0) + return err; + de->inode.uid = current->euid; + de->inode.gid = current->egid; + de->inode.atime = CURRENT_TIME; + de->inode.mtime = CURRENT_TIME; + de->inode.ctime = CURRENT_TIME; + if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL) + return -ENOMEM; + DPRINTK(DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n", + dentry->d_name.name, de->inode.ino, inode, dentry); + d_instantiate(dentry, inode); + if (!is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + return 0; +} /* End Function devfs_mkdir */ + +static int devfs_rmdir(struct inode *dir, struct dentry *dentry) +{ + int err = 0; + struct devfs_entry *de; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + struct inode *inode = dentry->d_inode; + + if (dir->i_sb->s_fs_info != inode->i_sb->s_fs_info) + return -EINVAL; + de = get_devfs_entry_from_vfs_inode(inode); + if (de == NULL) + return -ENOENT; + if (!S_ISDIR(de->mode)) + return -ENOTDIR; + if (!de->vfs) + return -EPERM; + /* First ensure the directory is empty and will stay that way */ + write_lock(&de->u.dir.lock); + if (de->u.dir.first) + err = -ENOTEMPTY; + else + de->u.dir.no_more_additions = TRUE; + write_unlock(&de->u.dir.lock); + if (err) + return err; + /* Now unhook the directory from its parent */ + write_lock(&de->parent->u.dir.lock); + if (!_devfs_unhook(de)) + err = -ENOENT; + write_unlock(&de->parent->u.dir.lock); + if (err) + return err; + if (!is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_DELETE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + free_dentry(de); + devfs_put(de); + return 0; +} /* End Function devfs_rmdir */ + +static int devfs_mknod(struct inode *dir, struct dentry *dentry, int mode, + dev_t rdev) { - struct devfs_entry tmp; /* Must stay in scope until devfsd idle again */ - struct devfs_lookup_struct lookup_info; - struct fs_info *fs_info = dir->i_sb->s_fs_info; - struct devfs_entry *parent, *de; - struct inode *inode; - struct dentry *retval = NULL; - - /* Set up the dentry operations before anything else, to ensure cleaning - up on any error */ - dentry->d_op = &devfs_dops; - /* First try to get the devfs entry for this directory */ - parent = get_devfs_entry_from_vfs_inode (dir); - DPRINTK (DEBUG_I_LOOKUP, "(%s): dentry: %p parent: %p by: \"%s\"\n", - dentry->d_name.name, dentry, parent, current->comm); - if (parent == NULL) return ERR_PTR (-ENOENT); - read_lock (&parent->u.dir.lock); - de = _devfs_search_dir (parent, dentry->d_name.name, dentry->d_name.len); - read_unlock (&parent->u.dir.lock); - lookup_info.de = de; - init_waitqueue_head (&lookup_info.wait_queue); - dentry->d_fsdata = &lookup_info; - if (de == NULL) - { /* Try with devfsd. For any kind of failure, leave a negative dentry - so someone else can deal with it (in the case where the sysadmin - does a mknod()). It's important to do this before hashing the - dentry, so that the devfsd queue is filled before revalidates - can start */ - if (try_modload (parent, fs_info, - dentry->d_name.name, dentry->d_name.len, &tmp) < 0) - { /* Lookup event was not queued to devfsd */ - d_add (dentry, NULL); - return NULL; - } - } - dentry->d_op = &devfs_wait_dops; - d_add (dentry, NULL); /* Open the floodgates */ - /* Unlock directory semaphore, which will release any waiters. They - will get the hashed dentry, and may be forced to wait for - revalidation */ - up (&dir->i_sem); - wait_for_devfsd_finished (fs_info); /* If I'm not devfsd, must wait */ - down (&dir->i_sem); /* Grab it again because them's the rules */ - de = lookup_info.de; - /* If someone else has been so kind as to make the inode, we go home - early */ - if (dentry->d_inode) goto out; - if (de == NULL) - { - read_lock (&parent->u.dir.lock); - de = _devfs_search_dir (parent, dentry->d_name.name, - dentry->d_name.len); - read_unlock (&parent->u.dir.lock); - if (de == NULL) goto out; - /* OK, there's an entry now, but no VFS inode yet */ - } - /* Create an inode, now that the driver information is available */ - inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry); - if (!inode) - { - retval = ERR_PTR (-ENOMEM); - goto out; - } - DPRINTK (DEBUG_I_LOOKUP, "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", - de->name, de->inode.ino, inode, de, current->comm); - d_instantiate (dentry, inode); -out: - write_lock (&parent->u.dir.lock); - dentry->d_op = &devfs_dops; - dentry->d_fsdata = NULL; - wake_up (&lookup_info.wait_queue); - write_unlock (&parent->u.dir.lock); - devfs_put (de); - return retval; -} /* End Function devfs_lookup */ - -static int devfs_unlink (struct inode *dir, struct dentry *dentry) -{ - int unhooked; - struct devfs_entry *de; - struct inode *inode = dentry->d_inode; - struct fs_info *fs_info = dir->i_sb->s_fs_info; - - de = get_devfs_entry_from_vfs_inode (inode); - DPRINTK (DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de); - if (de == NULL) return -ENOENT; - if (!de->vfs) return -EPERM; - write_lock (&de->parent->u.dir.lock); - unhooked = _devfs_unhook (de); - write_unlock (&de->parent->u.dir.lock); - if (!unhooked) return -ENOENT; - if ( !is_devfsd_or_child (fs_info) ) - devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode, - inode->i_uid, inode->i_gid, fs_info); - free_dentry (de); - devfs_put (de); - return 0; -} /* End Function devfs_unlink */ - -static int devfs_symlink (struct inode *dir, struct dentry *dentry, - const char *symname) -{ - int err; - struct fs_info *fs_info = dir->i_sb->s_fs_info; - struct devfs_entry *parent, *de; - struct inode *inode; - - /* First try to get the devfs entry for this directory */ - parent = get_devfs_entry_from_vfs_inode (dir); - if (parent == NULL) return -ENOENT; - err = devfs_do_symlink (parent, dentry->d_name.name, symname, &de); - DPRINTK (DEBUG_DISABLED, "(%s): errcode from : %d\n", - dentry->d_name.name, err); - if (err < 0) return err; - de->vfs = TRUE; - de->inode.uid = current->euid; - de->inode.gid = current->egid; - de->inode.atime = CURRENT_TIME; - de->inode.mtime = CURRENT_TIME; - de->inode.ctime = CURRENT_TIME; - if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL ) - return -ENOMEM; - DPRINTK (DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n", - dentry->d_name.name, de->inode.ino, inode, dentry); - d_instantiate (dentry, inode); - if ( !is_devfsd_or_child (fs_info) ) - devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode, - inode->i_uid, inode->i_gid, fs_info); - return 0; -} /* End Function devfs_symlink */ - -static int devfs_mkdir (struct inode *dir, struct dentry *dentry, int mode) -{ - int err; - struct fs_info *fs_info = dir->i_sb->s_fs_info; - struct devfs_entry *parent, *de; - struct inode *inode; - - mode = (mode & ~S_IFMT) | S_IFDIR; /* VFS doesn't pass S_IFMT part */ - parent = get_devfs_entry_from_vfs_inode (dir); - if (parent == NULL) return -ENOENT; - de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode); - if (!de) return -ENOMEM; - de->vfs = TRUE; - if ( ( err = _devfs_append_entry (parent, de, NULL) ) != 0 ) - return err; - de->inode.uid = current->euid; - de->inode.gid = current->egid; - de->inode.atime = CURRENT_TIME; - de->inode.mtime = CURRENT_TIME; - de->inode.ctime = CURRENT_TIME; - if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL ) - return -ENOMEM; - DPRINTK (DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n", - dentry->d_name.name, de->inode.ino, inode, dentry); - d_instantiate (dentry, inode); - if ( !is_devfsd_or_child (fs_info) ) - devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode, - inode->i_uid, inode->i_gid, fs_info); - return 0; -} /* End Function devfs_mkdir */ - -static int devfs_rmdir (struct inode *dir, struct dentry *dentry) -{ - int err = 0; - struct devfs_entry *de; - struct fs_info *fs_info = dir->i_sb->s_fs_info; - struct inode *inode = dentry->d_inode; - - if (dir->i_sb->s_fs_info != inode->i_sb->s_fs_info) return -EINVAL; - de = get_devfs_entry_from_vfs_inode (inode); - if (de == NULL) return -ENOENT; - if ( !S_ISDIR (de->mode) ) return -ENOTDIR; - if (!de->vfs) return -EPERM; - /* First ensure the directory is empty and will stay that way */ - write_lock (&de->u.dir.lock); - if (de->u.dir.first) err = -ENOTEMPTY; - else de->u.dir.no_more_additions = TRUE; - write_unlock (&de->u.dir.lock); - if (err) return err; - /* Now unhook the directory from its parent */ - write_lock (&de->parent->u.dir.lock); - if ( !_devfs_unhook (de) ) err = -ENOENT; - write_unlock (&de->parent->u.dir.lock); - if (err) return err; - if ( !is_devfsd_or_child (fs_info) ) - devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode, - inode->i_uid, inode->i_gid, fs_info); - free_dentry (de); - devfs_put (de); - return 0; -} /* End Function devfs_rmdir */ - -static int devfs_mknod (struct inode *dir, struct dentry *dentry, int mode, - dev_t rdev) -{ - int err; - struct fs_info *fs_info = dir->i_sb->s_fs_info; - struct devfs_entry *parent, *de; - struct inode *inode; - - DPRINTK (DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %u:%u\n", - dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); - parent = get_devfs_entry_from_vfs_inode (dir); - if (parent == NULL) return -ENOENT; - de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode); - if (!de) return -ENOMEM; - de->vfs = TRUE; - if (S_ISCHR(mode) || S_ISBLK(mode)) - de->u.dev = rdev; - if ( ( err = _devfs_append_entry (parent, de, NULL) ) != 0 ) + int err; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + struct devfs_entry *parent, *de; + struct inode *inode; + + DPRINTK(DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %u:%u\n", + dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); + parent = get_devfs_entry_from_vfs_inode(dir); + if (parent == NULL) + return -ENOENT; + de = _devfs_alloc_entry(dentry->d_name.name, dentry->d_name.len, mode); + if (!de) + return -ENOMEM; + de->vfs = TRUE; + if (S_ISCHR(mode) || S_ISBLK(mode)) + de->u.dev = rdev; + if ((err = _devfs_append_entry(parent, de, NULL)) != 0) + return err; + de->inode.uid = current->euid; + de->inode.gid = current->egid; + de->inode.atime = CURRENT_TIME; + de->inode.mtime = CURRENT_TIME; + de->inode.ctime = CURRENT_TIME; + if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL) + return -ENOMEM; + DPRINTK(DEBUG_I_MKNOD, ": new VFS inode(%u): %p dentry: %p\n", + de->inode.ino, inode, dentry); + d_instantiate(dentry, inode); + if (!is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + return 0; +} /* End Function devfs_mknod */ + +static int devfs_readlink(struct dentry *dentry, char *buffer, int buflen) +{ + int err; + struct devfs_entry *de; + + de = get_devfs_entry_from_vfs_inode(dentry->d_inode); + if (!de) + return -ENODEV; + err = vfs_readlink(dentry, buffer, buflen, de->u.symlink.linkname); return err; - de->inode.uid = current->euid; - de->inode.gid = current->egid; - de->inode.atime = CURRENT_TIME; - de->inode.mtime = CURRENT_TIME; - de->inode.ctime = CURRENT_TIME; - if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL ) - return -ENOMEM; - DPRINTK (DEBUG_I_MKNOD, ": new VFS inode(%u): %p dentry: %p\n", - de->inode.ino, inode, dentry); - d_instantiate (dentry, inode); - if ( !is_devfsd_or_child (fs_info) ) - devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode, - inode->i_uid, inode->i_gid, fs_info); - return 0; -} /* End Function devfs_mknod */ - -static int devfs_readlink (struct dentry *dentry, char *buffer, int buflen) -{ - int err; - struct devfs_entry *de; - - de = get_devfs_entry_from_vfs_inode (dentry->d_inode); - if (!de) return -ENODEV; - err = vfs_readlink (dentry, buffer, buflen, de->u.symlink.linkname); - return err; -} /* End Function devfs_readlink */ - -static int devfs_follow_link (struct dentry *dentry, struct nameidata *nd) -{ - int err; - struct devfs_entry *de; - - de = get_devfs_entry_from_vfs_inode (dentry->d_inode); - if (!de) return -ENODEV; - err = vfs_follow_link (nd, de->u.symlink.linkname); - return err; -} /* End Function devfs_follow_link */ +} /* End Function devfs_readlink */ -static struct inode_operations devfs_iops = +static int devfs_follow_link(struct dentry *dentry, struct nameidata *nd) { - .setattr = devfs_notify_change, + int err; + struct devfs_entry *de; + + de = get_devfs_entry_from_vfs_inode(dentry->d_inode); + if (!de) + return -ENODEV; + err = vfs_follow_link(nd, de->u.symlink.linkname); + return err; +} /* End Function devfs_follow_link */ + +static struct inode_operations devfs_iops = { + .setattr = devfs_notify_change, }; -static struct inode_operations devfs_dir_iops = -{ - .lookup = devfs_lookup, - .unlink = devfs_unlink, - .symlink = devfs_symlink, - .mkdir = devfs_mkdir, - .rmdir = devfs_rmdir, - .mknod = devfs_mknod, - .setattr = devfs_notify_change, +static struct inode_operations devfs_dir_iops = { + .lookup = devfs_lookup, + .unlink = devfs_unlink, + .symlink = devfs_symlink, + .mkdir = devfs_mkdir, + .rmdir = devfs_rmdir, + .mknod = devfs_mknod, + .setattr = devfs_notify_change, }; -static struct inode_operations devfs_symlink_iops = -{ - .readlink = devfs_readlink, - .follow_link = devfs_follow_link, - .setattr = devfs_notify_change, +static struct inode_operations devfs_symlink_iops = { + .readlink = devfs_readlink, + .follow_link = devfs_follow_link, + .setattr = devfs_notify_change, }; -static int devfs_fill_super (struct super_block *sb, void *data, int silent) +static int devfs_fill_super(struct super_block *sb, void *data, int silent) { - struct inode *root_inode = NULL; + struct inode *root_inode = NULL; + + if (_devfs_get_root_entry() == NULL) + goto out_no_root; + atomic_set(&fs_info.devfsd_overrun_count, 0); + init_waitqueue_head(&fs_info.devfsd_wait_queue); + init_waitqueue_head(&fs_info.revalidate_wait_queue); + fs_info.sb = sb; + sb->s_fs_info = &fs_info; + sb->s_blocksize = 1024; + sb->s_blocksize_bits = 10; + sb->s_magic = DEVFS_SUPER_MAGIC; + sb->s_op = &devfs_sops; + if ((root_inode = _devfs_get_vfs_inode(sb, root_entry, NULL)) == NULL) + goto out_no_root; + sb->s_root = d_alloc_root(root_inode); + if (!sb->s_root) + goto out_no_root; + DPRINTK(DEBUG_S_READ, "(): made devfs ptr: %p\n", sb->s_fs_info); + return 0; + + out_no_root: + PRINTK("(): get root inode failed\n"); + if (root_inode) + iput(root_inode); + return -EINVAL; +} /* End Function devfs_fill_super */ - if (_devfs_get_root_entry () == NULL) goto out_no_root; - atomic_set (&fs_info.devfsd_overrun_count, 0); - init_waitqueue_head (&fs_info.devfsd_wait_queue); - init_waitqueue_head (&fs_info.revalidate_wait_queue); - fs_info.sb = sb; - sb->s_fs_info = &fs_info; - sb->s_blocksize = 1024; - sb->s_blocksize_bits = 10; - sb->s_magic = DEVFS_SUPER_MAGIC; - sb->s_op = &devfs_sops; - if ( ( root_inode = _devfs_get_vfs_inode (sb, root_entry, NULL) ) == NULL ) - goto out_no_root; - sb->s_root = d_alloc_root (root_inode); - if (!sb->s_root) goto out_no_root; - DPRINTK (DEBUG_S_READ, "(): made devfs ptr: %p\n", sb->s_fs_info); - return 0; - -out_no_root: - PRINTK ("(): get root inode failed\n"); - if (root_inode) iput (root_inode); - return -EINVAL; -} /* End Function devfs_fill_super */ - -static struct super_block * -devfs_get_sb (struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static struct super_block *devfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data) { - return get_sb_single (fs_type, flags, data, devfs_fill_super); + return get_sb_single(fs_type, flags, data, devfs_fill_super); } -static struct file_system_type devfs_fs_type = -{ - .name = DEVFS_NAME, - .get_sb = devfs_get_sb, - .kill_sb = kill_anon_super, +static struct file_system_type devfs_fs_type = { + .name = DEVFS_NAME, + .get_sb = devfs_get_sb, + .kill_sb = kill_anon_super, }; /* File operations for devfsd follow */ -static ssize_t devfsd_read (struct file *file, char *buf, size_t len, - loff_t *ppos) +static ssize_t devfsd_read(struct file *file, char *buf, size_t len, + loff_t * ppos) { - int done = FALSE; - int ival; - loff_t pos, devname_offset, tlen, rpos; - devfs_handle_t de; - struct devfsd_buf_entry *entry; - struct fs_info *fs_info = file->f_dentry->d_inode->i_sb->s_fs_info; - struct devfsd_notify_struct *info = fs_info->devfsd_info; - DECLARE_WAITQUEUE (wait, current); - - /* Can't seek (pread) on this device */ - if (ppos != &file->f_pos) return -ESPIPE; - /* Verify the task has grabbed the queue */ - if (fs_info->devfsd_task != current) return -EPERM; - info->major = 0; - info->minor = 0; - /* Block for a new entry */ - set_current_state (TASK_INTERRUPTIBLE); - add_wait_queue (&fs_info->devfsd_wait_queue, &wait); - while ( devfsd_queue_empty (fs_info) ) - { - fs_info->devfsd_sleeping = TRUE; - wake_up (&fs_info->revalidate_wait_queue); - schedule (); - fs_info->devfsd_sleeping = FALSE; - if ( signal_pending (current) ) - { - remove_wait_queue (&fs_info->devfsd_wait_queue, &wait); - __set_current_state (TASK_RUNNING); - return -EINTR; - } - set_current_state (TASK_INTERRUPTIBLE); - } - remove_wait_queue (&fs_info->devfsd_wait_queue, &wait); - __set_current_state (TASK_RUNNING); - /* Now play with the data */ - ival = atomic_read (&fs_info->devfsd_overrun_count); - info->overrun_count = ival; - entry = fs_info->devfsd_first_event; - info->type = entry->type; - info->mode = entry->mode; - info->uid = entry->uid; - info->gid = entry->gid; - de = entry->de; - if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) { - info->major = MAJOR(de->u.dev); - info->minor = MINOR(de->u.dev); - } - pos = devfs_generate_path (de, info->devname, DEVFS_PATHLEN); - if (pos < 0) return pos; - info->namelen = DEVFS_PATHLEN - pos - 1; - if (info->mode == 0) info->mode = de->mode; - devname_offset = info->devname - (char *) info; - rpos = *ppos; - if (rpos < devname_offset) - { - /* Copy parts of the header */ - tlen = devname_offset - rpos; - if (tlen > len) tlen = len; - if ( copy_to_user (buf, (char *) info + rpos, tlen) ) - { - return -EFAULT; - } - rpos += tlen; - buf += tlen; - len -= tlen; - } - if ( (rpos >= devname_offset) && (len > 0) ) - { - /* Copy the name */ - tlen = info->namelen + 1; - if (tlen > len) tlen = len; - else done = TRUE; - if ( copy_to_user (buf, info->devname + pos + rpos - devname_offset, - tlen) ) - { - return -EFAULT; - } - rpos += tlen; - } - tlen = rpos - *ppos; - if (done) - { - devfs_handle_t parent; - - spin_lock (&fs_info->devfsd_buffer_lock); - fs_info->devfsd_first_event = entry->next; - if (entry->next == NULL) fs_info->devfsd_last_event = NULL; - spin_unlock (&fs_info->devfsd_buffer_lock); - for (; de != NULL; de = parent) - { - parent = de->parent; - devfs_put (de); - } - kmem_cache_free (devfsd_buf_cache, entry); - if (ival > 0) atomic_sub (ival, &fs_info->devfsd_overrun_count); - *ppos = 0; - } - else *ppos = rpos; - return tlen; -} /* End Function devfsd_read */ - -static int devfsd_ioctl (struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int ival; - struct fs_info *fs_info = inode->i_sb->s_fs_info; - - switch (cmd) - { - case DEVFSDIOC_GET_PROTO_REV: - ival = DEVFSD_PROTOCOL_REVISION_KERNEL; - if ( copy_to_user ( (void *)arg, &ival, sizeof ival ) ) return -EFAULT; - break; - case DEVFSDIOC_SET_EVENT_MASK: - /* Ensure only one reader has access to the queue. This scheme will - work even if the global kernel lock were to be removed, because it - doesn't matter who gets in first, as long as only one gets it */ - if (fs_info->devfsd_task == NULL) - { - static spinlock_t lock = SPIN_LOCK_UNLOCKED; - - if ( !spin_trylock (&lock) ) return -EBUSY; - if (fs_info->devfsd_task != NULL) - { /* We lost the race... */ - spin_unlock (&lock); - return -EBUSY; - } - fs_info->devfsd_task = current; - spin_unlock (&lock); - fs_info->devfsd_pgrp = (process_group(current) == current->pid) ? - process_group(current) : 0; - fs_info->devfsd_file = file; - fs_info->devfsd_info = kmalloc (sizeof *fs_info->devfsd_info, - GFP_KERNEL); - if (!fs_info->devfsd_info) - { - devfsd_close (inode, file); - return -ENOMEM; - } + int done = FALSE; + int ival; + loff_t pos, devname_offset, tlen, rpos; + devfs_handle_t de; + struct devfsd_buf_entry *entry; + struct fs_info *fs_info = file->f_dentry->d_inode->i_sb->s_fs_info; + struct devfsd_notify_struct *info = fs_info->devfsd_info; + DECLARE_WAITQUEUE(wait, current); + + /* Can't seek (pread) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + /* Verify the task has grabbed the queue */ + if (fs_info->devfsd_task != current) + return -EPERM; + info->major = 0; + info->minor = 0; + /* Block for a new entry */ + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&fs_info->devfsd_wait_queue, &wait); + while (devfsd_queue_empty(fs_info)) { + fs_info->devfsd_sleeping = TRUE; + wake_up(&fs_info->revalidate_wait_queue); + schedule(); + fs_info->devfsd_sleeping = FALSE; + if (signal_pending(current)) { + remove_wait_queue(&fs_info->devfsd_wait_queue, &wait); + __set_current_state(TASK_RUNNING); + return -EINTR; + } + set_current_state(TASK_INTERRUPTIBLE); } - else if (fs_info->devfsd_task != current) return -EBUSY; - fs_info->devfsd_event_mask = arg; /* Let the masses come forth */ - break; - case DEVFSDIOC_RELEASE_EVENT_QUEUE: - if (fs_info->devfsd_file != file) return -EPERM; - return devfsd_close (inode, file); - /*break;*/ + remove_wait_queue(&fs_info->devfsd_wait_queue, &wait); + __set_current_state(TASK_RUNNING); + /* Now play with the data */ + ival = atomic_read(&fs_info->devfsd_overrun_count); + info->overrun_count = ival; + entry = fs_info->devfsd_first_event; + info->type = entry->type; + info->mode = entry->mode; + info->uid = entry->uid; + info->gid = entry->gid; + de = entry->de; + if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) { + info->major = MAJOR(de->u.dev); + info->minor = MINOR(de->u.dev); + } + pos = devfs_generate_path(de, info->devname, DEVFS_PATHLEN); + if (pos < 0) + return pos; + info->namelen = DEVFS_PATHLEN - pos - 1; + if (info->mode == 0) + info->mode = de->mode; + devname_offset = info->devname - (char *)info; + rpos = *ppos; + if (rpos < devname_offset) { + /* Copy parts of the header */ + tlen = devname_offset - rpos; + if (tlen > len) + tlen = len; + if (copy_to_user(buf, (char *)info + rpos, tlen)) { + return -EFAULT; + } + rpos += tlen; + buf += tlen; + len -= tlen; + } + if ((rpos >= devname_offset) && (len > 0)) { + /* Copy the name */ + tlen = info->namelen + 1; + if (tlen > len) + tlen = len; + else + done = TRUE; + if (copy_to_user + (buf, info->devname + pos + rpos - devname_offset, tlen)) { + return -EFAULT; + } + rpos += tlen; + } + tlen = rpos - *ppos; + if (done) { + devfs_handle_t parent; + + spin_lock(&fs_info->devfsd_buffer_lock); + fs_info->devfsd_first_event = entry->next; + if (entry->next == NULL) + fs_info->devfsd_last_event = NULL; + spin_unlock(&fs_info->devfsd_buffer_lock); + for (; de != NULL; de = parent) { + parent = de->parent; + devfs_put(de); + } + kmem_cache_free(devfsd_buf_cache, entry); + if (ival > 0) + atomic_sub(ival, &fs_info->devfsd_overrun_count); + *ppos = 0; + } else + *ppos = rpos; + return tlen; +} /* End Function devfsd_read */ + +static int devfsd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ival; + struct fs_info *fs_info = inode->i_sb->s_fs_info; + + switch (cmd) { + case DEVFSDIOC_GET_PROTO_REV: + ival = DEVFSD_PROTOCOL_REVISION_KERNEL; + if (copy_to_user((void *)arg, &ival, sizeof ival)) + return -EFAULT; + break; + case DEVFSDIOC_SET_EVENT_MASK: + /* Ensure only one reader has access to the queue. This scheme will + work even if the global kernel lock were to be removed, because it + doesn't matter who gets in first, as long as only one gets it */ + if (fs_info->devfsd_task == NULL) { + static spinlock_t lock = SPIN_LOCK_UNLOCKED; + + if (!spin_trylock(&lock)) + return -EBUSY; + if (fs_info->devfsd_task != NULL) { /* We lost the race... */ + spin_unlock(&lock); + return -EBUSY; + } + fs_info->devfsd_task = current; + spin_unlock(&lock); + fs_info->devfsd_pgrp = + (process_group(current) == + current->pid) ? process_group(current) : 0; + fs_info->devfsd_file = file; + fs_info->devfsd_info = + kmalloc(sizeof *fs_info->devfsd_info, GFP_KERNEL); + if (!fs_info->devfsd_info) { + devfsd_close(inode, file); + return -ENOMEM; + } + } else if (fs_info->devfsd_task != current) + return -EBUSY; + fs_info->devfsd_event_mask = arg; /* Let the masses come forth */ + break; + case DEVFSDIOC_RELEASE_EVENT_QUEUE: + if (fs_info->devfsd_file != file) + return -EPERM; + return devfsd_close(inode, file); + /*break; */ #ifdef CONFIG_DEVFS_DEBUG - case DEVFSDIOC_SET_DEBUG_MASK: - if ( copy_from_user (&ival, (void *) arg, sizeof ival) )return -EFAULT; - devfs_debug = ival; - break; + case DEVFSDIOC_SET_DEBUG_MASK: + if (copy_from_user(&ival, (void *)arg, sizeof ival)) + return -EFAULT; + devfs_debug = ival; + break; #endif - default: - return -ENOIOCTLCMD; - } - return 0; -} /* End Function devfsd_ioctl */ - -static int devfsd_close (struct inode *inode, struct file *file) -{ - struct devfsd_buf_entry *entry, *next; - struct fs_info *fs_info = inode->i_sb->s_fs_info; - - if (fs_info->devfsd_file != file) return 0; - fs_info->devfsd_event_mask = 0; - fs_info->devfsd_file = NULL; - spin_lock (&fs_info->devfsd_buffer_lock); - entry = fs_info->devfsd_first_event; - fs_info->devfsd_first_event = NULL; - fs_info->devfsd_last_event = NULL; - if (fs_info->devfsd_info) - { - kfree (fs_info->devfsd_info); - fs_info->devfsd_info = NULL; - } - spin_unlock (&fs_info->devfsd_buffer_lock); - fs_info->devfsd_pgrp = 0; - fs_info->devfsd_task = NULL; - wake_up (&fs_info->revalidate_wait_queue); - for (; entry; entry = next) - { - next = entry->next; - kmem_cache_free (devfsd_buf_cache, entry); - } - return 0; -} /* End Function devfsd_close */ + default: + return -ENOIOCTLCMD; + } + return 0; +} /* End Function devfsd_ioctl */ + +static int devfsd_close(struct inode *inode, struct file *file) +{ + struct devfsd_buf_entry *entry, *next; + struct fs_info *fs_info = inode->i_sb->s_fs_info; + + if (fs_info->devfsd_file != file) + return 0; + fs_info->devfsd_event_mask = 0; + fs_info->devfsd_file = NULL; + spin_lock(&fs_info->devfsd_buffer_lock); + entry = fs_info->devfsd_first_event; + fs_info->devfsd_first_event = NULL; + fs_info->devfsd_last_event = NULL; + if (fs_info->devfsd_info) { + kfree(fs_info->devfsd_info); + fs_info->devfsd_info = NULL; + } + spin_unlock(&fs_info->devfsd_buffer_lock); + fs_info->devfsd_pgrp = 0; + fs_info->devfsd_task = NULL; + wake_up(&fs_info->revalidate_wait_queue); + for (; entry; entry = next) { + next = entry->next; + kmem_cache_free(devfsd_buf_cache, entry); + } + return 0; +} /* End Function devfsd_close */ #ifdef CONFIG_DEVFS_DEBUG -static ssize_t stat_read (struct file *file, char *buf, size_t len, - loff_t *ppos) +static ssize_t stat_read(struct file *file, char *buf, size_t len, + loff_t * ppos) { - ssize_t num; - char txt[80]; + ssize_t num; + char txt[80]; - num = sprintf (txt, "Number of entries: %u number of bytes: %u\n", - stat_num_entries, stat_num_bytes) + 1; - /* Can't seek (pread) on this device */ - if (ppos != &file->f_pos) return -ESPIPE; - if (*ppos >= num) return 0; - if (*ppos + len > num) len = num - *ppos; - if ( copy_to_user (buf, txt + *ppos, len) ) return -EFAULT; - *ppos += len; - return len; -} /* End Function stat_read */ + num = sprintf(txt, "Number of entries: %u number of bytes: %u\n", + stat_num_entries, stat_num_bytes) + 1; + /* Can't seek (pread) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + if (*ppos >= num) + return 0; + if (*ppos + len > num) + len = num - *ppos; + if (copy_to_user(buf, txt + *ppos, len)) + return -EFAULT; + *ppos += len; + return len; +} /* End Function stat_read */ #endif static int __init init_devfs_fs(void) @@ -2793,8 +2809,8 @@ static int __init init_devfs_fs(void) printk(KERN_INFO "%s: %s Richard Gooch (rgooch@atnf.csiro.au)\n", DEVFS_NAME, DEVFS_VERSION); devfsd_buf_cache = kmem_cache_create("devfsd_event", - sizeof (struct devfsd_buf_entry), - 0, 0, NULL, NULL); + sizeof(struct devfsd_buf_entry), + 0, 0, NULL, NULL); if (!devfsd_buf_cache) OOPS("(): unable to allocate event slab\n"); #ifdef CONFIG_DEVFS_DEBUG @@ -2809,32 +2825,35 @@ static int __init init_devfs_fs(void) return major; /* And create the entry for ".devfsd" */ - devfsd = _devfs_alloc_entry(".devfsd", 0, S_IFCHR|S_IRUSR|S_IWUSR); - if (devfsd == NULL ) + devfsd = _devfs_alloc_entry(".devfsd", 0, S_IFCHR | S_IRUSR | S_IWUSR); + if (devfsd == NULL) return -ENOMEM; devfsd->u.dev = MKDEV(major, 0); _devfs_append_entry(root_entry, devfsd, NULL); #ifdef CONFIG_DEVFS_DEBUG - stat = _devfs_alloc_entry(".stat", 0, S_IFCHR|S_IRUGO); - if (stat == NULL ) + stat = _devfs_alloc_entry(".stat", 0, S_IFCHR | S_IRUGO); + if (stat == NULL) return -ENOMEM; stat->u.dev = MKDEV(major, 1); - _devfs_append_entry (root_entry, stat, NULL); + _devfs_append_entry(root_entry, stat, NULL); #endif err = register_filesystem(&devfs_fs_type); return err; -} /* End Function init_devfs_fs */ +} /* End Function init_devfs_fs */ -void __init mount_devfs_fs (void) +void __init mount_devfs_fs(void) { - int err; + int err; - if ( !(boot_options & OPTION_MOUNT) ) return; - err = do_mount ("none", "/dev", "devfs", 0, NULL); - if (err == 0) printk (KERN_INFO "Mounted devfs on /dev\n"); - else PRINTK ("(): unable to mount devfs, err: %d\n", err); -} /* End Function mount_devfs_fs */ + if (!(boot_options & OPTION_MOUNT)) + return; + err = do_mount("none", "/dev", "devfs", 0, NULL); + if (err == 0) + printk(KERN_INFO "Mounted devfs on /dev\n"); + else + PRINTK("(): unable to mount devfs, err: %d\n", err); +} /* End Function mount_devfs_fs */ module_init(init_devfs_fs) diff -puN fs/devfs/util.c~Lindent-devfs fs/devfs/util.c --- 25/fs/devfs/util.c~Lindent-devfs 2004-03-24 02:43:40.243747984 -0800 +++ 25-akpm/fs/devfs/util.c 2004-03-24 02:43:40.263744944 -0800 @@ -73,7 +73,6 @@ #include #include - int devfs_register_tape(const char *name) { char tname[32], dest[64]; @@ -86,6 +85,7 @@ int devfs_register_tape(const char *name return n; } + EXPORT_SYMBOL(devfs_register_tape); void devfs_unregister_tape(int num) diff -puN include/linux/devfs_fs.h~Lindent-devfs include/linux/devfs_fs.h --- 25/include/linux/devfs_fs.h~Lindent-devfs 2004-03-24 02:43:48.618474832 -0800 +++ 25-akpm/include/linux/devfs_fs.h 2004-03-24 02:44:00.569657976 -0800 @@ -22,22 +22,20 @@ #define DEVFSD_NOTIFY_CREATE 6 #define DEVFSD_NOTIFY_DELETE 7 -#define DEVFS_PATHLEN 1024 /* Never change this otherwise the - binary interface will change */ +#define DEVFS_PATHLEN 1024 /* Never change this otherwise the + binary interface will change */ -struct devfsd_notify_struct -{ /* Use native C types to ensure same types in kernel and user space */ - unsigned int type; /* DEVFSD_NOTIFY_* value */ - unsigned int mode; /* Mode of the inode or device entry */ - unsigned int major; /* Major number of device entry */ - unsigned int minor; /* Minor number of device entry */ - unsigned int uid; /* Uid of process, inode or device entry */ - unsigned int gid; /* Gid of process, inode or device entry */ - unsigned int overrun_count; /* Number of lost events */ - unsigned int namelen; /* Number of characters not including '\0' */ - /* The device name MUST come last */ - char devname[DEVFS_PATHLEN]; /* This will be '\0' terminated */ +struct devfsd_notify_struct { /* Use native C types to ensure same types in kernel and user space */ + unsigned int type; /* DEVFSD_NOTIFY_* value */ + unsigned int mode; /* Mode of the inode or device entry */ + unsigned int major; /* Major number of device entry */ + unsigned int minor; /* Minor number of device entry */ + unsigned int uid; /* Uid of process, inode or device entry */ + unsigned int gid; /* Gid of process, inode or device entry */ + unsigned int overrun_count; /* Number of lost events */ + unsigned int namelen; /* Number of characters not including '\0' */ + /* The device name MUST come last */ + char devname[DEVFS_PATHLEN]; /* This will be '\0' terminated */ }; - -#endif /* _LINUX_DEVFS_FS_H */ +#endif /* _LINUX_DEVFS_FS_H */ diff -puN include/linux/devfs_fs_kernel.h~Lindent-devfs include/linux/devfs_fs_kernel.h --- 25/include/linux/devfs_fs_kernel.h~Lindent-devfs 2004-03-24 02:44:21.893416272 -0800 +++ 25-akpm/include/linux/devfs_fs_kernel.h 2004-03-24 02:44:30.922043712 -0800 @@ -12,18 +12,18 @@ #ifdef CONFIG_DEVFS_FS extern int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) - __attribute__((format (printf, 3, 4))); + __attribute__ ((format(printf, 3, 4))); extern int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) - __attribute__((format (printf, 3, 4))); + __attribute__ ((format(printf, 3, 4))); extern int devfs_mk_symlink(const char *name, const char *link); extern int devfs_mk_dir(const char *fmt, ...) - __attribute__((format (printf, 1, 2))); + __attribute__ ((format(printf, 1, 2))); extern void devfs_remove(const char *fmt, ...) - __attribute__((format (printf, 1, 2))); + __attribute__ ((format(printf, 1, 2))); extern int devfs_register_tape(const char *name); extern void devfs_unregister_tape(int num); extern void mount_devfs_fs(void); -#else /* CONFIG_DEVFS_FS */ +#else /* CONFIG_DEVFS_FS */ static inline int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) { return 0; @@ -32,9 +32,9 @@ static inline int devfs_mk_cdev(dev_t de { return 0; } -static inline int devfs_mk_symlink (const char *name, const char *link) +static inline int devfs_mk_symlink(const char *name, const char *link) { - return 0; + return 0; } static inline int devfs_mk_dir(const char *fmt, ...) { @@ -43,16 +43,16 @@ static inline int devfs_mk_dir(const cha static inline void devfs_remove(const char *fmt, ...) { } -static inline int devfs_register_tape (const char *name) +static inline int devfs_register_tape(const char *name) { - return -1; + return -1; } static inline void devfs_unregister_tape(int num) { } -static inline void mount_devfs_fs (void) +static inline void mount_devfs_fs(void) { - return; + return; } -#endif /* CONFIG_DEVFS_FS */ -#endif /* _LINUX_DEVFS_FS_KERNEL_H */ +#endif /* CONFIG_DEVFS_FS */ +#endif /* _LINUX_DEVFS_FS_KERNEL_H */ _