diff options
Diffstat (limited to 'fs/bfs/inode.c')
-rw-r--r-- | fs/bfs/inode.c | 126 |
1 files changed, 42 insertions, 84 deletions
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 8f3d9fd8960..883e77acd5a 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -12,9 +12,9 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/fs.h> -#include <linux/smp_lock.h> #include <linux/buffer_head.h> #include <linux/vfs.h> +#include <linux/writeback.h> #include <asm/uaccess.h> #include "bfs.h" @@ -30,7 +30,6 @@ 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) @@ -98,35 +97,40 @@ error: return ERR_PTR(-EIO); } -static int bfs_write_inode(struct inode *inode, int wait) +static struct bfs_inode *find_inode(struct super_block *sb, u16 ino, struct buffer_head **p) +{ + if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(sb)->si_lasti)) { + printf("Bad inode number %s:%08x\n", sb->s_id, ino); + return ERR_PTR(-EIO); + } + + ino -= BFS_ROOT_INO; + + *p = sb_bread(sb, 1 + ino / BFS_INODES_PER_BLOCK); + if (!*p) { + printf("Unable to read inode %s:%08x\n", sb->s_id, ino); + return ERR_PTR(-EIO); + } + + return (struct bfs_inode *)(*p)->b_data + ino % BFS_INODES_PER_BLOCK; +} + +static int bfs_write_inode(struct inode *inode, struct writeback_control *wbc) { 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; int err = 0; dprintf("ino=%08x\n", ino); - if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) { - printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino); - return -EIO; - } + di = find_inode(inode->i_sb, ino, &bh); + if (IS_ERR(di)) + return PTR_ERR(di); mutex_lock(&info->bfs_lock); - block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; - bh = sb_bread(inode->i_sb, block); - if (!bh) { - printf("Unable to read inode %s:%08x\n", - inode->i_sb->s_id, ino); - mutex_unlock(&info->bfs_lock); - return -EIO; - } - - off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; - di = (struct bfs_inode *)bh->b_data + off; if (ino == BFS_ROOT_INO) di->i_vtype = cpu_to_le32(BFS_VDIR); @@ -147,7 +151,7 @@ static int bfs_write_inode(struct inode *inode, int wait) di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1); mark_buffer_dirty(bh); - if (wait) { + if (wbc->sync_mode == WB_SYNC_ALL) { sync_dirty_buffer(bh); if (buffer_req(bh) && !buffer_uptodate(bh)) err = -EIO; @@ -157,12 +161,11 @@ static int bfs_write_inode(struct inode *inode, int wait) return err; } -static void bfs_delete_inode(struct inode *inode) +static void bfs_evict_inode(struct inode *inode) { unsigned long ino = inode->i_ino; struct bfs_inode *di; struct buffer_head *bh; - int block, off; struct super_block *s = inode->i_sb; struct bfs_sb_info *info = BFS_SB(s); struct bfs_inode_info *bi = BFS_I(inode); @@ -170,28 +173,19 @@ static void bfs_delete_inode(struct inode *inode) dprintf("ino=%08lx\n", ino); truncate_inode_pages(&inode->i_data, 0); + invalidate_inode_buffers(inode); + end_writeback(inode); - if ((ino < BFS_ROOT_INO) || (ino > info->si_lasti)) { - printf("invalid ino=%08lx\n", ino); + if (inode->i_nlink) return; - } - - inode->i_size = 0; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; - mutex_lock(&info->bfs_lock); - mark_inode_dirty(inode); - block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; - bh = sb_bread(s, block); - if (!bh) { - printf("Unable to read inode %s:%08lx\n", - inode->i_sb->s_id, ino); - mutex_unlock(&info->bfs_lock); + di = find_inode(s, inode->i_ino, &bh); + if (IS_ERR(di)) return; - } - off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; - di = (struct bfs_inode *)bh->b_data + off; - memset((void *)di, 0, sizeof(struct bfs_inode)); + + mutex_lock(&info->bfs_lock); + /* clear on-disk inode */ + memset(di, 0, sizeof(struct bfs_inode)); mark_buffer_dirty(bh); brelse(bh); @@ -208,32 +202,9 @@ static void bfs_delete_inode(struct inode *inode) * "last block of the last file" even if there is no * real file there, saves us 1 gap. */ - if (info->si_lf_eblk == bi->i_eblock) { + if (info->si_lf_eblk == bi->i_eblock) info->si_lf_eblk = bi->i_sblock - 1; - mark_buffer_dirty(info->si_sbh); - } - mutex_unlock(&info->bfs_lock); - 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) @@ -243,18 +214,10 @@ static void bfs_put_super(struct super_block *s) if (!info) return; - lock_kernel(); - - if (s->s_dirt) - bfs_write_super(s); - - brelse(info->si_sbh); mutex_destroy(&info->bfs_lock); kfree(info->si_imap); kfree(info); s->s_fs_info = NULL; - - unlock_kernel(); } static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf) @@ -318,10 +281,8 @@ static const struct super_operations bfs_sops = { .alloc_inode = bfs_alloc_inode, .destroy_inode = bfs_destroy_inode, .write_inode = bfs_write_inode, - .delete_inode = bfs_delete_inode, + .evict_inode = bfs_evict_inode, .put_super = bfs_put_super, - .write_super = bfs_write_super, - .sync_fs = bfs_sync_fs, .statfs = bfs_statfs, }; @@ -348,7 +309,7 @@ void dump_imap(const char *prefix, struct super_block *s) static int bfs_fill_super(struct super_block *s, void *data, int silent) { - struct buffer_head *bh; + struct buffer_head *bh, *sbh; struct bfs_super_block *bfs_sb; struct inode *inode; unsigned i, imap_len; @@ -364,10 +325,10 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) sb_set_blocksize(s, BFS_BSIZE); - info->si_sbh = sb_bread(s, 0); - if (!info->si_sbh) + sbh = sb_bread(s, 0); + if (!sbh) goto out; - bfs_sb = (struct bfs_super_block *)info->si_sbh->b_data; + bfs_sb = (struct bfs_super_block *)sbh->b_data; if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) { if (!silent) printf("No BFS filesystem on %s (magic=%08x)\n", @@ -471,10 +432,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) info->si_lf_eblk = eblock; } brelse(bh); - if (!(s->s_flags & MS_RDONLY)) { - mark_buffer_dirty(info->si_sbh); - s->s_dirt = 1; - } + brelse(sbh); dump_imap("read_super", s); return 0; @@ -484,7 +442,7 @@ out3: out2: kfree(info->si_imap); out1: - brelse(info->si_sbh); + brelse(sbh); out: mutex_destroy(&info->bfs_lock); kfree(info); |