------=_NextPart_000_001C_01BEAF9F.E8D9EED0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
I think you ran into the same problem I had a few weeks ago:
I typed
#swapon /dev/hda1
instead of
#swapon /dev/hda3
and the computer hung.
The problem:
the kernel prevents you from mounting a filesystem twice, and
it prevents you from mouting a swap partition twice,
but if you call sys_swapon() on a filesystem, the this crashes:
(try "swapon /dev/<root>", [fsck...])
- sys_swapon() must set the block size, otherwise it
can't check the superblock
- settings the blocksize prevents the filesystem from
accessing the device
--> crash.
I've written and posted a patch, but I received no replies.
I've attached the patch, but I tested it only with 2.2.6.
--
Manfred
------=_NextPart_000_001C_01BEAF9F.E8D9EED0
Content-Type: application/octet-stream;
name="patch_busy-2.2.6"
Content-Disposition: attachment;
filename="patch_busy-2.2.6"
Content-Transfer-Encoding: quoted-printable
// $Header: /pub/cvs/ms/patches/patch_busy-2.2.6,v 1.1 1999/05/26 =
15:21:45 ms Exp $
diff -r -u -P -x CVS -x *,v 2.2.6/drivers/block/ll_rw_blk.c =
current/drivers/block/ll_rw_blk.c
--- 2.2.6/drivers/block/ll_rw_blk.c Wed Mar 31 00:56:57 1999
+++ current/drivers/block/ll_rw_blk.c Thu Apr 22 18:02:20 1999
@@ -16,6 +16,7 @@
#include <linux/config.h>
#include <linux/locks.h>
#include <linux/mm.h>
+#include <linux/slab.h>
#include <linux/init.h>
=20
#include <asm/system.h>
@@ -241,8 +242,24 @@
}
=20
/* RO fail safe mechanism */
+/* device busy: (C) Manfred Spraul masp0008@stud.uni-sb.de */
=20
-static long ro_bits[MAX_BLKDEV][8];
+struct kdev_bits {
+ unsigned char ro_bits[(1U << MINORBITS)/8];
+ unsigned char busy_bits[(1U << MINORBITS)/8];
+};
+
+static struct kdev_bits* kdev_info[MAX_BLKDEV] =3D { NULL, NULL };
+
+#define ALLOC_KDEV_BITS(major) \
+ if (kdev_info[major] =3D=3D NULL) { \
+ kdev_info[major] =3D kmalloc(sizeof(struct kdev_bits),GFP_KERNEL); \
+ if(kdev_info[major] =3D=3D NULL) { \
+ printk("ALLOC_KDEV_BITS() failed due to ENOMEM.\n"); \
+ return; \
+ } \
+ memset(kdev_info[major],0,sizeof(struct kdev_bits)); \
+ }
=20
int is_read_only(kdev_t dev)
{
@@ -251,7 +268,8 @@
major =3D MAJOR(dev);
minor =3D MINOR(dev);
if (major < 0 || major >=3D MAX_BLKDEV) return 0;
- return ro_bits[major][minor >> 5] & (1 << (minor & 31));
+ if (kdev_info[major] =3D=3D NULL) return 0;
+ return kdev_info[major]->ro_bits[minor >> 3] & (1 << (minor & =
7));
}
=20
void set_device_ro(kdev_t dev,int flag)
@@ -261,10 +279,39 @@
major =3D MAJOR(dev);
minor =3D MINOR(dev);
if (major < 0 || major >=3D MAX_BLKDEV) return;
- if (flag) ro_bits[major][minor >> 5] |=3D 1 << (minor & 31);
- else ro_bits[major][minor >> 5] &=3D ~(1 << (minor & 31));
+ ALLOC_KDEV_BITS(major)
+ if (flag)
+ kdev_info[major]->ro_bits[minor >> 3] |=3D 1 << (minor & 7);
+ else
+ kdev_info[major]->ro_bits[minor >> 3] &=3D ~(1 << (minor & 7));
+}
+
+int is_device_busy(kdev_t dev)
+{
+ int minor,major;
+
+ major =3D MAJOR(dev);
+ minor =3D MINOR(dev);
+ if (major < 0 || major >=3D MAX_BLKDEV) return 0;
+ if (kdev_info[major] =3D=3D NULL) return 0;
+ return kdev_info[major]->busy_bits[minor >> 3] & (1 << (minor & 7));
}
=20
+void set_device_busy(kdev_t dev,int flag)
+{
+ int minor,major;
+=09
+ major =3D MAJOR(dev);
+ minor =3D MINOR(dev);
+ if (major < 0 || major >=3D MAX_BLKDEV) return;
+ ALLOC_KDEV_BITS(major)
+ if (flag)
+ kdev_info[major]->busy_bits[minor >> 3] |=3D 1 << (minor & 7);
+ else
+ kdev_info[major]->busy_bits[minor >> 3] &=3D ~(1 << (minor & 7));
+}
+
+
static inline void drive_stat_acct(int cmd, unsigned long nr_sectors,
short disk_index)
{
@@ -731,7 +778,6 @@
req->rq_status =3D RQ_INACTIVE;
req->next =3D NULL;
}
- memset(ro_bits,0,sizeof(ro_bits));
memset(max_readahead, 0, sizeof(max_readahead));
memset(max_sectors, 0, sizeof(max_sectors));
#ifdef CONFIG_AMIGA_Z2RAM
diff -r -u -P -x CVS -x *,v 2.2.6/fs/super.c current/fs/super.c
--- 2.2.6/fs/super.c Tue Apr 20 13:41:57 1999
+++ current/fs/super.c Thu Apr 22 18:02:20 1999
@@ -131,6 +131,7 @@
vfsmnttail->mnt_next =3D lptr;
vfsmnttail =3D lptr;
}
+ set_device_busy(sb->s_dev,1);
out:
return lptr;
}
@@ -165,6 +166,8 @@
kfree(tofree->mnt_devname);
kfree(tofree->mnt_dirname);
kfree_s(tofree, sizeof(struct vfsmount));
+
+ set_device_busy(dev,0);
}
=20
int register_filesystem(struct file_system_type * fs)
@@ -873,6 +876,8 @@
if (dir_d->d_covers !=3D dir_d)
goto dput_and_out;
=20
+ if (is_device_busy(dev))
+ goto dput_and_out;
/*
* Note: If the superblock already exists,
* read_super just does a get_super().
diff -r -u -P -x CVS -x *,v 2.2.6/include/linux/fs.h =
current/include/linux/fs.h
--- 2.2.6/include/linux/fs.h Tue Apr 20 13:41:58 1999
+++ current/include/linux/fs.h Thu Apr 22 18:02:20 1999
@@ -839,6 +839,8 @@
extern struct buffer_head * find_buffer(kdev_t dev, int block, int =
size);
extern void ll_rw_block(int, int, struct buffer_head * bh[]);
extern int is_read_only(kdev_t);
+extern int is_device_busy(kdev_t);
+extern void set_device_busy(kdev_t dev, int flag);
extern void __brelse(struct buffer_head *);
extern inline void brelse(struct buffer_head *buf)
{
diff -r -u -P -x CVS -x *,v 2.2.6/kernel/ksyms.c current/kernel/ksyms.c
--- 2.2.6/kernel/ksyms.c Wed Mar 31 00:56:57 1999
+++ current/kernel/ksyms.c Thu Apr 22 18:02:20 1999
@@ -47,7 +47,7 @@
#endif
=20
extern char *get_options(char *str, int *ints);
-extern void set_device_ro(kdev_t dev,int flag);
+extern void set_device_ro(kdev_t dev, int flag);
extern struct file_operations * get_blkfops(unsigned int);
extern int blkdev_release(struct inode * inode);
#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
@@ -209,6 +209,8 @@
EXPORT_SYMBOL(blk_dev);
EXPORT_SYMBOL(is_read_only);
EXPORT_SYMBOL(set_device_ro);
+EXPORT_SYMBOL(is_device_busy);
+EXPORT_SYMBOL(set_device_busy);
EXPORT_SYMBOL(bmap);
EXPORT_SYMBOL(sync_dev);
EXPORT_SYMBOL(get_blkfops);
diff -r -u -P -x CVS -x *,v 2.2.6/mm/swapfile.c current/mm/swapfile.c
--- 2.2.6/mm/swapfile.c Wed Mar 31 00:56:57 1999
+++ current/mm/swapfile.c Thu Apr 22 18:02:20 1999
@@ -414,6 +414,7 @@
filp.f_op->release(dentry->d_inode,&filp);
filp.f_op->release(dentry->d_inode,&filp);
}
+ set_device_busy(p->swap_device,0);
}
dput(dentry);
=20
@@ -531,6 +532,10 @@
=20
if (S_ISBLK(swap_dentry->d_inode->i_mode)) {
p->swap_device =3D swap_dentry->d_inode->i_rdev;
+ if(is_device_busy(p->swap_device)) {
+ error =3D -EBUSY;
+ goto bad_swap;
+ }
set_blocksize(p->swap_device, PAGE_SIZE);
=09
filp.f_dentry =3D swap_dentry;
@@ -686,6 +691,8 @@
swap_info[prev].next =3D p - swap_info;
}
error =3D 0;
+ if(p->swap_device !=3D 0)
+ set_device_busy(p->swap_device,1);
goto out;
bad_swap:
if(filp.f_op && filp.f_op->release)
------=_NextPart_000_001C_01BEAF9F.E8D9EED0--
-
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/