defvs patch v84 for linux 2.2.0-pre9 bugfix

Heinz Mauelshagen (mauelsha@ez-darmstadt.telekom.de)
Sat, 23 Jan 1999 14:44:45 MET


Hi Richard!

Yesterday i gave myself a chance to have a look at your devfs patch
for Linux 2.2.0-pre9 8*)

I found a little bug, which seems to cause non standard block devices
beeing _not_ mountable any more.
In detail, my logical volume manager block devices don't work.
The block device specials are created by lvm user commands.

I think any software creating block specials should fail with the
v84 code in super.c, where your patch looks like:

@@ -1067,8 +1079,9 @@
if (MAJOR(dev) >= MAX_BLKDEV)
goto dput_and_out;

- retval = -ENOTBLK;
- dummy.f_op = get_blkfops(MAJOR(dev));
+ retval = devfs_fill_file (inode, &dummy, NULL);
+ if ( !retval && !S_ISBLK (inode->i_mode) ) retval = -ENOTBLK;
+ if (retval < 0) dummy.f_op = get_blkfops(MAJOR(dev));
if (!dummy.f_op)
goto dput_and_out;

Please give me feedback.
Best regards and keep up the good work,
Heinz

Patch against stock linux-2.2.0-pre9/fs/super.c to fix the problem follows:

--- linux/fs/super.c.orig Thu Jan 7 00:01:25 1999
+++ linux/fs/super.c Sat Jan 23 14:29:27 1999
@@ -15,12 +15,14 @@
*
* Added kerneld support: Jacques Gelinas and Bjorn Ekwall
* Added change_root: Werner Almesberger & Hans Lermen, Feb '96
+ * Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998
*/

#include <linux/config.h>
#include <linux/malloc.h>
#include <linux/locks.h>
#include <linux/smp_lock.h>
+#include <linux/devfs_fs.h>
#include <linux/fd.h>
#include <linux/init.h>
#include <linux/quotaops.h>
@@ -739,7 +741,17 @@
if (!retval) {
fsync_dev(dev);
if (dev != ROOT_DEV) {
- blkdev_release(inode);
+ int err;
+ struct file file;
+ void *handle;
+
+ handle = devfs_find_handle (NULL, 0,
+ MAJOR (dev), MINOR (dev),
+ DEVFS_SPECIAL_BLK, 0);
+ err = devfs_fill_file (inode, &file, handle);
+ if (!err && file.f_op && file.f_op->release)
+ file.f_op->release (inode, NULL);
+ if (err) blkdev_release(inode);
put_unnamed_dev(dev);
}
}
@@ -1067,8 +1079,9 @@
if (MAJOR(dev) >= MAX_BLKDEV)
goto dput_and_out;

- retval = -ENOTBLK;
- dummy.f_op = get_blkfops(MAJOR(dev));
+ if ( !( retval = devfs_fill_file (inode, &dummy, NULL)))
+ retval = -ENOTBLK;
+ if ( retval < 0) dummy.f_op = get_blkfops(MAJOR(dev));
if (!dummy.f_op)
goto dput_and_out;

@@ -1122,6 +1135,9 @@
struct inode * d_inode = NULL;
struct file filp;
int retval;
+ void *handle;
+ char path[37];
+ int path_start = -1;

#ifdef CONFIG_ROOT_NFS
if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
@@ -1172,20 +1188,46 @@
filp.f_mode = 1; /* read only */
else
filp.f_mode = 3; /* read write */
- retval = blkdev_open(d_inode, &filp);
+ handle = devfs_find_handle (ROOT_DEVICE_NAME, 0,
+ MAJOR (ROOT_DEV), MINOR (ROOT_DEV),
+ DEVFS_SPECIAL_BLK, 1);
+ retval = devfs_fill_file (d_inode, &filp, handle);
+ if (retval == 0)
+ {
+ path_start = devfs_generate_path (handle, path + 5,
+ sizeof (path) - 5);
+ if (filp.f_op && filp.f_op->open)
+ retval = filp.f_op->open (d_inode, &filp);
+ if (retval == 0) ROOT_DEV = d_inode->i_rdev;
+ }
+ if (retval < 0) retval = blkdev_open(d_inode, &filp);
if (retval == -EROFS) {
root_mountflags |= MS_RDONLY;
filp.f_mode = 1;
- retval = blkdev_open(d_inode, &filp);
+ handle = devfs_find_handle (root_device_name, 0,
+ MAJOR (ROOT_DEV), MINOR (ROOT_DEV),
+ DEVFS_SPECIAL_BLK, 1);
+ retval = devfs_fill_file (d_inode, &filp, handle);
+ if (retval == 0)
+ {
+ path_start = devfs_generate_path (handle, path + 5,
+ sizeof (path) - 5);
+ if (filp.f_op && filp.f_op->open)
+ retval = filp.f_op->open (d_inode, &filp);
+ if (retval == 0) ROOT_DEV = d_inode->i_rdev;
+ }
+ if (retval < 0) retval = blkdev_open(d_inode, &filp);
}
iput(d_inode);
- if (retval)
+ if (retval) {
/*
* Allow the user to distinguish between failed open
* and bad superblock on root device.
*/
- printk("VFS: Cannot open root device %s\n",
- kdevname(ROOT_DEV));
+ printk ("VFS: Cannot open root device \"%s\" or %s\n",
+ root_device_name, kdevname (ROOT_DEV));
+ printk ("Please append a correct \"root=\" boot option\n");
+ }
else for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
if (!(fs_type->fs_flags & FS_REQUIRES_DEV))
continue;
@@ -1197,7 +1239,16 @@
printk ("VFS: Mounted root (%s filesystem)%s.\n",
fs_type->name,
(sb->s_flags & MS_RDONLY) ? " readonly" : "");
- vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
+ if (path_start >= 0) {
+ devfs_mk_symlink (NULL,
+ "root", 0, DEVFS_FL_DEFAULT,
+ path + 5 + path_start, 0,
+ NULL);
+ memcpy (path + path_start, "/dev/", 5);
+ vfsmnt = add_vfsmnt (sb, path + path_start,
+ "/");
+ }
+ else vfsmnt = add_vfsmnt (sb, "/dev/root", "/");
if (vfsmnt)
return;
panic("VFS: add_vfsmnt failed for root fs");
@@ -1224,6 +1275,18 @@
printk(KERN_CRIT "New root is busy. Staying in initrd.\n");
return -EBUSY;
}
+ /* First unmount devfs if mounted */
+ dir_d = lookup_dentry ("/dev", NULL, 1);
+ if (!IS_ERR(dir_d)) {
+ struct super_block *sb = dir_d->d_inode->i_sb;
+
+ if (sb && (dir_d->d_inode == sb->s_root->d_inode) &&
+ (sb->s_magic == DEVFS_SUPER_MAGIC)) {
+ dput (dir_d);
+ do_umount (sb->s_dev, 0, 0);
+ }
+ else dput (dir_d);
+ }
ROOT_DEV = new_root_dev;
mount_root();
dput(old_root);
@@ -1232,6 +1295,7 @@
shrink_dcache();
printk("change_root: old root has d_count=%d\n", old_root->d_count);
#endif
+ mount_devfs_fs ();
/*
* Get the new mount directory
*/

--

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Systemmanagement Entwicklungsbereich 2 Deutsche Telekom AG Entwicklungszentrum Darmstadt Heinz Mauelshagen Otto-Roehm-Strasse 71c Postfach 10 05 41 mge@ez-darmstadt.telekom.de 64205 Darmstadt Germany +49 6151 886-425 FAX-386 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/