patch-2.4.19 linux-2.4.19/fs/devfs/base.c
Next file: linux-2.4.19/fs/devfs/util.c
Previous file: linux-2.4.19/fs/dcache.c
Back to the patch index
Back to the overall index
- Lines: 252
- Date:
Fri Aug 2 17:39:45 2002
- Orig file:
linux-2.4.18/fs/devfs/base.c
- Orig date:
Mon Feb 25 11:38:08 2002
diff -urN linux-2.4.18/fs/devfs/base.c linux-2.4.19/fs/devfs/base.c
@@ -608,6 +608,18 @@
Fixed deadlock bug in <devfs_d_revalidate_wait>.
Tag VFS deletable in <devfs_mk_symlink> if handle ignored.
v1.10
+ 20020129 Richard Gooch <rgooch@atnf.csiro.au>
+ Added KERN_* to remaining messages.
+ Cleaned up declaration of <stat_read>.
+ v1.11
+ 20020219 Richard Gooch <rgooch@atnf.csiro.au>
+ Changed <devfs_rmdir> to allow later additions if not yet empty.
+ v1.12
+ 20020514 Richard Gooch <rgooch@atnf.csiro.au>
+ Added BKL to <devfs_open> because drivers still need it.
+ Protected <scan_dir_for_removable> and <get_removable_partition>
+ from changing directory contents.
+ v1.12a
*/
#include <linux/types.h>
#include <linux/errno.h>
@@ -640,7 +652,7 @@
#include <asm/bitops.h>
#include <asm/atomic.h>
-#define DEVFS_VERSION "1.10 (20020120)"
+#define DEVFS_VERSION "1.12a (20020514)"
#define DEVFS_NAME "devfs"
@@ -848,8 +860,8 @@
unsigned int cmd, unsigned long arg);
static int devfsd_close (struct inode *inode, struct file *file);
#ifdef CONFIG_DEVFS_DEBUG
-static int 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);
static struct file_operations stat_fops =
{
read: stat_read,
@@ -2415,6 +2427,9 @@
* @de: The device.
*
* Returns 1 if the media was changed, else 0.
+ *
+ * This function may block, and may indirectly cause the parent directory
+ * contents to be changed due to partition re-reading.
*/
static int check_disc_changed (struct devfs_entry *de)
@@ -2431,10 +2446,10 @@
if (bdops->check_media_change == NULL) goto out;
if ( !bdops->check_media_change (dev) ) goto out;
retval = 1;
- printk ( KERN_DEBUG "VFS: Disk change detected on device %s\n",
+ printk (KERN_DEBUG "VFS: Disk change detected on device %s\n",
kdevname (dev) );
- if (invalidate_device(dev, 0))
- printk("VFS: busy inodes on changed media..\n");
+ if ( invalidate_device (dev, 0) )
+ printk (KERN_WARNING "VFS: busy inodes on changed media..\n");
/* Ugly hack to disable messages about unable to read partition table */
tmp = warn_no_part;
warn_no_part = 0;
@@ -2449,19 +2464,29 @@
/**
* scan_dir_for_removable - Scan a directory for removable media devices and check media.
* @dir: The directory.
+ *
+ * This function may block, and may indirectly cause the directory
+ * contents to be changed due to partition re-reading. The directory will
+ * be locked for reading.
*/
static void scan_dir_for_removable (struct devfs_entry *dir)
{
struct devfs_entry *de;
- if (dir->u.dir.num_removable < 1) return;
- for (de = dir->u.dir.first; de != NULL; de = de->next)
+ read_lock (&dir->u.dir.lock);
+ if (dir->u.dir.num_removable < 1) de = NULL;
+ else
{
- if ( !S_ISBLK (de->mode) ) continue;
- if (!de->u.fcb.removable) continue;
- check_disc_changed (de);
+ for (de = dir->u.dir.first; de != NULL; de = de->next)
+ {
+ if (S_ISBLK (de->mode) && de->u.fcb.removable) break;
+ }
+ devfs_get (de);
}
+ read_unlock (&dir->u.dir.lock);
+ if (de) check_disc_changed (de);
+ devfs_put (de);
} /* End Function scan_dir_for_removable */
/**
@@ -2471,25 +2496,37 @@
* @namelen: The number of characters in <<name>>.
*
* Returns 1 if the media was changed, else 0.
+ *
+ * This function may block, and may indirectly cause the directory
+ * contents to be changed due to partition re-reading. The directory must
+ * be locked for reading upon entry, and will be unlocked upon exit.
*/
static int get_removable_partition (struct devfs_entry *dir, const char *name,
unsigned int namelen)
{
+ int retval;
struct devfs_entry *de;
+ if (dir->u.dir.num_removable < 1)
+ {
+ read_unlock (&dir->u.dir.lock);
+ return 0;
+ }
for (de = dir->u.dir.first; de != NULL; de = de->next)
{
- if ( !S_ISBLK (de->mode) ) continue;
- if (!de->u.fcb.removable) continue;
- if (strcmp (de->name, "disc") == 0) return check_disc_changed (de);
+ if (!S_ISBLK (de->mode) || !de->u.fcb.removable) continue;
+ if (strcmp (de->name, "disc") == 0) break;
/* Support for names where the partition is appended to the disc name
*/
if (de->namelen >= namelen) continue;
- if (strncmp (de->name, name, de->namelen) != 0) continue;
- return check_disc_changed (de);
+ if (strncmp (de->name, name, de->namelen) == 0) break;
}
- return 0;
+ devfs_get (de);
+ read_unlock (&dir->u.dir.lock);
+ retval = de ? check_disc_changed (de) : 0;
+ devfs_put (de);
+ return retval;
} /* End Function get_removable_partition */
@@ -2738,15 +2775,22 @@
{
file->f_op = &def_blk_fops;
if (df->ops) inode->i_bdev->bd_op = df->ops;
+ err = def_blk_fops.open (inode, file);
}
- else file->f_op = fops_get ( (struct file_operations *) df->ops );
- if (file->f_op)
- err = file->f_op->open ? (*file->f_op->open) (inode, file) : 0;
else
{
- /* Fallback to legacy scheme */
- if ( S_ISCHR (inode->i_mode) ) err = chrdev_open (inode, file);
- else err = -ENODEV;
+ file->f_op = fops_get ( (struct file_operations *) df->ops );
+ if (file->f_op)
+ {
+ lock_kernel ();
+ err = file->f_op->open ? (*file->f_op->open) (inode, file) : 0;
+ unlock_kernel ();
+ }
+ else
+ { /* Fallback to legacy scheme */
+ if ( S_ISCHR (inode->i_mode) ) err = chrdev_open (inode, file);
+ else err = -ENODEV;
+ }
}
if (err < 0) return err;
/* Open was successful */
@@ -2946,15 +2990,17 @@
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);
- if ( (de == NULL) && (parent->u.dir.num_removable > 0) &&
- get_removable_partition (parent, dentry->d_name.name,
- dentry->d_name.len) )
- {
- 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) read_unlock (&parent->u.dir.lock);
+ else
+ { /* Try re-reading the partition (media may have changed) */
+ if ( get_removable_partition (parent, dentry->d_name.name,
+ dentry->d_name.len) ) /* Unlocks */
+ { /* Media did change */
+ 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);
@@ -3112,10 +3158,10 @@
if (de == NULL) return -ENOENT;
if ( !S_ISDIR (de->mode) ) return -ENOTDIR;
if (!de->vfs_deletable) return -EPERM;
- /* First ensure the directory is empty and will stay thay way */
+ /* First ensure the directory is empty and will stay that way */
write_lock (&de->u.dir.lock);
- de->u.dir.no_more_additions = TRUE;
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 it's parent */
@@ -3237,7 +3283,7 @@
return sb;
out_no_root:
- printk ("devfs_read_super: get root inode failed\n");
+ PRINTK ("(): get root inode failed\n");
if (root_inode) iput (root_inode);
return NULL;
} /* End Function devfs_read_super */
@@ -3464,7 +3510,7 @@
{
int err;
- printk ("%s: v%s Richard Gooch (rgooch@atnf.csiro.au)\n",
+ printk (KERN_INFO "%s: v%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),
@@ -3472,9 +3518,9 @@
if (!devfsd_buf_cache) OOPS ("(): unable to allocate event slab\n");
#ifdef CONFIG_DEVFS_DEBUG
devfs_debug = devfs_debug_init;
- printk ("%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug);
+ printk (KERN_INFO "%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug);
#endif
- printk ("%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options);
+ printk (KERN_INFO "%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options);
err = register_filesystem (&devfs_fs_type);
if (!err)
{
@@ -3491,8 +3537,8 @@
if ( !(boot_options & OPTION_MOUNT) ) return;
err = do_mount ("none", "/dev", "devfs", 0, "");
- if (err == 0) printk ("Mounted devfs on /dev\n");
- else printk ("Warning: unable to mount devfs, err: %d\n", err);
+ 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)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)