aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-05-17 10:03:34 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-05-17 10:03:34 -0700
commitfa82a1dad8713f50233150710637981776dcdf3a (patch)
tree37a452aed9bb5092eb8d53f1befe6f50bfad4ad9
parent7dbe32bed2b9103e744ced54d3f3076e5f01028e (diff)
parenta68d9759bd527662bd605a6462a75f3a59907286 (diff)
downloadhistory-fa82a1dad8713f50233150710637981776dcdf3a.tar.gz
Merge bk://bkbits.ras.ucalgary.ca/rgooch-2.5v2.5.16
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--Documentation/filesystems/devfs/ChangeLog19
-rw-r--r--drivers/char/misc.c11
-rw-r--r--fs/devfs/base.c119
-rw-r--r--fs/devfs/util.c18
4 files changed, 108 insertions, 59 deletions
diff --git a/Documentation/filesystems/devfs/ChangeLog b/Documentation/filesystems/devfs/ChangeLog
index 4c4ddd9d2758c..1db800e739c77 100644
--- a/Documentation/filesystems/devfs/ChangeLog
+++ b/Documentation/filesystems/devfs/ChangeLog
@@ -1912,3 +1912,22 @@ Changes for patch v210
Thanks to Anton Blanchard <anton@samba.org>
- Updated README from master HTML file
+===============================================================================
+Changes for patch v211
+
+- Do not put miscellaneous character devices in /dev/misc if they
+ specify their own directory (i.e. contain a '/' character)
+
+- Copied macro for error messages from fs/devfs/base.c to
+ fs/devfs/util.c and made use of this macro
+
+- Removed 2.4.x compatibility code from fs/devfs/base.c
+===============================================================================
+Changes for patch v212
+
+- Added BKL to <devfs_open> because drivers still need it
+===============================================================================
+Changes for patch v213
+
+- Protected <scan_dir_for_removable> and <get_removable_partition>
+ from changing directory contents
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index bb45e919fc01e..e410c4a65a79b 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -170,7 +170,7 @@ static struct file_operations misc_fops = {
int misc_register(struct miscdevice * misc)
{
- static devfs_handle_t devfs_handle;
+ static devfs_handle_t devfs_handle, dir;
struct miscdevice *c;
if (misc->next || misc->prev)
@@ -201,11 +201,12 @@ int misc_register(struct miscdevice * misc)
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
if (!devfs_handle)
devfs_handle = devfs_mk_dir (NULL, "misc", NULL);
+ dir = strchr (misc->name, '/') ? NULL : devfs_handle;
misc->devfs_handle =
- devfs_register (devfs_handle, misc->name, DEVFS_FL_NONE,
- MISC_MAJOR, misc->minor,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
- misc->fops, NULL);
+ devfs_register (dir, misc->name, DEVFS_FL_NONE,
+ MISC_MAJOR, misc->minor,
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
+ misc->fops, NULL);
/*
* Add it to the front, so that later devices can "override"
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 862f7486cc959..f6d4c7125ebfd 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -620,6 +620,19 @@
unlock_kernel() due to recent VFS locking changes. BKL isn't
required in devfs.
v1.13
+ 20020428 Richard Gooch <rgooch@atnf.csiro.au>
+ Removed 2.4.x compatibility code.
+ v1.14
+ 20020510 Richard Gooch <rgooch@atnf.csiro.au>
+ Added BKL to <devfs_open> because drivers still need it.
+ v1.15
+ 20020512 Richard Gooch <rgooch@atnf.csiro.au>
+ Protected <scan_dir_for_removable> and <get_removable_partition>
+ from changing directory contents.
+ v1.16
+ 20020514 Richard Gooch <rgooch@atnf.csiro.au>
+ Minor cleanup of <scan_dir_for_removable>.
+ v1.17
*/
#include <linux/types.h>
#include <linux/errno.h>
@@ -652,7 +665,7 @@
#include <asm/bitops.h>
#include <asm/atomic.h>
-#define DEVFS_VERSION "1.13 (20020406)"
+#define DEVFS_VERSION "1.17 (20020514)"
#define DEVFS_NAME "devfs"
@@ -1400,16 +1413,8 @@ static void free_dentry (struct devfs_entry *de)
static int is_devfsd_or_child (struct fs_info *fs_info)
{
- struct task_struct *p;
-
if (current == fs_info->devfsd_task) return (TRUE);
if (current->pgrp == fs_info->devfsd_pgrp) return (TRUE);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,1)
- for (p = current->p_opptr; p != &init_task; p = p->p_opptr)
- {
- if (p == fs_info->devfsd_task) return (TRUE);
- }
-#endif
return (FALSE);
} /* End Function is_devfsd_or_child */
@@ -1829,16 +1834,6 @@ devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name, void *info)
de->info = info;
if ( ( err = _devfs_append_entry (dir, de, FALSE, &old) ) != 0 )
{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,1)
- if ( old && S_ISDIR (old->mode) )
- {
- PRINTK ("(%s): using old entry in dir: %p \"%s\"\n",
- name, dir, dir->name);
- old->vfs_deletable = FALSE;
- devfs_put (dir);
- return old;
- }
-#endif
PRINTK ("(%s): could not append to dir: %p \"%s\", err: %d\n",
name, dir, dir->name, err);
devfs_put (old);
@@ -2427,6 +2422,9 @@ static int try_modload (struct devfs_entry *parent, struct fs_info *fs_info,
* @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)
@@ -2461,19 +2459,29 @@ out:
/**
* 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 */
/**
@@ -2483,25 +2491,37 @@ static void scan_dir_for_removable (struct devfs_entry *dir)
* @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 */
@@ -2739,15 +2759,22 @@ static int devfs_open (struct inode *inode, struct file *file)
{
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 */
@@ -2947,15 +2974,17 @@ static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry)
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);
diff --git a/fs/devfs/util.c b/fs/devfs/util.c
index f9c955f6b61c3..9431e7d903b2b 100644
--- a/fs/devfs/util.c
+++ b/fs/devfs/util.c
@@ -56,6 +56,8 @@
Made major bitfield type and initialiser 64 bit safe.
20020413 Richard Gooch <rgooch@atnf.csiro.au>
Fixed shift warning on 64 bit machines.
+ 20020428 Richard Gooch <rgooch@atnf.csiro.au>
+ Copied and used macro for error messages from fs/devfs/base.c
*/
#include <linux/module.h>
#include <linux/init.h>
@@ -65,6 +67,9 @@
#include <asm/bitops.h>
+#define PRINTK(format, args...) \
+ {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);}
+
/* Private functions follow */
@@ -209,9 +214,7 @@ void devfs_dealloc_major (char type, int major)
spin_lock (&list->lock);
was_set = __test_and_clear_bit (major, list->bits);
spin_unlock (&list->lock);
- if (!was_set)
- printk (KERN_ERR __FUNCTION__ "(): major %d was already free\n",
- major);
+ if (!was_set) PRINTK ("(): major %d was already free\n", major);
} /* End Function devfs_dealloc_major */
EXPORT_SYMBOL(devfs_dealloc_major);
@@ -339,12 +342,11 @@ void devfs_dealloc_devnum (char type, kdev_t devnum)
if (was_set) list->none_free = 0;
up (semaphore);
if (!was_set)
- printk ( KERN_ERR __FUNCTION__ "(): device %s was already free\n",
- kdevname (devnum) );
+ PRINTK ( "(): device %s was already free\n", kdevname (devnum) );
return;
}
up (semaphore);
- printk ( KERN_ERR __FUNCTION__ "(): major for %s not previously allocated\n",
+ PRINTK ( "(): major for %s not previously allocated\n",
kdevname (devnum) );
} /* End Function devfs_dealloc_devnum */
EXPORT_SYMBOL(devfs_dealloc_devnum);
@@ -419,8 +421,6 @@ void devfs_dealloc_unique_number (struct unique_numspace *space, int number)
was_set = __test_and_clear_bit (number, space->bits);
if (was_set) ++space->num_free;
up (&space->semaphore);
- if (!was_set)
- printk (KERN_ERR __FUNCTION__ "(): number %d was already free\n",
- number);
+ if (!was_set) PRINTK ("(): number %d was already free\n", number);
} /* End Function devfs_dealloc_unique_number */
EXPORT_SYMBOL(devfs_dealloc_unique_number);