diff -ru -x '*.[oas]' -x '*.[oa].flags' -x .depend -x .config -x modversions.h -x '*.ver' -x autoconf.h /usr/src/linux-2.4.20-2mdk/fs/ext2/super.c linux-2.4.20-2mdk/fs/ext2/super.c
--- /usr/src/linux-2.4.20-2mdk/fs/ext2/super.c	2002-11-29 02:53:15.000000000 +0300
+++ linux-2.4.20-2mdk/fs/ext2/super.c	2002-12-31 13:57:33.000000000 +0300
@@ -274,6 +274,12 @@
 		         || !strcmp (this_char, "quota")
 		         || !strcmp (this_char, "usrquota"))
 			/* Don't do anything ;-) */ ;
+#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
+		/* Silently ignore NLS options */
+		else if (!strcmp (this_char, "iocharset")
+		         || !strcmp (this_char, "codepage"))
+			/* Don't do anything ;-) */ ;
+#endif
 		else {
 			printk ("EXT2-fs: Unrecognized mount option %s\n", this_char);
 			return 0;
diff -ru -x '*.[oas]' -x '*.[oa].flags' -x .depend -x .config -x modversions.h -x '*.ver' -x autoconf.h /usr/src/linux-2.4.20-2mdk/fs/fat/file.c linux-2.4.20-2mdk/fs/fat/file.c
--- /usr/src/linux-2.4.20-2mdk/fs/fat/file.c	2001-08-12 21:56:56.000000000 +0400
+++ linux-2.4.20-2mdk/fs/fat/file.c	2002-12-30 14:48:15.000000000 +0300
@@ -117,8 +117,17 @@
 	int cluster;
 
 	/* Why no return value?  Surely the disk could fail... */
+#if 0
+	/*
+	 * Why do we need this check? VFS layer should already have
+	 * checked user access before we ever get here; and we can 
+	 * get here from iput on read-only file system, consider
+	 * remounting file system read-only after changing some file.
+	 * That is exactly what happens with supermount and breaks it
+	 */
 	if (IS_RDONLY (inode))
 		return /* -EPERM */;
+#endif
 	if (IS_IMMUTABLE(inode))
 		return /* -EPERM */;
 	cluster = 1 << sbi->cluster_bits;
diff -ru -x '*.[oas]' -x '*.[oa].flags' -x .depend -x .config -x modversions.h -x '*.ver' -x autoconf.h /usr/src/linux-2.4.20-2mdk/fs/inode.c linux-2.4.20-2mdk/fs/inode.c
--- /usr/src/linux-2.4.20-2mdk/fs/inode.c	2002-12-09 14:38:23.000000000 +0300
+++ linux-2.4.20-2mdk/fs/inode.c	2002-12-31 14:00:36.000000000 +0300
@@ -703,7 +703,11 @@
 {
 	struct super_block *sb = get_super(dev);
 	int res = 0;
+
 	if (sb) {
+#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
+		sb->s_media_changed = 1;
+#endif
 		res = invalidate_inodes(sb);
 		drop_super(sb);
 	}
diff -ru -x '*.[oas]' -x '*.[oa].flags' -x .depend -x .config -x modversions.h -x '*.ver' -x autoconf.h /usr/src/linux-2.4.20-2mdk/fs/supermount/super.c linux-2.4.20-2mdk/fs/supermount/super.c
--- /usr/src/linux-2.4.20-2mdk/fs/supermount/super.c	2002-12-09 14:38:17.000000000 +0300
+++ linux-2.4.20-2mdk/fs/supermount/super.c	2002-12-31 14:12:17.000000000 +0300
@@ -238,9 +238,11 @@
 	down(&sbi->sem);
 
 	if (subfs_is_mounted(sbi)) {
+		struct super_block *subsb = supermount_subfs_sb(sbi);
+
 		/* check for disk change or disk not present */
-		dev = supermount_subfs_sb(sbi)->s_dev;
-		if (!query_disk_change(dev))
+		dev = subsb->s_dev;
+		if (!(subsb->s_media_changed || query_disk_change(dev)))
 			goto mounted;
 
 		/* We have a disk change!  Unmount the subfs */
diff -ru -x '*.[oas]' -x '*.[oa].flags' -x .depend -x .config -x modversions.h -x '*.ver' -x autoconf.h /usr/src/linux-2.4.20-2mdk/fs/supermount/super_operations.c linux-2.4.20-2mdk/fs/supermount/super_operations.c
--- /usr/src/linux-2.4.20-2mdk/fs/supermount/super_operations.c	2002-12-09 14:38:17.000000000 +0300
+++ linux-2.4.20-2mdk/fs/supermount/super_operations.c	2002-12-31 14:14:27.000000000 +0300
@@ -113,6 +113,7 @@
 		kfree(sbi->s_data);
 	if (sbi->s_data_copy)
 		kfree(sbi->s_data_copy);
+	kfree(sbi);
 }
 
 /* Release the superblock and any resources it has reserved 
@@ -128,6 +129,7 @@
 
 	if (subfs_is_mounted(sbi))
 		subfs_umount(sb);
+	sb->u.generic_sbp = 0;
 	free_sbi(sbi);
 	sb->s_dev = 0;
 }
@@ -219,20 +221,6 @@
 	if (!sbi)
 		goto fail_no_memory;
 
-	s->s_blocksize = 1024;
-	s->s_blocksize_bits = 10;
-	s->s_magic = SUPERMOUNT_SUPER_MAGIC;
-	s->s_op = &supermount_sops;
-	s->u.generic_sbp = sbi;
-
-	root_inode = supermount_root_inode(s);
-	if (!root_inode)
-		goto fail_allocating_root_inode;
-
-	root = d_alloc_root(root_inode);
-	if (!root)
-		goto fail_allocating_root_dentry;
-
 	if (parse_options((char *) data, sbi))
 		goto fail_parsing;
 
@@ -241,6 +229,7 @@
 				 "no dev=<filesystem> option");
 		goto fail_parsing;
 	}
+
 	if (sbi->s_data) {
 		sbi->s_data_copy = kmalloc(1 + strlen(sbi->s_data), GFP_KERNEL);
 		if (!sbi->s_data_copy) {
@@ -252,24 +241,35 @@
 	} else
 		sbi->s_data_copy = NULL;
 
+	s->s_blocksize = 1024;
+	s->s_blocksize_bits = 10;
+	s->s_magic = SUPERMOUNT_SUPER_MAGIC;
+	s->s_op = &supermount_sops;
+	s->u.generic_sbp = sbi;
+
+	root_inode = supermount_root_inode(s);
+	if (!root_inode)
+		goto fail_allocating_root_inode;
+
+	root = d_alloc_root(root_inode);
+	if (!root)
+		goto fail_allocating_root_dentry;
+
 	s->s_root = root;
 	s->s_root->d_op = &supermount_dir_dops;
-	dget(root);
 
 	return s;
-fail_parsing:
-	s->s_dev = 0;
-	dput(root);
 
+fail_allocating_root_dentry:
+	iput(root_inode);
+
+fail_parsing:
 fail_allocating_root_inode:
 	free_sbi(sbi);
+
 fail_no_memory:
 	return NULL;
 
-fail_allocating_root_dentry:
-	/* the dput() will do the iput() */
-	iput(root_inode);
-	goto fail_allocating_root_inode;
 }
 
 /*
@@ -304,47 +304,9 @@
 	return rc;
 }
 
-/* Stolen from dcache.c, have to convince viro to export it
- */
-
-static inline void dentry_iput(struct dentry * dentry)
-{
-	struct inode *inode = dentry->d_inode;
-	if (inode) {
-		dentry->d_inode = NULL;
-		list_del_init(&dentry->d_alias);
-		spin_unlock(&dcache_lock);
-		if (dentry->d_op && dentry->d_op->d_iput)
-			dentry->d_op->d_iput(dentry, inode);
-		else
-			iput(inode);
-	} else
-		spin_unlock(&dcache_lock);
-}
-
-/* Based in force_delete, but we here have to also remove the
- * subdentry/subinode
- * Is is vaild that there are inodes without dentries if they are
- * obsolete.
- */
-
-static void supermount_put_inode(struct inode *inode)
-{
-	if (atomic_read(&inode->i_count) == 1) {
-		struct dentry *dentry = supermount_i(inode)->i_dentry;
-		supermount_i(inode)->i_dentry = NULL;
-		if (dentry)
-			dentry_iput(dentry);
-		else if (!is_inode_obsolete(inode))
-			BUG();
-		inode->i_nlink = 0;
-	}
-}
-
 static struct super_operations supermount_sops = {
 	.write_inode	= supermount_write_inode,
 	.clear_inode	= supermount_clear_inode,
-	.put_inode	= supermount_put_inode,
 	.put_super	= supermount_put_super,
 	.write_super	= supermount_write_super,
 	.statfs		= supermount_statfs,
diff -ru -x '*.[oas]' -x '*.[oa].flags' -x .depend -x .config -x modversions.h -x '*.ver' -x autoconf.h /usr/src/linux-2.4.20-2mdk/fs/supermount/translation.c linux-2.4.20-2mdk/fs/supermount/translation.c
--- /usr/src/linux-2.4.20-2mdk/fs/supermount/translation.c	2002-12-09 14:38:17.000000000 +0300
+++ linux-2.4.20-2mdk/fs/supermount/translation.c	2002-12-31 14:15:44.000000000 +0300
@@ -128,7 +128,7 @@
 		BUG();
 
 	if (is_inode_obsolete(inode))
-		return ERR_PTR(-EINVAL);
+		return ERR_PTR(-ESTALE);
 
 	sbi = supermount_sbi(inode->i_sb);
 	if (!subfs_is_mounted(sbi))
diff -ru -x '*.[oas]' -x '*.[oa].flags' -x .depend -x .config -x modversions.h -x '*.ver' -x autoconf.h /usr/src/linux-2.4.20-2mdk/fs/udf/super.c linux-2.4.20-2mdk/fs/udf/super.c
--- /usr/src/linux-2.4.20-2mdk/fs/udf/super.c	2002-08-03 04:39:45.000000000 +0400
+++ linux-2.4.20-2mdk/fs/udf/super.c	2002-12-31 13:57:33.000000000 +0300
@@ -268,6 +268,11 @@
 			uopt->nls_map = load_nls(val);
 			uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
 		}
+#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
+		/* Silently ignore NLS option */
+		else if (!strcmp (opt, "codepage"))
+			/* Don't do anything ;-) */ ;
+#endif
 #endif
 		else if (!strcmp(opt, "utf8") && !val)
 			uopt->flags |= (1 << UDF_FLAG_UTF8);
diff -ru -x '*.[oas]' -x '*.[oa].flags' -x .depend -x .config -x modversions.h -x '*.ver' -x autoconf.h /usr/src/linux-2.4.20-2mdk/include/linux/fs.h linux-2.4.20-2mdk/include/linux/fs.h
--- /usr/src/linux-2.4.20-2mdk/include/linux/fs.h	2002-12-09 17:07:58.000000000 +0300
+++ linux-2.4.20-2mdk/include/linux/fs.h	2002-12-31 14:00:36.000000000 +0300
@@ -803,6 +803,15 @@
 	 * non-directories) are allowed, but not unconnected diretories.
 	 */
 	struct semaphore s_nfsd_free_path_sem;
+#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
+	/*
+	 * This one is for supermount. When somebody tries to access changed
+	 * media before supermount, media changed flag is lost (the most natural
+	 * example is eject -t). So we record this flag here. This flag is
+	 * implicitly reset when superblock is destroyed
+	 */
+	int s_media_changed;
+#endif
 };
 
 /*
