Hi guys,
After many people commented on the deficiencies (well, serious SMP-races!)
of my earlier version of the forced umount support, I have rewritten it to
be safe, to the best of my knowledge.
So, here it is for your comments, testing, improvements etc.
There are no known problems with it so please report to me absolutely
anything suspicious you find.
There are, however, known limitations ;)
o It doesn't catch SCM_RIGHTS datagrams in flight, i.e. passing fds
between processes. This is not a bug but a limitation - umount will
just fail in those cases
o There are possible timings (hopefully "rare" - in quotes because it
depends how busy your apps are) whereby having apps doing io on open
files will cause umount -f still to fail. Again, this is not a bug but
limitation. Basically, there was a choice there between:
a) guaranteed to succeed in almost all cases but be SMP-unsafe
b) best effort service (since the above is not 100% to succeed
anyway) but be safe always.
Again, I repeat that by "succeed" I meant that umount will successfully
umount the filesystem. If it doesn't succeed it will just fail with EBUSY
but no data structures are corrupted - everything remains consistent. (If
you find otherwise - I would like to know!)
The patch is against 2.4.0-test7-pre3 (and also works on
2.4.0-test7-pre2).
Regards,
Tigran
http://www.moses.uklinux.net/patches/badfs-2.4.0-test7-p2.patch
diff -urN -X dontdiff linux/fs/Makefile badfs/fs/Makefile
--- linux/fs/Makefile Thu Aug 10 06:51:11 2000
+++ badfs/fs/Makefile Sat Aug 12 09:14:22 2000
@@ -18,9 +18,9 @@
ALL_SUB_DIRS := coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
hpfs sysv smbfs ncpfs ufs efs affs romfs autofs hfs lockd \
nfsd nls devpts devfs adfs partitions qnx4 udf bfs cramfs \
- openpromfs autofs4 ramfs jffs
+ openpromfs autofs4 ramfs jffs badfs
-SUB_DIRS :=
+SUB_DIRS := badfs
ifeq ($(CONFIG_QUOTA),y)
O_OBJS += dquot.o
diff -urN -X dontdiff linux/fs/badfs/Makefile badfs/fs/badfs/Makefile
--- linux/fs/badfs/Makefile Thu Jan 1 01:00:00 1970
+++ badfs/fs/badfs/Makefile Sat Aug 12 09:14:36 2000
@@ -0,0 +1,9 @@
+#
+# Makefile for badfs filesystem.
+#
+
+O_TARGET := badfs.o
+O_OBJS := inode.o
+M_OBJS := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -urN -X dontdiff linux/fs/badfs/inode.c badfs/fs/badfs/inode.c
--- linux/fs/badfs/inode.c Thu Jan 1 01:00:00 1970
+++ badfs/fs/badfs/inode.c Sat Aug 12 09:21:07 2000
@@ -0,0 +1,265 @@
+/*
+ * badfs - the Bad Filesystem
+ *
+ * Author - Tigran Aivazian <[EMAIL PROTECTED]>
+ *
+ * Thanks to:
+ * Manfred Spraul <[EMAIL PROTECTED]>, for useful comments.
+ *
+ * This file is released under the GPL.
+ *
+ * The badfs filesystem is used by forced umount ('umount -f' command)
+ * to move inodes that keep the filesystem being umounted busy to it.
+ *
+ * The entry point into this module is via quiesce_filesystem() called
+ * from fs/super.c:do_umount() if MNT_FORCE is passed.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#define BADFS_MAGIC0xBADF0001
+
+static struct super_block *badfs_read_super(struct super_block *,void *,int);
+
+#define FS_FLAGS_BADFS (FS_NOMOUNT | FS_SINGLE)
+static DECLARE_FSTYPE(badfs_fs_type,"badfs",badfs_read_super,FS_FLAGS_BADFS);
+
+static struct vfsmount *badfs_mnt; /* returned by kern_mount() */
+static struct super_block *badfs_sb; /* badfs_mnt->mnt_sb */
+static struct dentry *badfs_root; /* badfs_sb->s_root */
+
+static int __init init_badfs_fs(void)
+{
+ int err = register_filesystem(&badfs_fs_type);
+
+ if (!err) {
+ badfs_mnt = kern_mount(&badfs_fs_type);
+ if (IS_ERR(badfs_mnt)) {
+ err = PTR_ERR(badfs_mnt);
+ unregister_filesystem(&badfs_fs_type);
+ } else {
+ badfs_sb = badfs_mnt->mnt_sb;
+ err = 0;
+ }
+ }
+ return err;
+}
+
+module_init(init_badfs_fs);
+
+static struct inode *badfs_get_inode(struct super_block *sb, int mode)
+{
+ struct inode *inode = get_empty_inode();
+
+ if (inode) {
+ make_bad_inode(inode);
+ inode->i_sb = sb;
+ inode->i_dev = sb->s_dev;
+ inode->i_mode = mode;
+ inode->i_nlink = 1;
+ inode->i_size = 0;
+ inode->i_blocks = 0;
+ }
+ return inode;
+}
+
+/* VFS ->read_super() method */
+static struct super_block *badfs_read_super(struct super_block * sb,
+ void * data, int silent)
+{
+ static struct super_operations badfs_ops = {};
+ struct inode * root = badfs_get_inode(sb, S_IFDIR|S_IRUSR|S_IWUSR);
+
+ if (!root)
+ return NULL;
+ sb->s_blocksize = 1024;
+ sb->s_blocksize_bits = 10;
+ sb->s_magic = BADFS_MAGIC;
+ s