aboutsummaryrefslogtreecommitdiff
path: root/fs/sysv/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysv/inode.c')
-rw-r--r--fs/sysv/inode.c72
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);
}