aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysv
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysv')
-rw-r--r--fs/sysv/balloc.c18
-rw-r--r--fs/sysv/file.c5
-rw-r--r--fs/sysv/ialloc.c14
-rw-r--r--fs/sysv/inode.c35
-rw-r--r--fs/sysv/itree.c17
-rw-r--r--fs/sysv/namei.c4
-rw-r--r--fs/sysv/super.c1
-rw-r--r--fs/sysv/sysv.h2
8 files changed, 47 insertions, 49 deletions
diff --git a/fs/sysv/balloc.c b/fs/sysv/balloc.c
index 9a6ad96acf2..921c053fc05 100644
--- a/fs/sysv/balloc.c
+++ b/fs/sysv/balloc.c
@@ -60,12 +60,12 @@ void sysv_free_block(struct super_block * sb, sysv_zone_t nr)
return;
}
- lock_super(sb);
+ mutex_lock(&sbi->s_lock);
count = fs16_to_cpu(sbi, *sbi->s_bcache_count);
if (count > sbi->s_flc_size) {
printk("sysv_free_block: flc_count > flc_size\n");
- unlock_super(sb);
+ mutex_unlock(&sbi->s_lock);
return;
}
/* If the free list head in super-block is full, it is copied
@@ -77,7 +77,7 @@ void sysv_free_block(struct super_block * sb, sysv_zone_t nr)
bh = sb_getblk(sb, block);
if (!bh) {
printk("sysv_free_block: getblk() failed\n");
- unlock_super(sb);
+ mutex_unlock(&sbi->s_lock);
return;
}
memset(bh->b_data, 0, sb->s_blocksize);
@@ -93,7 +93,7 @@ void sysv_free_block(struct super_block * sb, sysv_zone_t nr)
*sbi->s_bcache_count = cpu_to_fs16(sbi, count);
fs32_add(sbi, sbi->s_free_blocks, 1);
dirty_sb(sb);
- unlock_super(sb);
+ mutex_unlock(&sbi->s_lock);
}
sysv_zone_t sysv_new_block(struct super_block * sb)
@@ -104,7 +104,7 @@ sysv_zone_t sysv_new_block(struct super_block * sb)
struct buffer_head * bh;
unsigned count;
- lock_super(sb);
+ mutex_lock(&sbi->s_lock);
count = fs16_to_cpu(sbi, *sbi->s_bcache_count);
if (count == 0) /* Applies only to Coherent FS */
@@ -147,11 +147,11 @@ sysv_zone_t sysv_new_block(struct super_block * sb)
/* Now the free list head in the superblock is valid again. */
fs32_add(sbi, sbi->s_free_blocks, -1);
dirty_sb(sb);
- unlock_super(sb);
+ mutex_unlock(&sbi->s_lock);
return nr;
Enospc:
- unlock_super(sb);
+ mutex_unlock(&sbi->s_lock);
return 0;
}
@@ -173,7 +173,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
if (sbi->s_type == FSTYPE_AFS)
return 0;
- lock_super(sb);
+ mutex_lock(&sbi->s_lock);
sb_count = fs32_to_cpu(sbi, *sbi->s_free_blocks);
if (0)
@@ -211,7 +211,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
if (count != sb_count)
goto Ecount;
done:
- unlock_super(sb);
+ mutex_unlock(&sbi->s_lock);
return count;
Einval:
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 0a65939508e..9d4dc683179 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -41,9 +41,11 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size != i_size_read(inode)) {
- error = vmtruncate(inode, attr->ia_size);
+ error = inode_newsize_ok(inode, attr->ia_size);
if (error)
return error;
+ truncate_setsize(inode, attr->ia_size);
+ sysv_truncate(inode);
}
setattr_copy(inode, attr);
@@ -52,7 +54,6 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
}
const struct inode_operations sysv_file_inode_operations = {
- .truncate = sysv_truncate,
.setattr = sysv_setattr,
.getattr = sysv_getattr,
};
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
index 8233b02ecca..f9db4eb31db 100644
--- a/fs/sysv/ialloc.c
+++ b/fs/sysv/ialloc.c
@@ -118,7 +118,7 @@ void sysv_free_inode(struct inode * inode)
"%s\n", inode->i_sb->s_id);
return;
}
- lock_super(sb);
+ mutex_lock(&sbi->s_lock);
count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count);
if (count < sbi->s_fic_size) {
*sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sbi, ino);
@@ -128,7 +128,7 @@ void sysv_free_inode(struct inode * inode)
dirty_sb(sb);
memset(raw_inode, 0, sizeof(struct sysv_inode));
mark_buffer_dirty(bh);
- unlock_super(sb);
+ mutex_unlock(&sbi->s_lock);
brelse(bh);
}
@@ -147,13 +147,13 @@ struct inode * sysv_new_inode(const struct inode * dir, umode_t mode)
if (!inode)
return ERR_PTR(-ENOMEM);
- lock_super(sb);
+ mutex_lock(&sbi->s_lock);
count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count);
if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) {
count = refill_free_cache(sb);
if (count == 0) {
iput(inode);
- unlock_super(sb);
+ mutex_unlock(&sbi->s_lock);
return ERR_PTR(-ENOSPC);
}
}
@@ -174,7 +174,7 @@ struct inode * sysv_new_inode(const struct inode * dir, umode_t mode)
sysv_write_inode(inode, &wbc); /* ensure inode not allocated again */
mark_inode_dirty(inode); /* cleared by sysv_write_inode() */
/* That's it. */
- unlock_super(sb);
+ mutex_unlock(&sbi->s_lock);
return inode;
}
@@ -185,7 +185,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb)
struct sysv_inode * raw_inode;
int ino, count, sb_count;
- lock_super(sb);
+ mutex_lock(&sbi->s_lock);
sb_count = fs16_to_cpu(sbi, *sbi->s_sb_total_free_inodes);
@@ -213,7 +213,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb)
if (count != sb_count)
goto Einval;
out:
- unlock_super(sb);
+ mutex_unlock(&sbi->s_lock);
return count;
Einval:
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 08d0b2568cd..c327d4ee123 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -36,14 +36,13 @@ 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,
* then attach current time stamp.
* But if the filesystem was marked clean, keep it clean.
*/
- sb->s_dirt = 0;
old_time = fs32_to_cpu(sbi, *sbi->s_sb_time);
if (sbi->s_type == FSTYPE_SYSV4) {
if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time))
@@ -52,28 +51,17 @@ 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);
+
if (sbi->s_forced_ro)
*flags |= MS_RDONLY;
- if (*flags & MS_RDONLY)
- sysv_write_super(sb);
- unlock_super(sb);
return 0;
}
@@ -81,9 +69,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);
@@ -217,8 +202,8 @@ 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);
+ 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);
@@ -271,8 +256,8 @@ static 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);
@@ -357,7 +342,6 @@ const struct super_operations sysv_sops = {
.write_inode = sysv_write_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,
@@ -376,5 +360,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);
}
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index 90b54b43878..c1a591a4725 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -464,6 +464,16 @@ int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len)
return __block_write_begin(page, pos, len, get_block);
}
+static void sysv_write_failed(struct address_space *mapping, loff_t to)
+{
+ struct inode *inode = mapping->host;
+
+ if (to > inode->i_size) {
+ truncate_pagecache(inode, to, inode->i_size);
+ sysv_truncate(inode);
+ }
+}
+
static int sysv_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata)
@@ -471,11 +481,8 @@ static int sysv_write_begin(struct file *file, struct address_space *mapping,
int ret;
ret = block_write_begin(mapping, pos, len, flags, pagep, get_block);
- if (unlikely(ret)) {
- loff_t isize = mapping->host->i_size;
- if (pos + len > isize)
- vmtruncate(mapping->host, isize);
- }
+ if (unlikely(ret))
+ sysv_write_failed(mapping, pos + len);
return ret;
}
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index d7466e29361..1c0d5f26476 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -43,7 +43,7 @@ const struct dentry_operations sysv_dentry_operations = {
.d_hash = sysv_hash,
};
-static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
{
struct inode * inode = NULL;
ino_t ino;
@@ -80,7 +80,7 @@ static int sysv_mknod(struct inode * dir, struct dentry * dentry, umode_t mode,
return err;
}
-static int sysv_create(struct inode * dir, struct dentry * dentry, umode_t mode, struct nameidata *nd)
+static int sysv_create(struct inode * dir, struct dentry * dentry, umode_t mode, bool excl)
{
return sysv_mknod(dir, dentry, mode, 0);
}
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index 7491c33b646..a38e87bdd78 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -368,6 +368,7 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_sb = sb;
sbi->s_block_base = 0;
+ mutex_init(&sbi->s_lock);
sb->s_fs_info = sbi;
sb_set_blocksize(sb, BLOCK_SIZE);
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index 11b07672f6c..69d488986cc 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -58,6 +58,7 @@ struct sysv_sb_info {
u32 s_nzones; /* same as s_sbd->s_fsize */
u16 s_namelen; /* max length of dir entry */
int s_forced_ro;
+ struct mutex s_lock;
};
/*
@@ -117,7 +118,6 @@ static inline void dirty_sb(struct super_block *sb)
mark_buffer_dirty(sbi->s_bh1);
if (sbi->s_bh1 != sbi->s_bh2)
mark_buffer_dirty(sbi->s_bh2);
- sb->s_dirt = 1;
}