[PATCH] ramfs fixes

From: Alexander Viro (aviro@redhat.com)
Date: Sat Jun 17 2000 - 03:54:26 EDT

  • Next message: Rogier Wolff: "Re: Linux 2.2.17pre3"

            Contents:
    * adds a new method to address_space_operations: void detach_page(page).
      Meaning: do all work necessary to make page droppable. For block-based
      filesystems it's block_destroy_buffers(). For ramfs - ClearPageDirty().
      It is used by truncate_complete_page() and truncate_all_inode_pages() -
      i.e. whenever we are getting rid of a page due to truncate() or final
      iput() after unlink().
    * adds ->put_inode() to ramfs, making the final iput() drive i_nlink to zero
      and cause truncate_all_inode_pages() (on ramfs final iput() == deletion or
      death from umount).
    * adds a new flag - FS_LITTER, for filesystems that need d_genocide() upon
      ->put_super(). Unfortunately, doing that _from_ put_super() is impossible -
      by that time the root dentry is gone. And postponing the dput() of root
      dentry until the return from put_super() is not an option - by that time
      filesystem has every right to expect that everything is over. So we call
      d_genocide()/shrink_dcache_parent() from fs/super.c::kill_super() if fs
      type has FS_LITTER in the flags.
    * for filesystems mounted in the kernel space we did not release the dentry
      tree upon kern_umount(). Fixed (in kill_super()).

    AFAICS it fixes all problems with ramfs and closes a couple of leaks. BTW,
    I suspect that "Self-destruct in 5 seconds" bug report might be also fixed,
    but that's another story.

    Impact on filesystems: for block-based address_space you'll need to add
            detach_page: block_destroy_buffers,
    into struct address_space_operations. I've done that for all relevant ones
    in the tree.

    Alan, could you apply it?
                                                            Cheers,
                                                                    Al
    diff -urN linux-ac19/fs/adfs/inode.c linux-ac19-fixes0/fs/adfs/inode.c
    --- linux-ac19/fs/adfs/inode.c Fri Jun 16 21:47:04 2000
    +++ linux-ac19-fixes0/fs/adfs/inode.c Sat Jun 17 01:01:37 2000
    @@ -76,6 +76,7 @@
             sync_page: block_sync_page,
             prepare_write: adfs_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: _adfs_bmap
     };
     
    diff -urN linux-ac19/fs/affs/file.c linux-ac19-fixes0/fs/affs/file.c
    --- linux-ac19/fs/affs/file.c Mon May 8 16:51:01 2000
    +++ linux-ac19-fixes0/fs/affs/file.c Sat Jun 17 01:00:43 2000
    @@ -361,6 +361,7 @@
             sync_page: block_sync_page,
             prepare_write: affs_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: _affs_bmap
     };
     
    diff -urN linux-ac19/fs/bfs/file.c linux-ac19-fixes0/fs/bfs/file.c
    --- linux-ac19/fs/bfs/file.c Mon May 8 16:51:01 2000
    +++ linux-ac19-fixes0/fs/bfs/file.c Sat Jun 17 00:58:34 2000
    @@ -153,6 +153,7 @@
             sync_page: block_sync_page,
             prepare_write: bfs_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: bfs_bmap
     };
     
    diff -urN linux-ac19/fs/efs/inode.c linux-ac19-fixes0/fs/efs/inode.c
    --- linux-ac19/fs/efs/inode.c Mon May 8 14:11:29 2000
    +++ linux-ac19-fixes0/fs/efs/inode.c Sat Jun 17 01:02:15 2000
    @@ -22,6 +22,7 @@
     struct address_space_operations efs_aops = {
             readpage: efs_readpage,
             sync_page: block_sync_page,
    + detach_page: block_destroy_buffers,
             bmap: _efs_bmap
     };
     
    diff -urN linux-ac19/fs/ext2/inode.c linux-ac19-fixes0/fs/ext2/inode.c
    --- linux-ac19/fs/ext2/inode.c Fri Jun 16 21:47:04 2000
    +++ linux-ac19-fixes0/fs/ext2/inode.c Sat Jun 17 00:55:33 2000
    @@ -639,6 +639,7 @@
             sync_page: block_sync_page,
             prepare_write: ext2_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: ext2_bmap
     };
     
    diff -urN linux-ac19/fs/fat/inode.c linux-ac19-fixes0/fs/fat/inode.c
    --- linux-ac19/fs/fat/inode.c Fri Jun 16 21:47:04 2000
    +++ linux-ac19-fixes0/fs/fat/inode.c Sat Jun 17 00:59:59 2000
    @@ -752,6 +752,7 @@
             sync_page: block_sync_page,
             prepare_write: fat_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: _fat_bmap
     };
     
    diff -urN linux-ac19/fs/hfs/inode.c linux-ac19-fixes0/fs/hfs/inode.c
    --- linux-ac19/fs/hfs/inode.c Fri Jun 16 21:47:05 2000
    +++ linux-ac19-fixes0/fs/hfs/inode.c Sat Jun 17 01:01:24 2000
    @@ -240,6 +240,7 @@
             sync_page: block_sync_page,
             prepare_write: hfs_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: hfs_bmap
     };
     
    diff -urN linux-ac19/fs/hpfs/file.c linux-ac19-fixes0/fs/hpfs/file.c
    --- linux-ac19/fs/hpfs/file.c Fri Jun 16 21:47:05 2000
    +++ linux-ac19-fixes0/fs/hpfs/file.c Sat Jun 17 01:00:29 2000
    @@ -109,6 +109,7 @@
             sync_page: block_sync_page,
             prepare_write: hpfs_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: _hpfs_bmap
     };
     
    diff -urN linux-ac19/fs/isofs/inode.c linux-ac19-fixes0/fs/isofs/inode.c
    --- linux-ac19/fs/isofs/inode.c Mon May 8 14:11:29 2000
    +++ linux-ac19-fixes0/fs/isofs/inode.c Sat Jun 17 00:54:37 2000
    @@ -992,6 +992,7 @@
     static struct address_space_operations isofs_aops = {
             readpage: isofs_readpage,
             sync_page: block_sync_page,
    + detach_page: block_destroy_buffers,
             bmap: _isofs_bmap
     };
     
    diff -urN linux-ac19/fs/minix/inode.c linux-ac19-fixes0/fs/minix/inode.c
    --- linux-ac19/fs/minix/inode.c Fri Jun 16 21:47:05 2000
    +++ linux-ac19-fixes0/fs/minix/inode.c Sat Jun 17 00:53:57 2000
    @@ -1028,6 +1028,7 @@
             sync_page: block_sync_page,
             prepare_write: minix_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: minix_bmap
     };
     
    diff -urN linux-ac19/fs/ntfs/fs.c linux-ac19-fixes0/fs/ntfs/fs.c
    --- linux-ac19/fs/ntfs/fs.c Fri Jun 16 21:47:05 2000
    +++ linux-ac19-fixes0/fs/ntfs/fs.c Sat Jun 17 01:01:51 2000
    @@ -610,6 +610,7 @@
             sync_page: block_sync_page,
             prepare_write: ntfs_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: _ntfs_bmap
     };
     /* ntfs_read_inode is called by the Virtual File System (the kernel layer that
    diff -urN linux-ac19/fs/qnx4/inode.c linux-ac19-fixes0/fs/qnx4/inode.c
    --- linux-ac19/fs/qnx4/inode.c Fri Jun 16 21:47:05 2000
    +++ linux-ac19-fixes0/fs/qnx4/inode.c Sat Jun 17 00:58:08 2000
    @@ -432,6 +432,7 @@
             sync_page: block_sync_page,
             prepare_write: qnx4_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: qnx4_bmap
     };
     
    diff -urN linux-ac19/fs/ramfs/inode.c linux-ac19-fixes0/fs/ramfs/inode.c
    --- linux-ac19/fs/ramfs/inode.c Fri Jun 16 21:47:05 2000
    +++ linux-ac19-fixes0/fs/ramfs/inode.c Sat Jun 17 01:55:33 2000
    @@ -82,6 +82,11 @@
             return 0;
     }
     
    +static void ramfs_detach_page(struct page *page)
    +{
    + ClearPageDirty(page);
    +}
    +
     static int ramfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
     {
             void *addr;
    @@ -272,7 +277,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 +304,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 +331,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-fixes0/fs/super.c
    --- linux-ac19/fs/super.c Fri Jun 16 21:47:05 2000
    +++ linux-ac19-fixes0/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/fs/sysv/inode.c linux-ac19-fixes0/fs/sysv/inode.c
    --- linux-ac19/fs/sysv/inode.c Fri Jun 16 21:47:05 2000
    +++ linux-ac19-fixes0/fs/sysv/inode.c Sat Jun 17 00:59:45 2000
    @@ -961,6 +961,7 @@
             sync_page: block_sync_page,
             prepare_write: sysv_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: sysv_bmap
     };
     
    diff -urN linux-ac19/fs/udf/file.c linux-ac19-fixes0/fs/udf/file.c
    --- linux-ac19/fs/udf/file.c Mon May 8 16:51:01 2000
    +++ linux-ac19-fixes0/fs/udf/file.c Sat Jun 17 01:05:00 2000
    @@ -115,9 +115,11 @@
             return 0;
     }
     
    +/* FIXME: block_sync_page() is wrong here */
    +
     struct address_space_operations udf_adinicb_aops = {
    - readpage: udf_adinicb_readpage,
    - writepage: udf_adinicb_writepage,
    + readpage: udf_adinicb_readpage,
    + writepage: udf_adinicb_writepage,
             sync_page: block_sync_page,
             prepare_write: udf_adinicb_prepare_write,
             commit_write: udf_adinicb_commit_write,
    diff -urN linux-ac19/fs/udf/inode.c linux-ac19-fixes0/fs/udf/inode.c
    --- linux-ac19/fs/udf/inode.c Fri Jun 16 21:47:05 2000
    +++ linux-ac19-fixes0/fs/udf/inode.c Sat Jun 17 01:03:06 2000
    @@ -146,12 +146,13 @@
     }
     
     struct address_space_operations udf_aops = {
    - readpage: udf_readpage,
    - writepage: udf_writepage,
    + readpage: udf_readpage,
    + writepage: udf_writepage,
             sync_page: block_sync_page,
             prepare_write: udf_prepare_write,
             commit_write: generic_commit_write,
    - bmap: udf_bmap,
    + detach_page: block_destroy_buffers,
    + bmap: udf_bmap,
     };
     
     void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
    diff -urN linux-ac19/fs/ufs/inode.c linux-ac19-fixes0/fs/ufs/inode.c
    --- linux-ac19/fs/ufs/inode.c Fri Jun 16 21:47:05 2000
    +++ linux-ac19-fixes0/fs/ufs/inode.c Sat Jun 17 01:00:16 2000
    @@ -562,6 +562,7 @@
             sync_page: block_sync_page,
             prepare_write: ufs_prepare_write,
             commit_write: generic_commit_write,
    + detach_page: block_destroy_buffers,
             bmap: ufs_bmap
     };
     
    diff -urN linux-ac19/include/linux/fs.h linux-ac19-fixes0/include/linux/fs.h
    --- linux-ac19/include/linux/fs.h Fri Jun 16 21:47:06 2000
    +++ linux-ac19-fixes0/include/linux/fs.h Sat Jun 17 01:55:12 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);
    + void (*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-fixes0/kernel/ksyms.c
    --- linux-ac19/kernel/ksyms.c Fri Jun 16 21:47:07 2000
    +++ linux-ac19-fixes0/kernel/ksyms.c Sat Jun 17 01:08:32 2000
    @@ -198,6 +198,7 @@
     EXPORT_SYMBOL(block_read_full_page);
     EXPORT_SYMBOL(block_prepare_write);
     EXPORT_SYMBOL(block_sync_page);
    +EXPORT_SYMBOL(block_destroy_buffers);
     EXPORT_SYMBOL(cont_prepare_write);
     EXPORT_SYMBOL(generic_commit_write);
     EXPORT_SYMBOL(generic_block_bmap);
    @@ -217,7 +218,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-fixes0/mm/filemap.c
    --- linux-ac19/mm/filemap.c Fri Jun 16 21:47:07 2000
    +++ linux-ac19-fixes0/mm/filemap.c Sat Jun 17 01:09:33 2000
    @@ -164,8 +164,8 @@
     
     static inline void truncate_complete_page(struct page *page)
     {
    - 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);
             
             /*
    @@ -272,11 +272,11 @@
                             page_cache_release(page);
                             goto repeat;
                     }
    - if (page->buffers) {
    + if (mapping->a_ops->detach_page) {
                             page_cache_get(page);
                             spin_unlock(&pagemap_lru_lock);
                             spin_unlock(&pagecache_lock);
    - block_destroy_buffers(page);
    + mapping->a_ops->detach_page(page);
                             remove_inode_page(page);
                             lru_cache_del(page);
                             page_cache_release(page);
    diff -urN linux-ac19/mm/swap_state.c linux-ac19-fixes0/mm/swap_state.c
    --- linux-ac19/mm/swap_state.c Fri Jun 16 21:47:07 2000
    +++ linux-ac19-fixes0/mm/swap_state.c Sat Jun 17 01:53:02 2000
    @@ -18,7 +18,8 @@
     #include <asm/pgtable.h>
     
     static struct address_space_operations swap_aops = {
    - sync_page: block_sync_page
    + sync_page: block_sync_page,
    + detach_page: block_destroy_buffers,
     };
     
     struct address_space swapper_space = {

    -
    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 : Sat Jun 17 2000 - 03:56:17 EDT