patch-2.4.0-test3 linux/fs/devfs/base.c
Next file: linux/fs/devfs/util.c
Previous file: linux/fs/dcache.c
Back to the patch index
Back to the overall index
- Lines: 373
- Date:
Sat Jul 8 19:26:13 2000
- Orig file:
v2.4.0-test2/linux/fs/devfs/base.c
- Orig date:
Fri Jun 23 21:55:10 2000
diff -u --recursive --new-file v2.4.0-test2/linux/fs/devfs/base.c linux/fs/devfs/base.c
@@ -476,6 +476,11 @@
Changed interface to <devfs_register>.
Work sponsored by SGI.
v0.101
+ 20000622 Richard Gooch <rgooch@atnf.csiro.au>
+ Simplified interface to <devfs_mk_symlink> and <devfs_mk_dir>.
+ Simplified interface to <devfs_find_handle>.
+ Work sponsored by SGI.
+ v0.102
*/
#include <linux/types.h>
#include <linux/errno.h>
@@ -510,7 +515,7 @@
#include <asm/bitops.h>
#include <asm/atomic.h>
-#define DEVFS_VERSION "0.101 (20000621)"
+#define DEVFS_VERSION "0.102 (20000622)"
#define DEVFS_NAME "devfs"
@@ -1070,22 +1075,25 @@
{
struct dentry *dentry;
+ spin_lock(&dcache_lock);
dentry = de->inode.dentry;
if (dentry != NULL)
{
- dget (dentry);
+ dget_locked (dentry);
de->inode.dentry = NULL;
+ spin_unlock(&dcache_lock);
/* Forcefully remove the inode */
if (dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0;
d_drop (dentry);
dput (dentry);
- }
+ } else
+ spin_unlock(&dcache_lock);
} /* End Function free_dentries */
/**
* is_devfsd_or_child - Test if the current process is devfsd or one of its children.
- * fs_info: The filesystem information.
+ * @fs_info: The filesystem information.
*
* Returns %TRUE if devfsd or child, else %FALSE.
*/
@@ -1419,7 +1427,7 @@
/**
* devfs_unregister - Unregister a device entry.
- * de: A handle previously created by devfs_register() or returned from
+ * @de: A handle previously created by devfs_register() or returned from
* devfs_find_handle(). If this is %NULL the routine does nothing.
*/
@@ -1440,27 +1448,19 @@
* @dir: The handle to the parent devfs directory entry. If this is %NULL the
* new name is relative to the root of the devfs.
* @name: The name of the entry.
- * @namelen: The number of characters in @name, not including a %NULL
- * terminator. If this is 0, then @name must be %NULL-terminated and the
- * length is computed internally.
* @flags: A set of bitwise-ORed flags (DEVFS_FL_*).
* @link: The destination name.
- * @linklength: The number of characters in @link, not including a %NULL
- * terminator. If this is 0, then @link must be %NULL-terminated and the
- * length is computed internally.
* @handle: The handle to the symlink entry is written here. This may be %NULL.
* @info: An arbitrary pointer which will be associated with the entry.
*
* Returns 0 on success, else a negative error code is returned.
*/
-int devfs_mk_symlink (devfs_handle_t dir,
- const char *name, unsigned int namelen,
- unsigned int flags,
- const char *link, unsigned int linklength,
- devfs_handle_t *handle, void *info)
+int devfs_mk_symlink (devfs_handle_t dir, const char *name, unsigned int flags,
+ const char *link, devfs_handle_t *handle, void *info)
{
int is_new;
+ unsigned int linklength;
char *newname;
struct devfs_entry *de;
@@ -1474,14 +1474,14 @@
if (devfs_debug & DEBUG_REGISTER)
printk ("%s: devfs_mk_symlink(%s)\n", DEVFS_NAME, name);
#endif
- if (namelen < 1) namelen = strlen (name);
if (link == NULL)
{
printk ("%s: devfs_mk_symlink(): NULL link pointer\n", DEVFS_NAME);
return -EINVAL;
}
- if (linklength < 1) linklength = strlen (link);
- de = search_for_entry (dir, name, namelen, TRUE, TRUE, &is_new, FALSE);
+ linklength = strlen (link);
+ de = search_for_entry (dir, name, strlen (name), TRUE, TRUE, &is_new,
+ FALSE);
if (de == NULL) return -ENOMEM;
if (!S_ISLNK (de->mode) && de->registered)
{
@@ -1493,7 +1493,7 @@
de->mode = S_IFLNK | S_IRUGO | S_IXUGO;
de->info = info;
de->show_unreg = ( (boot_options & OPTION_SHOW)
- || (flags & DEVFS_FL_SHOW_UNREG) ) ? TRUE : FALSE;
+ || (flags & DEVFS_FL_SHOW_UNREG) ) ? TRUE : FALSE;
de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE;
/* Note there is no need to fiddle the dentry cache if the symlink changes
as the symlink follow method is called every time it's needed */
@@ -1533,9 +1533,6 @@
* @dir: The handle to the parent devfs directory entry. If this is %NULL the
* new name is relative to the root of the devfs.
* @name: The name of the entry.
- * @namelen: The number of characters in @name, not including a %NULL
- * terminator. If this is 0, then @name must be %NULL-terminated and the
- * length is computed internally.
* @info: An arbitrary pointer which will be associated with the entry.
*
* Use of this function is optional. The devfs_register() function
@@ -1545,8 +1542,7 @@
* On failure %NULL is returned.
*/
-devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name,
- unsigned int namelen, void *info)
+devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name, void *info)
{
int is_new;
struct devfs_entry *de;
@@ -1556,8 +1552,8 @@
printk ("%s: devfs_mk_dir(): NULL name pointer\n", DEVFS_NAME);
return NULL;
}
- if (namelen < 1) namelen = strlen (name);
- de = search_for_entry (dir, name, namelen, TRUE, TRUE, &is_new, FALSE);
+ de = search_for_entry (dir, name, strlen (name), TRUE, TRUE, &is_new,
+ FALSE);
if (de == NULL)
{
printk ("%s: devfs_mk_dir(): could not create entry: \"%s\"\n",
@@ -1596,9 +1592,6 @@
* @dir: The handle to the parent devfs directory entry. If this is %NULL the
* name is relative to the root of the devfs.
* @name: The name of the entry.
- * @namelen: The number of characters in @name, not including a %NULL
- * terminator. If this is 0, then @name must be %NULL-terminated and the
- * length is computed internally.
* @major: The major number. This is used if @name is %NULL.
* @minor: The minor number. This is used if @name is %NULL.
* @type: The type of special file to search for. This may be either
@@ -1611,15 +1604,14 @@
* devfs_get_flags(), or devfs_set_flags(). On failure %NULL is returned.
*/
-devfs_handle_t devfs_find_handle (devfs_handle_t dir,
- const char *name, unsigned int namelen,
+devfs_handle_t devfs_find_handle (devfs_handle_t dir, const char *name,
unsigned int major, unsigned int minor,
char type, int traverse_symlinks)
{
devfs_handle_t de;
if ( (name != NULL) && (name[0] == '\0') ) name = NULL;
- de = find_entry (dir, name, namelen, major, minor, type,
+ de = find_entry (dir, name, 0, major, minor, type,
traverse_symlinks);
if (de == NULL) return NULL;
if (!de->registered) return NULL;
@@ -2306,7 +2298,7 @@
#endif
} /* End Function devfs_read_inode */
-static void devfs_write_inode (struct inode *inode, int unused)
+static void devfs_write_inode (struct inode *inode, int wait)
{
int index;
struct devfs_entry *de;
@@ -2314,10 +2306,12 @@
if (inode->i_ino < FIRST_INODE) return;
index = inode->i_ino - FIRST_INODE;
+ lock_kernel();
if (index >= fs_info->num_inodes)
{
printk ("%s: writing inode: %lu for which there is no entry!\n",
DEVFS_NAME, inode->i_ino);
+ unlock_kernel();
return;
}
de = fs_info->table[index];
@@ -2337,6 +2331,7 @@
de->inode.atime = inode->i_atime;
de->inode.mtime = inode->i_mtime;
de->inode.ctime = inode->i_ctime;
+ unlock_kernel();
} /* End Function devfs_write_inode */
static int devfs_notify_change (struct dentry *dentry, struct iattr *iattr)
@@ -2379,8 +2374,8 @@
/**
* get_vfs_inode - Get a VFS inode.
* @sb: The super block.
- * @di: The devfs inode.
- * @dentry The dentry to register with the devfs inode.
+ * @de: The devfs inode.
+ * @dentry: The dentry to register with the devfs inode.
*
* Returns the inode on success, else %NULL.
*/
@@ -2487,11 +2482,18 @@
struct devfs_entry *de;
struct fs_info *fs_info = inode->i_sb->u.generic_sbp;
+ lock_kernel();
de = get_devfs_entry_from_vfs_inode (inode);
- if (de == NULL) return -ENODEV;
- if ( S_ISDIR (de->mode) ) return 0;
+ err = -ENODEV;
+ if (de == NULL)
+ goto out;
+ err = 0;
+ if ( S_ISDIR (de->mode) )
+ goto out;
df = &de->u.fcb;
- if (!de->registered) return -ENODEV;
+ err = -ENODEV;
+ if (!de->registered)
+ goto out;
file->private_data = de->info;
if ( S_ISBLK (inode->i_mode) )
{
@@ -2507,9 +2509,10 @@
if ( S_ISCHR (inode->i_mode) ) err = chrdev_open (inode, file);
else err = -ENODEV;
}
- if (err < 0) return err;
+ if (err < 0) goto out;
/* Open was successful */
- if (df->open) return 0;
+ err = 0;
+ if (df->open) goto out;
df->open = TRUE; /* This is the first open */
if (df->auto_owner)
{
@@ -2524,7 +2527,9 @@
if (df->aopen_notify)
devfsd_notify_one (de, DEVFSD_NOTIFY_ASYNC_OPEN, inode->i_mode,
current->euid, current->egid, fs_info);
- return 0;
+out:
+ unlock_kernel();
+ return err;
} /* End Function devfs_open */
static struct file_operations devfs_fops =
@@ -2564,16 +2569,15 @@
{
struct devfs_entry *de;
+ lock_kernel ();
de = get_devfs_entry_from_vfs_inode (inode);
#ifdef CONFIG_DEVFS_DEBUG
if (devfs_debug & DEBUG_D_IPUT)
printk ("%s: d_iput(): dentry: %p inode: %p de: %p de->dentry: %p\n",
DEVFS_NAME, dentry, inode, de, de->inode.dentry);
#endif
- if (de->inode.dentry == dentry)
- {
- de->inode.dentry = NULL;
- }
+ if (de->inode.dentry == dentry) de->inode.dentry = NULL;
+ unlock_kernel ();
iput (inode);
} /* End Function devfs_d_iput */
@@ -2598,7 +2602,7 @@
/**
* devfs_d_delete - Callback for when all files for a dentry are closed.
- * @detry: The dentry.
+ * @dentry: The dentry.
*/
static int devfs_d_delete (struct dentry *dentry)
@@ -2647,9 +2651,12 @@
static int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
{
devfs_handle_t de = dentry->d_fsdata;
- struct inode *dir = dentry->d_parent->d_inode;
- struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
+ struct inode *dir;
+ struct fs_info *fs_info;
+ lock_kernel ();
+ dir = dentry->d_parent->d_inode;
+ fs_info = dir->i_sb->u.generic_sbp;
if (!de || de->registered)
{
if ( !dentry->d_inode && is_devfsd_or_child (fs_info) )
@@ -2675,7 +2682,7 @@
de = search_for_entry_in_dir (parent, dentry->d_name.name,
dentry->d_name.len, FALSE);
}
- if (de == NULL) return 1;
+ if (de == NULL) goto out;
/* Create an inode, now that the driver information is available
*/
if (de->no_persistence) update_devfs_inode_from_entry (de);
@@ -2683,17 +2690,19 @@
else de->inode.mode =
(de->mode & ~S_IALLUGO) | (de->inode.mode & S_IALLUGO);
if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
- return 1;
+ goto out;
#ifdef CONFIG_DEVFS_DEBUG
if (devfs_debug & DEBUG_I_LOOKUP)
printk ("%s: d_revalidate(): new VFS inode(%u): %p devfs_entry: %p\n",
DEVFS_NAME, de->inode.ino, inode, de);
#endif
d_instantiate (dentry, inode);
- return 1;
+ goto out;
}
}
if ( wait_for_devfsd_finished (fs_info) ) dentry->d_op = &devfs_dops;
+out:
+ unlock_kernel ();
return 1;
} /* End Function devfs_d_revalidate_wait */
@@ -2857,8 +2866,8 @@
parent = get_devfs_entry_from_vfs_inode (dir);
if (parent == NULL) return -EINVAL;
if (!parent->registered) return -ENOENT;
- err = devfs_mk_symlink (parent, dentry->d_name.name, dentry->d_name.len,
- DEVFS_FL_NONE, symname, 0, &de, NULL);
+ err = devfs_mk_symlink (parent, dentry->d_name.name, DEVFS_FL_NONE,
+ symname, &de, NULL);
#ifdef CONFIG_DEVFS_DEBUG
if (devfs_debug & DEBUG_DISABLED)
printk ("%s: symlink(): errcode from <devfs_mk_symlink>: %d\n",
@@ -3046,15 +3055,21 @@
static int devfs_readlink (struct dentry *dentry, char *buffer, int buflen)
{
- struct devfs_entry *de = get_devfs_entry_from_vfs_inode (dentry->d_inode);
+ struct devfs_entry *de;
+ lock_kernel ();
+ de = get_devfs_entry_from_vfs_inode (dentry->d_inode);
+ unlock_kernel ();
return vfs_readlink (dentry, buffer, buflen, de->u.symlink.linkname);
} /* End Function devfs_readlink */
static int devfs_follow_link (struct dentry *dentry, struct nameidata *nd)
{
- struct devfs_entry *de = get_devfs_entry_from_vfs_inode (dentry->d_inode);
+ struct devfs_entry *de;
+ lock_kernel ();
+ de = get_devfs_entry_from_vfs_inode (dentry->d_inode);
+ unlock_kernel ();
return vfs_follow_link (nd, de->u.symlink.linkname);
} /* End Function devfs_follow_link */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)