diff options
Diffstat (limited to 'fs/sysv/inode.c')
| -rw-r--r-- | fs/sysv/inode.c | 72 |
1 files changed, 40 insertions, 32 deletions
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 9824743832a..88956309cc8 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -26,6 +26,7 @@ #include <linux/init.h> #include <linux/buffer_head.h> #include <linux/vfs.h> +#include <linux/writeback.h> #include <linux/namei.h> #include <asm/byteorder.h> #include "sysv.h" @@ -35,7 +36,7 @@ static int sysv_sync_fs(struct super_block *sb, int wait) struct sysv_sb_info *sbi = SYSV_SB(sb); unsigned long time = get_seconds(), old_time; - lock_super(sb); + mutex_lock(&sbi->s_lock); /* * If we are going to write out the super block, @@ -50,28 +51,18 @@ static int sysv_sync_fs(struct super_block *sb, int wait) mark_buffer_dirty(sbi->s_bh2); } - unlock_super(sb); + mutex_unlock(&sbi->s_lock); return 0; } -static void sysv_write_super(struct super_block *sb) -{ - if (!(sb->s_flags & MS_RDONLY)) - sysv_sync_fs(sb, 1); - else - sb->s_dirt = 0; -} - static int sysv_remount(struct super_block *sb, int *flags, char *data) { struct sysv_sb_info *sbi = SYSV_SB(sb); - lock_super(sb); + + sync_filesystem(sb); if (sbi->s_forced_ro) *flags |= MS_RDONLY; - if (!(*flags & MS_RDONLY)) - sb->s_dirt = 1; - unlock_super(sb); return 0; } @@ -79,9 +70,6 @@ static void sysv_put_super(struct super_block *sb) { struct sysv_sb_info *sbi = SYSV_SB(sb); - if (sb->s_dirt) - sysv_write_super(sb); - if (!(sb->s_flags & MS_RDONLY)) { /* XXX ext2 also updates the state here */ mark_buffer_dirty(sbi->s_bh1); @@ -215,9 +203,9 @@ struct inode *sysv_iget(struct super_block *sb, unsigned int ino) } /* SystemV FS: kludge permissions if ino==SYSV_ROOT_INO ?? */ inode->i_mode = fs16_to_cpu(sbi, raw_inode->i_mode); - inode->i_uid = (uid_t)fs16_to_cpu(sbi, raw_inode->i_uid); - inode->i_gid = (gid_t)fs16_to_cpu(sbi, raw_inode->i_gid); - inode->i_nlink = fs16_to_cpu(sbi, raw_inode->i_nlink); + i_uid_write(inode, (uid_t)fs16_to_cpu(sbi, raw_inode->i_uid)); + i_gid_write(inode, (gid_t)fs16_to_cpu(sbi, raw_inode->i_gid)); + set_nlink(inode, fs16_to_cpu(sbi, raw_inode->i_nlink)); inode->i_size = fs32_to_cpu(sbi, raw_inode->i_size); inode->i_atime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_atime); inode->i_mtime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_mtime); @@ -246,7 +234,7 @@ bad_inode: return ERR_PTR(-EIO); } -int sysv_write_inode(struct inode *inode, int wait) +static int __sysv_write_inode(struct inode *inode, int wait) { struct super_block * sb = inode->i_sb; struct sysv_sb_info * sbi = SYSV_SB(sb); @@ -269,8 +257,8 @@ int sysv_write_inode(struct inode *inode, int wait) } raw_inode->i_mode = cpu_to_fs16(sbi, inode->i_mode); - raw_inode->i_uid = cpu_to_fs16(sbi, fs_high2lowuid(inode->i_uid)); - raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(inode->i_gid)); + raw_inode->i_uid = cpu_to_fs16(sbi, fs_high2lowuid(i_uid_read(inode))); + raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(i_gid_read(inode))); raw_inode->i_nlink = cpu_to_fs16(sbi, inode->i_nlink); raw_inode->i_size = cpu_to_fs32(sbi, inode->i_size); raw_inode->i_atime = cpu_to_fs32(sbi, inode->i_atime.tv_sec); @@ -296,17 +284,27 @@ int sysv_write_inode(struct inode *inode, int wait) return 0; } +int sysv_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + return __sysv_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); +} + int sysv_sync_inode(struct inode *inode) { - return sysv_write_inode(inode, 1); + return __sysv_write_inode(inode, 1); } -static void sysv_delete_inode(struct inode *inode) +static void sysv_evict_inode(struct inode *inode) { - truncate_inode_pages(&inode->i_data, 0); - inode->i_size = 0; - sysv_truncate(inode); - sysv_free_inode(inode); + truncate_inode_pages_final(&inode->i_data); + if (!inode->i_nlink) { + inode->i_size = 0; + sysv_truncate(inode); + } + invalidate_inode_buffers(inode); + clear_inode(inode); + if (!inode->i_nlink) + sysv_free_inode(inode); } static struct kmem_cache *sysv_inode_cachep; @@ -321,11 +319,17 @@ static struct inode *sysv_alloc_inode(struct super_block *sb) return &si->vfs_inode; } -static void sysv_destroy_inode(struct inode *inode) +static void sysv_i_callback(struct rcu_head *head) { + struct inode *inode = container_of(head, struct inode, i_rcu); kmem_cache_free(sysv_inode_cachep, SYSV_I(inode)); } +static void sysv_destroy_inode(struct inode *inode) +{ + call_rcu(&inode->i_rcu, sysv_i_callback); +} + static void init_once(void *p) { struct sysv_inode_info *si = (struct sysv_inode_info *)p; @@ -337,9 +341,8 @@ const struct super_operations sysv_sops = { .alloc_inode = sysv_alloc_inode, .destroy_inode = sysv_destroy_inode, .write_inode = sysv_write_inode, - .delete_inode = sysv_delete_inode, + .evict_inode = sysv_evict_inode, .put_super = sysv_put_super, - .write_super = sysv_write_super, .sync_fs = sysv_sync_fs, .remount_fs = sysv_remount, .statfs = sysv_statfs, @@ -358,5 +361,10 @@ int __init sysv_init_icache(void) void sysv_destroy_icache(void) { + /* + * Make sure all delayed rcu free inodes are flushed before we + * destroy cache. + */ + rcu_barrier(); kmem_cache_destroy(sysv_inode_cachep); } |
