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

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)