From 8c85e125124a473d6f3e9bb187b0b84207f81d91 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 28 Apr 2009 18:00:26 +0200 Subject: remove ->write_super call in generic_shutdown_super We just did a full fs writeout using sync_filesystem before, and if that's not enough for the filesystem it can perform it's own writeout in ->put_super, which many filesystems already do. Move a call to foofs_write_super into every foofs_put_super for now to guarantee identical behaviour until it's cleaned up by the individual filesystem maintainers. Exceptions: - affs already has identical copy & pasted code at the beginning of affs_put_super so no need to do it twice. - xfs does the right thing without it and I have changes pending for the xfs tree touching this are so I don't really need conflicts here.. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/bfs/inode.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs/bfs/inode.c') diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index cc4062d12ca2..4cf3d269e271 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -30,6 +30,7 @@ MODULE_LICENSE("GPL"); #define dprintf(x...) #endif +static void bfs_write_super(struct super_block *s); void dump_imap(const char *prefix, struct super_block *s); struct inode *bfs_iget(struct super_block *sb, unsigned long ino) @@ -216,6 +217,9 @@ static void bfs_put_super(struct super_block *s) if (!info) return; + if (s->s_dirt) + bfs_write_super(s); + brelse(info->si_sbh); mutex_destroy(&info->bfs_lock); kfree(info->si_imap); -- cgit v1.2.3 From 6cfd0148425e528b859b26e436b01f23f6926224 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 5 May 2009 15:40:36 +0200 Subject: push BKL down into ->put_super Move BKL into ->put_super from the only caller. A couple of filesystems had trivial enough ->put_super (only kfree and NULLing of s_fs_info + stuff in there) to not get any locking: coda, cramfs, efs, hugetlbfs, omfs, qnx4, shmem, all others got the full treatment. Most of them probably don't need it, but I'd rather sort that out individually. Preferably after all the other BKL pushdowns in that area. [AV: original used to move lock_super() down as well; these changes are removed since we don't do lock_super() at all in generic_shutdown_super() now] [AV: fuse, btrfs and xfs are known to need no damn BKL, exempt] Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/adfs/super.c | 4 ++++ fs/affs/super.c | 5 ++++- fs/afs/super.c | 4 ++++ fs/befs/linuxvfs.c | 5 ++++- fs/bfs/inode.c | 4 ++++ fs/cifs/cifsfs.c | 6 +++++- fs/ecryptfs/super.c | 5 +++++ fs/exofs/super.c | 4 ++++ fs/ext2/super.c | 4 +++- fs/ext3/super.c | 5 ++++- fs/ext4/super.c | 2 +- fs/fat/inode.c | 4 ++++ fs/freevxfs/vxfs_super.c | 4 ++++ fs/gfs2/super.c | 4 ++++ fs/hfs/super.c | 4 ++++ fs/hfsplus/super.c | 5 +++++ fs/hpfs/super.c | 5 +++++ fs/isofs/inode.c | 5 +++++ fs/jffs2/super.c | 4 ++++ fs/jfs/super.c | 5 +++++ fs/minix/inode.c | 4 +++- fs/ncpfs/inode.c | 4 ++++ fs/nilfs2/super.c | 4 ++++ fs/ntfs/super.c | 6 +++++- fs/ocfs2/super.c | 4 ++++ fs/reiserfs/super.c | 4 +++- fs/smbfs/inode.c | 4 ++++ fs/squashfs/super.c | 4 ++++ fs/super.c | 3 --- fs/sysv/inode.c | 4 ++++ fs/ubifs/super.c | 5 +++++ fs/udf/super.c | 5 +++++ fs/ufs/super.c | 6 ++++++ 33 files changed, 133 insertions(+), 12 deletions(-) (limited to 'fs/bfs/inode.c') diff --git a/fs/adfs/super.c b/fs/adfs/super.c index dd9becca4241..0ec5aaf47aa7 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -132,11 +132,15 @@ static void adfs_put_super(struct super_block *sb) int i; struct adfs_sb_info *asb = ADFS_SB(sb); + lock_kernel(); + for (i = 0; i < asb->s_map_size; i++) brelse(asb->s_map[i].dm_bh); kfree(asb->s_map); kfree(asb); sb->s_fs_info = NULL; + + unlock_kernel(); } static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt) diff --git a/fs/affs/super.c b/fs/affs/super.c index 63f5183f263b..d7386462a8e7 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -29,6 +29,8 @@ affs_put_super(struct super_block *sb) struct affs_sb_info *sbi = AFFS_SB(sb); pr_debug("AFFS: put_super()\n"); + lock_kernel(); + if (!(sb->s_flags & MS_RDONLY)) { AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = cpu_to_be32(1); secs_to_datestamp(get_seconds(), @@ -42,7 +44,8 @@ affs_put_super(struct super_block *sb) affs_brelse(sbi->s_root_bh); kfree(sbi); sb->s_fs_info = NULL; - return; + + unlock_kernel(); } static void diff --git a/fs/afs/super.c b/fs/afs/super.c index 76828e5f8a39..ad0514d0115f 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -440,8 +440,12 @@ static void afs_put_super(struct super_block *sb) _enter(""); + lock_kernel(); + afs_put_volume(as->volume); + unlock_kernel(); + _leave(""); } diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 76afd0d6b86c..9367b6297d84 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -737,6 +737,8 @@ parse_options(char *options, befs_mount_options * opts) static void befs_put_super(struct super_block *sb) { + lock_kernel(); + kfree(BEFS_SB(sb)->mount_opts.iocharset); BEFS_SB(sb)->mount_opts.iocharset = NULL; @@ -747,7 +749,8 @@ befs_put_super(struct super_block *sb) kfree(sb->s_fs_info); sb->s_fs_info = NULL; - return; + + unlock_kernel(); } /* Allocate private field of the superblock, fill it. diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 4cf3d269e271..3a9a1361fdc1 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -217,6 +217,8 @@ static void bfs_put_super(struct super_block *s) if (!info) return; + lock_kernel(); + if (s->s_dirt) bfs_write_super(s); @@ -225,6 +227,8 @@ static void bfs_put_super(struct super_block *s) kfree(info->si_imap); kfree(info); s->s_fs_info = NULL; + + unlock_kernel(); } static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 0a10a59b6392..0d92114195ab 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -204,6 +204,9 @@ cifs_put_super(struct super_block *sb) cFYI(1, ("Empty cifs superblock info passed to unmount")); return; } + + lock_kernel(); + rc = cifs_umount(sb, cifs_sb); if (rc) cERROR(1, ("cifs_umount failed with return code %d", rc)); @@ -216,7 +219,8 @@ cifs_put_super(struct super_block *sb) unload_nls(cifs_sb->local_nls); kfree(cifs_sb); - return; + + unlock_kernel(); } static int diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index fa4c7e7d15d9..12d649602d3a 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include "ecryptfs_kernel.h" @@ -120,9 +121,13 @@ static void ecryptfs_put_super(struct super_block *sb) { struct ecryptfs_sb_info *sb_info = ecryptfs_superblock_to_private(sb); + lock_kernel(); + ecryptfs_destroy_mount_crypt_stat(&sb_info->mount_crypt_stat); kmem_cache_free(ecryptfs_sb_info_cache, sb_info); ecryptfs_set_superblock_private(sb, NULL); + + unlock_kernel(); } /** diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 3cdb761db8ad..cd1f8b18a218 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -258,6 +258,8 @@ static void exofs_put_super(struct super_block *sb) int num_pend; struct exofs_sb_info *sbi = sb->s_fs_info; + lock_kernel(); + if (sb->s_dirt) exofs_write_super(sb); @@ -274,6 +276,8 @@ static void exofs_put_super(struct super_block *sb) osduld_put_device(sbi->s_dev); kfree(sb->s_fs_info); sb->s_fs_info = NULL; + + unlock_kernel(); } /* diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 932a2bcb6908..a44963d8edbd 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -114,6 +114,8 @@ static void ext2_put_super (struct super_block * sb) int i; struct ext2_sb_info *sbi = EXT2_SB(sb); + lock_kernel(); + if (sb->s_dirt) ext2_write_super(sb); @@ -138,7 +140,7 @@ static void ext2_put_super (struct super_block * sb) kfree(sbi->s_blockgroup_lock); kfree(sbi); - return; + unlock_kernel(); } static struct kmem_cache * ext2_inode_cachep; diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 1efd958687e9..546b8d732bf2 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -398,6 +398,8 @@ static void ext3_put_super (struct super_block * sb) struct ext3_super_block *es = sbi->s_es; int i, err; + lock_kernel(); + ext3_xattr_put_super(sb); err = journal_destroy(sbi->s_journal); sbi->s_journal = NULL; @@ -446,7 +448,8 @@ static void ext3_put_super (struct super_block * sb) sb->s_fs_info = NULL; kfree(sbi->s_blockgroup_lock); kfree(sbi); - return; + + unlock_kernel(); } static struct kmem_cache *ext3_inode_cachep; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0d3034c5e8a4..1d4180b86772 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -577,6 +577,7 @@ static void ext4_put_super(struct super_block *sb) int i, err; lock_super(sb); + lock_kernel(); if (sb->s_dirt) ext4_write_super(sb); @@ -646,7 +647,6 @@ static void ext4_put_super(struct super_block *sb) unlock_super(sb); kobject_put(&sbi->s_kobj); wait_for_completion(&sbi->s_kobj_unregister); - lock_kernel(); kfree(sbi->s_blockgroup_lock); kfree(sbi); } diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 4978621511bf..2b88c93af227 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -451,6 +451,8 @@ static void fat_put_super(struct super_block *sb) { struct msdos_sb_info *sbi = MSDOS_SB(sb); + lock_kernel(); + if (sb->s_dirt) fat_write_super(sb); @@ -470,6 +472,8 @@ static void fat_put_super(struct super_block *sb) sb->s_fs_info = NULL; kfree(sbi); + + unlock_kernel(); } static struct kmem_cache *fat_inode_cachep; diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index 1dacda831577..cdbd1654e4cd 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -80,12 +80,16 @@ vxfs_put_super(struct super_block *sbp) { struct vxfs_sb_info *infp = VXFS_SBI(sbp); + lock_kernel(); + vxfs_put_fake_inode(infp->vsi_fship); vxfs_put_fake_inode(infp->vsi_ilist); vxfs_put_fake_inode(infp->vsi_stilist); brelse(infp->vsi_bp); kfree(infp); + + unlock_kernel(); } /** diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0a6801336470..c8930b31cdf0 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -719,6 +719,8 @@ static void gfs2_put_super(struct super_block *sb) int error; struct gfs2_jdesc *jd; + lock_kernel(); + /* Unfreeze the filesystem, if we need to */ mutex_lock(&sdp->sd_freeze_lock); @@ -785,6 +787,8 @@ restart: /* At this point, we're through participating in the lockspace */ gfs2_sys_fs_del(sdp); + + unlock_kernel(); } /** diff --git a/fs/hfs/super.c b/fs/hfs/super.c index e071e6d06463..9f5eaa01cc77 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -65,11 +65,15 @@ static void hfs_write_super(struct super_block *sb) */ static void hfs_put_super(struct super_block *sb) { + lock_kernel(); + if (sb->s_dirt) hfs_write_super(sb); hfs_mdb_close(sb); /* release the MDB's resources */ hfs_mdb_put(sb); + + unlock_kernel(); } /* diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 40bdab79dae8..9b292dcc39c8 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -199,6 +199,9 @@ static void hfsplus_put_super(struct super_block *sb) dprint(DBG_SUPER, "hfsplus_put_super\n"); if (!sb->s_fs_info) return; + + lock_kernel(); + if (sb->s_dirt) hfsplus_write_super(sb); if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) { @@ -220,6 +223,8 @@ static void hfsplus_put_super(struct super_block *sb) unload_nls(HFSPLUS_SB(sb).nls); kfree(sb->s_fs_info); sb->s_fs_info = NULL; + + unlock_kernel(); } static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index fc77965be841..437a32e9deac 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -99,11 +99,16 @@ int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2, static void hpfs_put_super(struct super_block *s) { struct hpfs_sb_info *sbi = hpfs_sb(s); + + lock_kernel(); + kfree(sbi->sb_cp_table); kfree(sbi->sb_bmp_dir); unmark_dirty(s); s->s_fs_info = NULL; kfree(sbi); + + unlock_kernel(); } unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno) diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index b4cbe9603c7d..068b34b5a107 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -42,11 +42,16 @@ static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qst static void isofs_put_super(struct super_block *sb) { struct isofs_sb_info *sbi = ISOFS_SB(sb); + #ifdef CONFIG_JOLIET + lock_kernel(); + if (sbi->s_nls_iocharset) { unload_nls(sbi->s_nls_iocharset); sbi->s_nls_iocharset = NULL; } + + unlock_kernel(); #endif kfree(sbi); diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 5059e9633edb..37b12125c127 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -174,6 +174,8 @@ static void jffs2_put_super (struct super_block *sb) D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n")); + lock_kernel(); + if (sb->s_dirt) jffs2_write_super(sb); @@ -195,6 +197,8 @@ static void jffs2_put_super (struct super_block *sb) if (c->mtd->sync) c->mtd->sync(c->mtd); + unlock_kernel(); + D1(printk(KERN_DEBUG "jffs2_put_super returning\n")); } diff --git a/fs/jfs/super.c b/fs/jfs/super.c index d9b0e92b3602..3eb13adf3862 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -183,6 +183,9 @@ static void jfs_put_super(struct super_block *sb) int rc; jfs_info("In jfs_put_super"); + + lock_kernel(); + rc = jfs_umount(sb); if (rc) jfs_err("jfs_umount failed with return code %d", rc); @@ -195,6 +198,8 @@ static void jfs_put_super(struct super_block *sb) sbi->direct_inode = NULL; kfree(sbi); + + unlock_kernel(); } enum { diff --git a/fs/minix/inode.c b/fs/minix/inode.c index daad3c2740db..7eb53970f4bc 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -35,6 +35,8 @@ static void minix_put_super(struct super_block *sb) int i; struct minix_sb_info *sbi = minix_sb(sb); + lock_kernel(); + if (!(sb->s_flags & MS_RDONLY)) { if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ sbi->s_ms->s_state = sbi->s_mount_state; @@ -49,7 +51,7 @@ static void minix_put_super(struct super_block *sb) sb->s_fs_info = NULL; kfree(sbi); - return; + unlock_kernel(); } static struct kmem_cache * minix_inode_cachep; diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index d642f0e5b365..b99ce205b1bd 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -736,6 +736,8 @@ static void ncp_put_super(struct super_block *sb) { struct ncp_server *server = NCP_SBP(sb); + lock_kernel(); + ncp_lock_server(server); ncp_disconnect(server); ncp_unlock_server(server); @@ -769,6 +771,8 @@ static void ncp_put_super(struct super_block *sb) vfree(server->packet); sb->s_fs_info = NULL; kfree(server); + + unlock_kernel(); } static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 7901d8cbb9b1..7262e8427c20 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -316,6 +316,8 @@ static void nilfs_put_super(struct super_block *sb) struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sbi->s_nilfs; + lock_kernel(); + if (sb->s_dirt) nilfs_write_super(sb); @@ -333,6 +335,8 @@ static void nilfs_put_super(struct super_block *sb) sbi->s_super = NULL; sb->s_fs_info = NULL; kfree(sbi); + + unlock_kernel(); } /** diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 6aa7c4713536..a9ec4e1084e4 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -2246,6 +2246,9 @@ static void ntfs_put_super(struct super_block *sb) ntfs_volume *vol = NTFS_SB(sb); ntfs_debug("Entering."); + + lock_kernel(); + #ifdef NTFS_RW /* * Commit all inodes while they are still open in case some of them @@ -2444,7 +2447,8 @@ static void ntfs_put_super(struct super_block *sb) } sb->s_fs_info = NULL; kfree(vol); - return; + + unlock_kernel(); } /** diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 3eb076ce4c07..02737596b597 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1536,9 +1536,13 @@ static void ocfs2_put_super(struct super_block *sb) { mlog_entry("(0x%p)\n", sb); + lock_kernel(); + ocfs2_sync_blockdev(sb); ocfs2_dismount_volume(sb, 0); + unlock_kernel(); + mlog_exit_void(); } diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 3da0401c0a96..90dcb7b033ea 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -465,6 +465,8 @@ static void reiserfs_put_super(struct super_block *s) struct reiserfs_transaction_handle th; th.t_trans_id = 0; + lock_kernel(); + if (s->s_dirt) reiserfs_write_super(s); @@ -500,7 +502,7 @@ static void reiserfs_put_super(struct super_block *s) kfree(s->s_fs_info); s->s_fs_info = NULL; - return; + unlock_kernel(); } static struct kmem_cache *reiserfs_inode_cachep; diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index fc27fbfc5397..1402d2d54f52 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -474,6 +474,8 @@ smb_put_super(struct super_block *sb) { struct smb_sb_info *server = SMB_SB(sb); + lock_kernel(); + smb_lock_server(server); server->state = CONN_INVALID; smbiod_unregister_server(server); @@ -489,6 +491,8 @@ smb_put_super(struct super_block *sb) smb_unlock_server(server); put_pid(server->conn_pid); kfree(server); + + unlock_kernel(); } static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 0adc624c956f..3b52770f46ff 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -338,6 +338,8 @@ static int squashfs_remount(struct super_block *sb, int *flags, char *data) static void squashfs_put_super(struct super_block *sb) { + lock_kernel(); + if (sb->s_fs_info) { struct squashfs_sb_info *sbi = sb->s_fs_info; squashfs_cache_delete(sbi->block_cache); @@ -350,6 +352,8 @@ static void squashfs_put_super(struct super_block *sb) kfree(sb->s_fs_info); sb->s_fs_info = NULL; } + + unlock_kernel(); } diff --git a/fs/super.c b/fs/super.c index 54fd331f0cab..bdd7158b785e 100644 --- a/fs/super.c +++ b/fs/super.c @@ -309,7 +309,6 @@ void generic_shutdown_super(struct super_block *sb) /* bad name - it should be evict_inodes() */ invalidate_inodes(sb); - lock_kernel(); if (sop->put_super) sop->put_super(sb); @@ -320,8 +319,6 @@ void generic_shutdown_super(struct super_block *sb) "Self-destruct in 5 seconds. Have a nice day...\n", sb->s_id); } - - unlock_kernel(); put_fs_excl(); } spin_lock(&sb_lock); diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index cd80316302cc..a8189864c241 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -72,6 +72,8 @@ static void sysv_put_super(struct super_block *sb) { struct sysv_sb_info *sbi = SYSV_SB(sb); + lock_kernel(); + if (sb->s_dirt) sysv_write_super(sb); @@ -87,6 +89,8 @@ static void sysv_put_super(struct super_block *sb) brelse(sbi->s_bh2); kfree(sbi); + + unlock_kernel(); } static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 84f3c7fd1552..522c3fd7eb3c 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1684,6 +1684,9 @@ static void ubifs_put_super(struct super_block *sb) ubifs_msg("un-mount UBI device %d, volume %d", c->vi.ubi_num, c->vi.vol_id); + + lock_kernel(); + /* * The following asserts are only valid if there has not been a failure * of the media. For example, there will be dirty inodes if we failed @@ -1750,6 +1753,8 @@ static void ubifs_put_super(struct super_block *sb) ubi_close_volume(c->ubi); mutex_unlock(&c->umount_mutex); kfree(c); + + unlock_kernel(); } static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) diff --git a/fs/udf/super.c b/fs/udf/super.c index 0ba44107d8f1..04802cc39b18 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -2062,6 +2062,9 @@ static void udf_put_super(struct super_block *sb) struct udf_sb_info *sbi; sbi = UDF_SB(sb); + + lock_kernel(); + if (sbi->s_vat_inode) iput(sbi->s_vat_inode); if (sbi->s_partitions) @@ -2077,6 +2080,8 @@ static void udf_put_super(struct super_block *sb) kfree(sbi->s_partmaps); kfree(sb->s_fs_info); sb->s_fs_info = NULL; + + unlock_kernel(); } static int udf_sync_fs(struct super_block *sb, int wait) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 74afb9fbf58e..2b4d2b6234df 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -594,6 +594,9 @@ static void ufs_put_super_internal(struct super_block *sb) UFSD("ENTER\n"); + + lock_kernel(); + ufs_put_cstotal(sb); size = uspi->s_cssize; blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; @@ -621,6 +624,9 @@ static void ufs_put_super_internal(struct super_block *sb) brelse (sbi->s_ucg[i]); kfree (sbi->s_ucg); kfree (base); + + unlock_kernel(); + UFSD("EXIT\n"); } -- cgit v1.2.3 From 4427f0c36e22e2cd6696b2fe7643e9756a14b3d3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 8 Jun 2009 01:15:58 -0400 Subject: repair bfs_write_inode(), switch bfs to simple_fsync() Signed-off-by: Al Viro --- fs/bfs/dir.c | 8 ++++---- fs/bfs/inode.c | 12 +++++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'fs/bfs/inode.c') diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 4dd1b623f937..54bd07d44e68 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -79,7 +79,7 @@ static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir) const struct file_operations bfs_dir_operations = { .read = generic_read_dir, .readdir = bfs_readdir, - .fsync = file_fsync, + .fsync = simple_fsync, .llseek = generic_file_llseek, }; @@ -205,7 +205,7 @@ static int bfs_unlink(struct inode *dir, struct dentry *dentry) inode->i_nlink = 1; } de->ino = 0; - mark_buffer_dirty(bh); + mark_buffer_dirty_inode(bh, dir); dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; mark_inode_dirty(dir); inode->i_ctime = dir->i_ctime; @@ -267,7 +267,7 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry, new_inode->i_ctime = CURRENT_TIME_SEC; inode_dec_link_count(new_inode); } - mark_buffer_dirty(old_bh); + mark_buffer_dirty_inode(old_bh, old_dir); error = 0; end_rename: @@ -320,7 +320,7 @@ static int bfs_add_entry(struct inode *dir, const unsigned char *name, for (i = 0; i < BFS_NAMELEN; i++) de->name[i] = (i < namelen) ? name[i] : 0; - mark_buffer_dirty(bh); + mark_buffer_dirty_inode(bh, dir); brelse(bh); return 0; } diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 3a9a1361fdc1..d1d9d9088371 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -98,14 +98,15 @@ error: return ERR_PTR(-EIO); } -static int bfs_write_inode(struct inode *inode, int unused) +static int bfs_write_inode(struct inode *inode, int wait) { + struct bfs_sb_info *info = BFS_SB(inode->i_sb); unsigned int ino = (u16)inode->i_ino; unsigned long i_sblock; struct bfs_inode *di; struct buffer_head *bh; int block, off; - struct bfs_sb_info *info = BFS_SB(inode->i_sb); + int err = 0; dprintf("ino=%08x\n", ino); @@ -146,9 +147,14 @@ static int bfs_write_inode(struct inode *inode, int unused) di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1); mark_buffer_dirty(bh); + if (wait) { + sync_dirty_buffer(bh); + if (buffer_req(bh) && !buffer_uptodate(bh)) + err = -EIO; + } brelse(bh); mutex_unlock(&info->bfs_lock); - return 0; + return err; } static void bfs_delete_inode(struct inode *inode) -- cgit v1.2.3 From 561e47ce7244168788d4ecef9a2271df204b3c89 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 8 Jun 2009 10:03:38 +0200 Subject: bfs: add ->sync_fs Add a ->sync_fs method for data integrity syncs, and reimplement ->write_super ontop of it. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/bfs/inode.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'fs/bfs/inode.c') diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index d1d9d9088371..6f60336c6628 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -216,6 +216,26 @@ static void bfs_delete_inode(struct inode *inode) clear_inode(inode); } +static int bfs_sync_fs(struct super_block *sb, int wait) +{ + struct bfs_sb_info *info = BFS_SB(sb); + + mutex_lock(&info->bfs_lock); + mark_buffer_dirty(info->si_sbh); + sb->s_dirt = 0; + mutex_unlock(&info->bfs_lock); + + return 0; +} + +static void bfs_write_super(struct super_block *sb) +{ + if (!(sb->s_flags & MS_RDONLY)) + bfs_sync_fs(sb, 1); + else + sb->s_dirt = 0; +} + static void bfs_put_super(struct super_block *s) { struct bfs_sb_info *info = BFS_SB(s); @@ -254,17 +274,6 @@ static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf) return 0; } -static void bfs_write_super(struct super_block *s) -{ - struct bfs_sb_info *info = BFS_SB(s); - - mutex_lock(&info->bfs_lock); - if (!(s->s_flags & MS_RDONLY)) - mark_buffer_dirty(info->si_sbh); - s->s_dirt = 0; - mutex_unlock(&info->bfs_lock); -} - static struct kmem_cache *bfs_inode_cachep; static struct inode *bfs_alloc_inode(struct super_block *sb) @@ -312,6 +321,7 @@ static const struct super_operations bfs_sops = { .delete_inode = bfs_delete_inode, .put_super = bfs_put_super, .write_super = bfs_write_super, + .sync_fs = bfs_sync_fs, .statfs = bfs_statfs, }; -- cgit v1.2.3