Commit 4d40f872 authored by Richard Gooch's avatar Richard Gooch

[PATCH] devfs patch for 2.5.8-pre2

- Documentation updates
- BKL removal (devfs doesn't need the BKL)
- Changed <devfs_rmdir> to allow later additions if not yet empty
- Added calls to <devfs_register_partitions> in drivers/block/blkpc.c
  <add_partition> and <del_partition>
- Bug fixes in unique number and devnum allocators.
parent d720d94f
......@@ -1885,3 +1885,23 @@ Changes for patch v208
- Cleaned up declaration of <stat_read>
- Updated README from master HTML file
===============================================================================
Changes for patch v209
- Updated README from master HTML file
- Removed silently introduced calls to lock_kernel() and
unlock_kernel() due to recent VFS locking changes. BKL isn't
required in devfs
- Changed <devfs_rmdir> to allow later additions if not yet empty
- Added calls to <devfs_register_partitions> in drivers/block/blkpc.c
<add_partition> and <del_partition>
- Fixed bug in <devfs_alloc_unique_number>: was clearing beyond
bitfield
- Fixed bitfield data type for <devfs_*alloc_devnum>
- Made major bitfield type and initialiser 64 bit safe
......@@ -3,7 +3,7 @@ Devfs (Device File System) FAQ
Linux Devfs (Device File System) FAQ
Richard Gooch
24-JAN-2002
4-APR-2002
Document languages:
......@@ -803,12 +803,19 @@ devfsd /dev
add the following lines to your /etc/devfsd.conf file:
REGISTER ^pt[sy]/.* IGNORE
CHANGE ^pt[sy]/.* IGNORE
REGISTER ^pt[sy] IGNORE
CREATE ^pt[sy] IGNORE
CHANGE ^pt[sy] IGNORE
DELETE ^pt[sy] IGNORE
REGISTER .* COPY /dev-state/$devname $devpath
CHANGE .* COPY $devpath /dev-state/$devname
CREATE .* COPY $devpath /dev-state/$devname
CHANGE .* COPY $devpath /dev-state/$devname
DELETE .* CFUNCTION GLOBAL unlink /dev-state/$devname
RESTORE /dev-state
Note that the sample devfsd.conf file contains these lines,
as well as other sample configurations you may find useful. See the
devfsd distribution
reboot.
......@@ -872,7 +879,8 @@ You can then slowly migrate your system to using the new device names
(for example, by starting with /etc/fstab), and then limiting the
compatibility entries that devfsd creates.
MAKE SURE YOU INSTALL DEVFSD BEFORE YOU BOOT A DEVFS-ENABLED KERNEL!
IF YOU CONFIGURE TO MOUNT DEVFS AT BOOT, MAKE SURE YOU INSTALL DEVFSD
BEFORE YOU BOOT A DEVFS-ENABLED KERNEL!
Now that devfs has gone into the 2.3.46 kernel, I'm getting a lot of
reports back. Many of these are because people are trying to run
......@@ -1565,6 +1573,24 @@ character device, named pipe, etc.) may change without notice. Only
the existence of the entry should be relied upon.
When I start devfsd, I see the error:
Error opening file: ".devfsd" No such file or directory?
This means that devfs is not mounted. Make sure you have devfs mounted.
How do I mount devfs?
First make sure you have devfs compiled into your kernel (see
above). Then you will either need to:
set CONFIG_DEVFS_MOUNT=y in your kernel config
pass devfs=mount to your boot loader
mount devfs manually in your boot scripts with:
mount -t none devfs /dev
......@@ -1760,6 +1786,15 @@ steps below:
make sure you have enabled debugging output when configuring your
kernel. You will need to set (at least) the following config options:
CONFIG_DEVFS_DEBUG=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_SLAB=y
please make sure you have the latest devfs patches applied. The
latest kernel version might not have the latest devfs patches applied
yet (Linus is very busy)
......@@ -1768,7 +1803,10 @@ yet (Linus is very busy)
save a copy of your complete kernel logs (preferably by
using the dmesg programme) for later inclusion in your bug
report. You may need to use the -s switch to increase the
internal buffer size so you can capture all the boot messages
internal buffer size so you can capture all the boot messages.
Don't edit or trim the dmesg output
try booting with devfs=dall passed to the kernel boot
......@@ -1925,7 +1963,7 @@ http://www.atnf.csiro.au/~rgooch/linux/docs/devfs.html
A Korean translation by viatoris@nownuri.net is available at
http://viatoris.new21.org/devfs/devfs.html
http://your.destiny.pe.kr/devfs/devfs.html
......
......@@ -113,6 +113,7 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p)
g->part[minor].nr_sects = plength;
if (g->sizes)
g->sizes[minor] = (plength >> (BLOCK_SIZE_BITS - 9));
devfs_register_partitions (g, first_minor, 0);
return 0;
}
......@@ -172,6 +173,7 @@ int del_partition(struct block_device *bdev, struct blkpg_partition *p)
g->part[minor].nr_sects = 0;
if (g->sizes)
g->sizes[minor] = 0;
devfs_register_partitions (g, first_minor, 0);
bd_release(bdevp);
bdput(bdevp);
......
......@@ -612,6 +612,14 @@
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
20020406 Richard Gooch <rgooch@atnf.csiro.au>
Removed silently introduced calls to lock_kernel() and
unlock_kernel() due to recent VFS locking changes. BKL isn't
required in devfs.
v1.13
*/
#include <linux/types.h>
#include <linux/errno.h>
......@@ -644,7 +652,7 @@
#include <asm/bitops.h>
#include <asm/atomic.h>
#define DEVFS_VERSION "1.11 (20020129)"
#define DEVFS_VERSION "1.13 (20020406)"
#define DEVFS_NAME "devfs"
......@@ -2667,7 +2675,7 @@ static int devfs_readdir (struct file *file, void *dirent, filldir_t filldir)
case 0:
scan_dir_for_removable (parent);
err = (*filldir) (dirent, "..", 2, file->f_pos,
parent_ino(file->f_dentry), DT_DIR);
parent_ino (file->f_dentry), DT_DIR);
if (err == -EINVAL) break;
if (err < 0) return err;
file->f_pos++;
......@@ -2933,14 +2941,10 @@ static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry)
up on any error */
dentry->d_op = &devfs_dops;
/* First try to get the devfs entry for this directory */
lock_kernel();
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) {
unlock_kernel();
return ERR_PTR (-ENOENT);
}
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);
......@@ -2965,7 +2969,6 @@ static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry)
if (try_modload (parent, fs_info,
dentry->d_name.name, dentry->d_name.len, &tmp) < 0)
{ /* Lookup event was not queued to devfsd */
unlock_kernel();
d_add (dentry, NULL);
return NULL;
}
......@@ -3008,7 +3011,6 @@ static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry)
wake_up (&lookup_info.wait_queue);
write_unlock (&parent->u.dir.lock);
devfs_put (de);
unlock_kernel();
return retval;
} /* End Function devfs_lookup */
......@@ -3019,30 +3021,19 @@ static int devfs_unlink (struct inode *dir, struct dentry *dentry)
struct inode *inode = dentry->d_inode;
struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
lock_kernel();
de = get_devfs_entry_from_vfs_inode (inode);
DPRINTK (DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de);
if (de == NULL) {
unlock_kernel();
return -ENOENT;
}
if (!de->vfs_deletable) {
unlock_kernel();
return -EPERM;
}
if (de == NULL) return -ENOENT;
if (!de->vfs_deletable) return -EPERM;
write_lock (&de->parent->u.dir.lock);
unhooked = _devfs_unhook (de);
write_unlock (&de->parent->u.dir.lock);
if (!unhooked) {
unlock_kernel();
return -ENOENT;
}
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, 0);
free_dentry (de);
devfs_put (de);
unlock_kernel();
return 0;
} /* End Function devfs_unlink */
......@@ -3055,37 +3046,27 @@ static int devfs_symlink (struct inode *dir, struct dentry *dentry,
struct inode *inode;
/* First try to get the devfs entry for this directory */
lock_kernel();
parent = get_devfs_entry_from_vfs_inode (dir);
if (parent == NULL) {
unlock_kernel();
return -ENOENT;
}
if (parent == NULL) return -ENOENT;
err = devfs_do_symlink (parent, dentry->d_name.name, DEVFS_FL_NONE,
symname, &de, NULL);
DPRINTK (DEBUG_DISABLED, "(%s): errcode from <devfs_do_symlink>: %d\n",
dentry->d_name.name, err);
if (err < 0) {
unlock_kernel();
return err;
}
if (err < 0) return err;
de->vfs_deletable = 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 ) {
unlock_kernel();
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, 0);
unlock_kernel();
return 0;
} /* End Function devfs_symlink */
......@@ -3097,38 +3078,26 @@ static int devfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
struct inode *inode;
mode = (mode & ~S_IFMT) | S_IFDIR; /* VFS doesn't pass S_IFMT part */
lock_kernel();
parent = get_devfs_entry_from_vfs_inode (dir);
if (parent == NULL) {
unlock_kernel();
return -ENOENT;
}
if (parent == NULL) return -ENOENT;
de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
if (!de) {
unlock_kernel();
return -ENOMEM;
}
if (!de) return -ENOMEM;
de->vfs_deletable = TRUE;
if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 ) {
unlock_kernel();
if ( ( err = _devfs_append_entry (parent, de, FALSE, 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 ) {
unlock_kernel();
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, 0);
unlock_kernel();
return 0;
} /* End Function devfs_mkdir */
......@@ -3139,45 +3108,27 @@ static int devfs_rmdir (struct inode *dir, struct dentry *dentry)
struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
struct inode *inode = dentry->d_inode;
/* WTF??? */
if (dir->i_sb->u.generic_sbp != inode->i_sb->u.generic_sbp) return -EINVAL;
lock_kernel();
de = get_devfs_entry_from_vfs_inode (inode);
if (de == NULL) {
unlock_kernel();
return -ENOENT;
}
if ( !S_ISDIR (de->mode) ) {
unlock_kernel();
return -ENOTDIR;
}
if (!de->vfs_deletable) {
unlock_kernel();
return -EPERM;
}
/* First ensure the directory is empty and will stay thay way */
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 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) {
unlock_kernel();
return err;
}
if (err) return err;
/* Now unhook the directory from it's parent */
write_lock (&de->parent->u.dir.lock);
if ( !_devfs_unhook (de) ) err = -ENOENT;
write_unlock (&de->parent->u.dir.lock);
if (err) {
unlock_kernel();
return err;
}
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, 0);
free_dentry (de);
devfs_put (de);
unlock_kernel();
return 0;
} /* End Function devfs_rmdir */
......@@ -3191,43 +3142,31 @@ static int devfs_mknod (struct inode *dir, struct dentry *dentry, int mode,
DPRINTK (DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %d\n",
dentry->d_name.name, mode, rdev);
lock_kernel();
parent = get_devfs_entry_from_vfs_inode (dir);
if (parent == NULL) {
unlock_kernel();
return -ENOENT;
}
if (parent == NULL) return -ENOENT;
de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
if (!de) {
unlock_kernel();
return -ENOMEM;
}
if (!de) return -ENOMEM;
de->vfs_deletable = TRUE;
if ( S_ISBLK (mode) || S_ISCHR (mode) )
{
de->u.fcb.u.device.major = MAJOR (rdev);
de->u.fcb.u.device.minor = MINOR (rdev);
}
if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 ) {
unlock_kernel();
if ( ( err = _devfs_append_entry (parent, de, FALSE, 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 ) {
unlock_kernel();
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, 0);
unlock_kernel();
return 0;
} /* End Function devfs_mknod */
......@@ -3301,18 +3240,19 @@ static int devfs_fill_super (struct super_block *sb, void *data, int silent)
PRINTK ("(): get root inode failed\n");
if (root_inode) iput (root_inode);
return -EINVAL;
} /* End Function devfs_read_super */
} /* End Function devfs_fill_super */
static struct super_block *devfs_get_sb(struct file_system_type *fs_type,
int flags, char *dev_name, void *data)
static struct super_block *devfs_get_sb (struct file_system_type *fs_type,
int flags, 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 */
......
/* devfs (Device FileSystem) utilities.
Copyright (C) 1999-2001 Richard Gooch
Copyright (C) 1999-2002 Richard Gooch
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
......@@ -48,6 +48,12 @@
20010818 Richard Gooch <rgooch@atnf.csiro.au>
Updated major masks up to Linus' "no new majors" proclamation.
Block: were 126 now 122 free, char: were 26 now 19 free.
20020324 Richard Gooch <rgooch@atnf.csiro.au>
Fixed bug in <devfs_alloc_unique_number>: was clearing beyond
bitfield.
20020326 Richard Gooch <rgooch@atnf.csiro.au>
Fixed bitfield data type for <devfs_*alloc_devnum>.
Made major bitfield type and initialiser 64 bit safe.
*/
#include <linux/module.h>
#include <linux/init.h>
......@@ -125,8 +131,13 @@ EXPORT_SYMBOL(devfs_register_series);
struct major_list
{
spinlock_t lock;
__u32 bits[8];
unsigned long bits[256 / BITS_PER_LONG];
};
#if BITS_PER_LONG == 32
# define INITIALISER64(low,high) (low), (high)
#else
# define INITIALISER64(low,high) ( (high) << 32 | (low) )
#endif
/* Block majors already assigned:
0-3, 7-9, 11-63, 65-99, 101-113, 120-127, 199, 201, 240-255
......@@ -134,14 +145,11 @@ struct major_list
*/
static struct major_list block_major_list =
{SPIN_LOCK_UNLOCKED,
{0xfffffb8f, /* Majors 0 to 31 */
0xffffffff, /* Majors 32 to 63 */
0xfffffffe, /* Majors 64 to 95 */
0xff03ffef, /* Majors 96 to 127 */
0x00000000, /* Majors 128 to 159 */
0x00000000, /* Majors 160 to 191 */
0x00000280, /* Majors 192 to 223 */
0xffff0000} /* Majors 224 to 255 */
{INITIALISER64 (0xfffffb8f, 0xffffffff), /* Majors 0-31, 32-63 */
INITIALISER64 (0xfffffffe, 0xff03ffef), /* Majors 64-95, 96-127 */
INITIALISER64 (0x00000000, 0x00000000), /* Majors 128-159, 160-191 */
INITIALISER64 (0x00000280, 0xffff0000), /* Majors 192-223, 224-255 */
}
};
/* Char majors already assigned:
......@@ -150,14 +158,11 @@ static struct major_list block_major_list =
*/
static struct major_list char_major_list =
{SPIN_LOCK_UNLOCKED,
{0xfffffeff, /* Majors 0 to 31 */
0xffffffff, /* Majors 32 to 63 */
0xffffffff, /* Majors 64 to 95 */
0xffffffff, /* Majors 96 to 127 */
0x7cffffff, /* Majors 128 to 159 */
0xffffffff, /* Majors 160 to 191 */
0x3f0fffff, /* Majors 192 to 223 */
0xffff007f} /* Majors 224 to 255 */
{INITIALISER64 (0xfffffeff, 0xffffffff), /* Majors 0-31, 32-63 */
INITIALISER64 (0xffffffff, 0xffffffff), /* Majors 64-95, 96-127 */
INITIALISER64 (0x7cffffff, 0xffffffff), /* Majors 128-159, 160-191 */
INITIALISER64 (0x3f0fffff, 0xffff007f), /* Majors 192-223, 224-255 */
}
};
......@@ -212,7 +217,7 @@ EXPORT_SYMBOL(devfs_dealloc_major);
struct minor_list
{
int major;
__u32 bits[8];
unsigned long bits[256 / BITS_PER_LONG];
struct minor_list *next;
};
......@@ -267,7 +272,7 @@ kdev_t devfs_alloc_devnum (char type)
if (minor >= 256) continue;
__set_bit (minor, entry->bits);
up (semaphore);
return mk_kdev(entry->major, minor);
return mk_kdev (entry->major, minor);
}
/* Need to allocate a new major */
if ( ( entry = kmalloc (sizeof *entry, GFP_KERNEL) ) == NULL )
......@@ -289,7 +294,7 @@ kdev_t devfs_alloc_devnum (char type)
else list->last->next = entry;
list->last = entry;
up (semaphore);
return mk_kdev(entry->major, 0);
return mk_kdev (entry->major, 0);
} /* End Function devfs_alloc_devnum */
EXPORT_SYMBOL(devfs_alloc_devnum);
......@@ -309,7 +314,7 @@ void devfs_dealloc_devnum (char type, kdev_t devnum)
struct device_list *list;
struct minor_list *entry;
if (kdev_none(devnum)) return;
if ( kdev_none (devnum) ) return;
if (type == DEVFS_SPECIAL_CHR)
{
semaphore = &char_semaphore;
......@@ -355,7 +360,6 @@ int devfs_alloc_unique_number (struct unique_numspace *space)
{
int number;
unsigned int length;
__u32 *bits;
/* Get around stupid lack of semaphore initialiser */
spin_lock (&space->init_lock);
......@@ -368,6 +372,8 @@ int devfs_alloc_unique_number (struct unique_numspace *space)
down (&space->semaphore);
if (space->num_free < 1)
{
void *bits;
if (space->length < 16) length = 16;
else length = space->length << 1;
if ( ( bits = vmalloc (length) ) == NULL )
......
......@@ -54,7 +54,7 @@ struct unique_numspace
unsigned char sem_initialised;
unsigned int num_free; /* Num free in bits */
unsigned int length; /* Array length in bytes */
__u32 *bits;
unsigned long *bits;
struct semaphore semaphore;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment