OK, how about the following? It seems to fix all problems.
Alan, I think that ->detach_page() thing (do whatever we need to make the
page droppable: ClearPageDirty() in case of ramfs) makes sense and for
block-based filesystems we simply should make ->detach_page ==
block_destroy_buffers. Comments?
diff -urN linux-ac19/fs/ramfs/inode.c linux-ac19-fixes/fs/ramfs/inode.c
--- linux-ac19/fs/ramfs/inode.c Fri Jun 16 21:47:05 2000
+++ linux-ac19-fixes/fs/ramfs/inode.c Fri Jun 16 21:29:57 2000
@@ -82,6 +82,12 @@
return 0;
}
+static int ramfs_detach_page(struct page *page)
+{
+ ClearPageDirty(page);
+ return 0;
+}
+
static int ramfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
void *addr;
@@ -272,7 +278,8 @@
readpage: ramfs_readpage,
writepage: ramfs_writepage,
prepare_write: ramfs_prepare_write,
- commit_write: ramfs_commit_write
+ commit_write: ramfs_commit_write,
+ detach_page: ramfs_detach_page,
};
static struct file_operations ramfs_file_operations = {
@@ -298,15 +305,9 @@
rename: ramfs_rename,
};
-static void ramfs_put_super(struct super_block *sb)
-{
- d_genocide(sb->s_root);
- shrink_dcache_parent(sb->s_root);
-}
-
static struct super_operations ramfs_ops = {
- put_super: ramfs_put_super,
statfs: ramfs_statfs,
+ put_inode: force_delete,
};
static struct super_block *ramfs_read_super(struct super_block * sb, void * data, int silent)
@@ -331,7 +332,7 @@
return sb;
}
-static DECLARE_FSTYPE(ramfs_fs_type, "ramfs", ramfs_read_super, 0);
+static DECLARE_FSTYPE(ramfs_fs_type, "ramfs", ramfs_read_super, FS_LITTER);
static int __init init_ramfs_fs(void)
{
diff -urN linux-ac19/fs/super.c linux-ac19-fixes/fs/super.c
--- linux-ac19/fs/super.c Fri Jun 16 21:47:05 2000
+++ linux-ac19-fixes/fs/super.c Fri Jun 16 20:22:25 2000
@@ -824,8 +824,14 @@
{
struct block_device *bdev;
kdev_t dev;
- dput(sb->s_root);
+ struct dentry *root = sb->s_root;
sb->s_root = NULL;
+ /* Need to clean after the sucker */
+ if (sb->s_type->fs_flags & FS_LITTER)
+ d_genocide(root);
+ if (sb->s_type->fs_flags & (FS_SINGLE|FS_LITTER))
+ shrink_dcache_parent(root);
+ dput(root);
lock_super(sb);
if (sb->s_op) {
if (sb->s_op->write_super && sb->s_dirt)
diff -urN linux-ac19/include/linux/fs.h linux-ac19-fixes/include/linux/fs.h
--- linux-ac19/include/linux/fs.h Fri Jun 16 21:47:06 2000
+++ linux-ac19-fixes/include/linux/fs.h Fri Jun 16 20:59:49 2000
@@ -89,6 +89,7 @@
* kernel-wide vfsmnt is kept in ->kern_mnt.
*/
#define FS_NOMOUNT 16 /* Never mount from userland */
+#define FS_LITTER 32 /* Keeps the tree in dcache */
/*
* These are the fs-independent mount-flags: up to 16 flags are supported
*/
@@ -355,6 +356,7 @@
int (*sync_page)(struct page *);
int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
+ int (*detach_page)(struct page *);
/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
int (*bmap)(struct address_space *, long);
};
diff -urN linux-ac19/kernel/ksyms.c linux-ac19-fixes/kernel/ksyms.c
--- linux-ac19/kernel/ksyms.c Fri Jun 16 21:47:07 2000
+++ linux-ac19-fixes/kernel/ksyms.c Fri Jun 16 20:22:25 2000
@@ -217,7 +217,6 @@
EXPORT_SYMBOL(locks_mandatory_area);
EXPORT_SYMBOL(dput);
EXPORT_SYMBOL(have_submounts);
-EXPORT_SYMBOL(d_genocide);
EXPORT_SYMBOL(d_find_alias);
EXPORT_SYMBOL(d_prune_aliases);
EXPORT_SYMBOL(prune_dcache);
diff -urN linux-ac19/mm/filemap.c linux-ac19-fixes/mm/filemap.c
--- linux-ac19/mm/filemap.c Fri Jun 16 21:47:07 2000
+++ linux-ac19-fixes/mm/filemap.c Fri Jun 16 21:09:34 2000
@@ -166,6 +166,8 @@
{
if (page->buffers)
block_destroy_buffers(page);
+ if (page->mapping->a_ops->detach_page)
+ page->mapping->a_ops->detach_page(page);
lru_cache_del(page);
/*
@@ -277,6 +279,18 @@
spin_unlock(&pagemap_lru_lock);
spin_unlock(&pagecache_lock);
block_destroy_buffers(page);
+ remove_inode_page(page);
+ lru_cache_del(page);
+ page_cache_release(page);
+ UnlockPage(page);
+ page_cache_release(page);
+ goto repeat;
+ }
+ if (page->mapping->a_ops->detach_page) {
+ page_cache_get(page);
+ spin_unlock(&pagemap_lru_lock);
+ spin_unlock(&pagecache_lock);
+ page->mapping->a_ops->detach_page(page);
remove_inode_page(page);
lru_cache_del(page);
page_cache_release(page);
-
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/
This archive was generated by hypermail 2b29 : Fri Jun 23 2000 - 21:00:13 EST