aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysv
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysv')
-rw-r--r--fs/sysv/dir.c7
-rw-r--r--fs/sysv/file.c17
-rw-r--r--fs/sysv/inode.c74
-rw-r--r--fs/sysv/sysv.h1
4 files changed, 37 insertions, 62 deletions
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 56f655254bfe..4e50286a4cc3 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -15,16 +15,16 @@
15 15
16#include <linux/pagemap.h> 16#include <linux/pagemap.h>
17#include <linux/highmem.h> 17#include <linux/highmem.h>
18#include <linux/smp_lock.h>
19#include <linux/swap.h> 18#include <linux/swap.h>
20#include "sysv.h" 19#include "sysv.h"
21 20
22static int sysv_readdir(struct file *, void *, filldir_t); 21static int sysv_readdir(struct file *, void *, filldir_t);
23 22
24const struct file_operations sysv_dir_operations = { 23const struct file_operations sysv_dir_operations = {
24 .llseek = generic_file_llseek,
25 .read = generic_read_dir, 25 .read = generic_read_dir,
26 .readdir = sysv_readdir, 26 .readdir = sysv_readdir,
27 .fsync = sysv_sync_file, 27 .fsync = simple_fsync,
28}; 28};
29 29
30static inline void dir_put_page(struct page *page) 30static inline void dir_put_page(struct page *page)
@@ -74,8 +74,6 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
74 unsigned long n = pos >> PAGE_CACHE_SHIFT; 74 unsigned long n = pos >> PAGE_CACHE_SHIFT;
75 unsigned long npages = dir_pages(inode); 75 unsigned long npages = dir_pages(inode);
76 76
77 lock_kernel();
78
79 pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1); 77 pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
80 if (pos >= inode->i_size) 78 if (pos >= inode->i_size)
81 goto done; 79 goto done;
@@ -113,7 +111,6 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
113 111
114done: 112done:
115 filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset; 113 filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset;
116 unlock_kernel();
117 return 0; 114 return 0;
118} 115}
119 116
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 589be21d884e..96340c01f4a7 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -26,7 +26,7 @@ const struct file_operations sysv_file_operations = {
26 .write = do_sync_write, 26 .write = do_sync_write,
27 .aio_write = generic_file_aio_write, 27 .aio_write = generic_file_aio_write,
28 .mmap = generic_file_mmap, 28 .mmap = generic_file_mmap,
29 .fsync = sysv_sync_file, 29 .fsync = simple_fsync,
30 .splice_read = generic_file_splice_read, 30 .splice_read = generic_file_splice_read,
31}; 31};
32 32
@@ -34,18 +34,3 @@ const struct inode_operations sysv_file_inode_operations = {
34 .truncate = sysv_truncate, 34 .truncate = sysv_truncate,
35 .getattr = sysv_getattr, 35 .getattr = sysv_getattr,
36}; 36};
37
38int sysv_sync_file(struct file * file, struct dentry *dentry, int datasync)
39{
40 struct inode *inode = dentry->d_inode;
41 int err;
42
43 err = sync_mapping_buffers(inode->i_mapping);
44 if (!(inode->i_state & I_DIRTY))
45 return err;
46 if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
47 return err;
48
49 err |= sysv_sync_inode(inode);
50 return err ? -EIO : 0;
51}
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index da20b48d350f..9824743832a7 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -21,7 +21,6 @@
21 * the superblock. 21 * the superblock.
22 */ 22 */
23 23
24#include <linux/smp_lock.h>
25#include <linux/highuid.h> 24#include <linux/highuid.h>
26#include <linux/slab.h> 25#include <linux/slab.h>
27#include <linux/init.h> 26#include <linux/init.h>
@@ -31,15 +30,12 @@
31#include <asm/byteorder.h> 30#include <asm/byteorder.h>
32#include "sysv.h" 31#include "sysv.h"
33 32
34/* This is only called on sync() and umount(), when s_dirt=1. */ 33static int sysv_sync_fs(struct super_block *sb, int wait)
35static void sysv_write_super(struct super_block *sb)
36{ 34{
37 struct sysv_sb_info *sbi = SYSV_SB(sb); 35 struct sysv_sb_info *sbi = SYSV_SB(sb);
38 unsigned long time = get_seconds(), old_time; 36 unsigned long time = get_seconds(), old_time;
39 37
40 lock_kernel(); 38 lock_super(sb);
41 if (sb->s_flags & MS_RDONLY)
42 goto clean;
43 39
44 /* 40 /*
45 * If we are going to write out the super block, 41 * If we are going to write out the super block,
@@ -53,18 +49,29 @@ static void sysv_write_super(struct super_block *sb)
53 *sbi->s_sb_time = cpu_to_fs32(sbi, time); 49 *sbi->s_sb_time = cpu_to_fs32(sbi, time);
54 mark_buffer_dirty(sbi->s_bh2); 50 mark_buffer_dirty(sbi->s_bh2);
55 } 51 }
56clean: 52
57 sb->s_dirt = 0; 53 unlock_super(sb);
58 unlock_kernel(); 54
55 return 0;
56}
57
58static void sysv_write_super(struct super_block *sb)
59{
60 if (!(sb->s_flags & MS_RDONLY))
61 sysv_sync_fs(sb, 1);
62 else
63 sb->s_dirt = 0;
59} 64}
60 65
61static int sysv_remount(struct super_block *sb, int *flags, char *data) 66static int sysv_remount(struct super_block *sb, int *flags, char *data)
62{ 67{
63 struct sysv_sb_info *sbi = SYSV_SB(sb); 68 struct sysv_sb_info *sbi = SYSV_SB(sb);
69 lock_super(sb);
64 if (sbi->s_forced_ro) 70 if (sbi->s_forced_ro)
65 *flags |= MS_RDONLY; 71 *flags |= MS_RDONLY;
66 if (!(*flags & MS_RDONLY)) 72 if (!(*flags & MS_RDONLY))
67 sb->s_dirt = 1; 73 sb->s_dirt = 1;
74 unlock_super(sb);
68 return 0; 75 return 0;
69} 76}
70 77
@@ -72,6 +79,9 @@ static void sysv_put_super(struct super_block *sb)
72{ 79{
73 struct sysv_sb_info *sbi = SYSV_SB(sb); 80 struct sysv_sb_info *sbi = SYSV_SB(sb);
74 81
82 if (sb->s_dirt)
83 sysv_write_super(sb);
84
75 if (!(sb->s_flags & MS_RDONLY)) { 85 if (!(sb->s_flags & MS_RDONLY)) {
76 /* XXX ext2 also updates the state here */ 86 /* XXX ext2 also updates the state here */
77 mark_buffer_dirty(sbi->s_bh1); 87 mark_buffer_dirty(sbi->s_bh1);
@@ -236,7 +246,7 @@ bad_inode:
236 return ERR_PTR(-EIO); 246 return ERR_PTR(-EIO);
237} 247}
238 248
239static struct buffer_head * sysv_update_inode(struct inode * inode) 249int sysv_write_inode(struct inode *inode, int wait)
240{ 250{
241 struct super_block * sb = inode->i_sb; 251 struct super_block * sb = inode->i_sb;
242 struct sysv_sb_info * sbi = SYSV_SB(sb); 252 struct sysv_sb_info * sbi = SYSV_SB(sb);
@@ -244,17 +254,18 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
244 struct sysv_inode * raw_inode; 254 struct sysv_inode * raw_inode;
245 struct sysv_inode_info * si; 255 struct sysv_inode_info * si;
246 unsigned int ino, block; 256 unsigned int ino, block;
257 int err = 0;
247 258
248 ino = inode->i_ino; 259 ino = inode->i_ino;
249 if (!ino || ino > sbi->s_ninodes) { 260 if (!ino || ino > sbi->s_ninodes) {
250 printk("Bad inode number on dev %s: %d is out of range\n", 261 printk("Bad inode number on dev %s: %d is out of range\n",
251 inode->i_sb->s_id, ino); 262 inode->i_sb->s_id, ino);
252 return NULL; 263 return -EIO;
253 } 264 }
254 raw_inode = sysv_raw_inode(sb, ino, &bh); 265 raw_inode = sysv_raw_inode(sb, ino, &bh);
255 if (!raw_inode) { 266 if (!raw_inode) {
256 printk("unable to read i-node block\n"); 267 printk("unable to read i-node block\n");
257 return NULL; 268 return -EIO;
258 } 269 }
259 270
260 raw_inode->i_mode = cpu_to_fs16(sbi, inode->i_mode); 271 raw_inode->i_mode = cpu_to_fs16(sbi, inode->i_mode);
@@ -273,37 +284,21 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
273 write3byte(sbi, (u8 *)&si->i_data[block], 284 write3byte(sbi, (u8 *)&si->i_data[block],
274 &raw_inode->i_data[3*block]); 285 &raw_inode->i_data[3*block]);
275 mark_buffer_dirty(bh); 286 mark_buffer_dirty(bh);
276 return bh; 287 if (wait) {
277} 288 sync_dirty_buffer(bh);
278 289 if (buffer_req(bh) && !buffer_uptodate(bh)) {
279int sysv_write_inode(struct inode * inode, int wait) 290 printk ("IO error syncing sysv inode [%s:%08x]\n",
280{ 291 sb->s_id, ino);
281 struct buffer_head *bh; 292 err = -EIO;
282 lock_kernel(); 293 }
283 bh = sysv_update_inode(inode); 294 }
284 brelse(bh); 295 brelse(bh);
285 unlock_kernel();
286 return 0; 296 return 0;
287} 297}
288 298
289int sysv_sync_inode(struct inode * inode) 299int sysv_sync_inode(struct inode *inode)
290{ 300{
291 int err = 0; 301 return sysv_write_inode(inode, 1);
292 struct buffer_head *bh;
293
294 bh = sysv_update_inode(inode);
295 if (bh && buffer_dirty(bh)) {
296 sync_dirty_buffer(bh);
297 if (buffer_req(bh) && !buffer_uptodate(bh)) {
298 printk ("IO error syncing sysv inode [%s:%08lx]\n",
299 inode->i_sb->s_id, inode->i_ino);
300 err = -1;
301 }
302 }
303 else if (!bh)
304 err = -1;
305 brelse (bh);
306 return err;
307} 302}
308 303
309static void sysv_delete_inode(struct inode *inode) 304static void sysv_delete_inode(struct inode *inode)
@@ -311,9 +306,7 @@ static void sysv_delete_inode(struct inode *inode)
311 truncate_inode_pages(&inode->i_data, 0); 306 truncate_inode_pages(&inode->i_data, 0);
312 inode->i_size = 0; 307 inode->i_size = 0;
313 sysv_truncate(inode); 308 sysv_truncate(inode);
314 lock_kernel();
315 sysv_free_inode(inode); 309 sysv_free_inode(inode);
316 unlock_kernel();
317} 310}
318 311
319static struct kmem_cache *sysv_inode_cachep; 312static struct kmem_cache *sysv_inode_cachep;
@@ -347,6 +340,7 @@ const struct super_operations sysv_sops = {
347 .delete_inode = sysv_delete_inode, 340 .delete_inode = sysv_delete_inode,
348 .put_super = sysv_put_super, 341 .put_super = sysv_put_super,
349 .write_super = sysv_write_super, 342 .write_super = sysv_write_super,
343 .sync_fs = sysv_sync_fs,
350 .remount_fs = sysv_remount, 344 .remount_fs = sysv_remount,
351 .statfs = sysv_statfs, 345 .statfs = sysv_statfs,
352}; 346};
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index 5784a318c883..53786eb5cf60 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -144,7 +144,6 @@ extern int __sysv_write_begin(struct file *file, struct address_space *mapping,
144extern struct inode *sysv_iget(struct super_block *, unsigned int); 144extern struct inode *sysv_iget(struct super_block *, unsigned int);
145extern int sysv_write_inode(struct inode *, int); 145extern int sysv_write_inode(struct inode *, int);
146extern int sysv_sync_inode(struct inode *); 146extern int sysv_sync_inode(struct inode *);
147extern int sysv_sync_file(struct file *, struct dentry *, int);
148extern void sysv_set_inode(struct inode *, dev_t); 147extern void sysv_set_inode(struct inode *, dev_t);
149extern int sysv_getattr(struct vfsmount *, struct dentry *, struct kstat *); 148extern int sysv_getattr(struct vfsmount *, struct dentry *, struct kstat *);
150extern int sysv_init_icache(void); 149extern int sysv_init_icache(void);