diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2009-06-07 09:30:08 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-06-11 21:36:11 -0400 |
commit | 79d25767583e4e086f8309bfd1f502660a64fe7f (patch) | |
tree | f13414f324d859f82c604bb4027a4aab19bed909 | |
parent | d5aacad548db1ff547adf35d0a77eb2a8ed4fe14 (diff) |
Sanitize qnx4 fsync handling
* have directory operations use mark_buffer_dirty_inode(),
so that sync_mapping_buffers() would get those.
* make qnx4_write_inode() honour its last argument.
* get rid of insane copies of very ancient "walk the indirect blocks"
in qnx4/fsync - they never matched the actual fs layout and, fortunately,
never'd been called. Again, all this junk is not needed; ->fsync()
should just do sync_mapping_buffers + sync_inode (and if we implement
block allocation for qnx4, we'll need to use mark_buffer_dirty_inode()
for extent blocks)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/qnx4/Makefile | 2 | ||||
-rw-r--r-- | fs/qnx4/dir.c | 2 | ||||
-rw-r--r-- | fs/qnx4/file.c | 2 | ||||
-rw-r--r-- | fs/qnx4/fsync.c | 169 | ||||
-rw-r--r-- | fs/qnx4/inode.c | 38 | ||||
-rw-r--r-- | fs/qnx4/namei.c | 4 | ||||
-rw-r--r-- | include/linux/qnx4_fs.h | 2 |
7 files changed, 17 insertions, 202 deletions
diff --git a/fs/qnx4/Makefile b/fs/qnx4/Makefile index 502d7fe98bab..e4d408cc5473 100644 --- a/fs/qnx4/Makefile +++ b/fs/qnx4/Makefile | |||
@@ -4,4 +4,4 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_QNX4FS_FS) += qnx4.o | 5 | obj-$(CONFIG_QNX4FS_FS) += qnx4.o |
6 | 6 | ||
7 | qnx4-objs := inode.o dir.o namei.o file.o bitmap.o truncate.o fsync.o | 7 | qnx4-objs := inode.o dir.o namei.o file.o bitmap.o truncate.o |
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c index ea9ffefb48ad..ff6c1ba6c4e0 100644 --- a/fs/qnx4/dir.c +++ b/fs/qnx4/dir.c | |||
@@ -84,7 +84,7 @@ const struct file_operations qnx4_dir_operations = | |||
84 | { | 84 | { |
85 | .read = generic_read_dir, | 85 | .read = generic_read_dir, |
86 | .readdir = qnx4_readdir, | 86 | .readdir = qnx4_readdir, |
87 | .fsync = file_fsync, | 87 | .fsync = simple_fsync, |
88 | }; | 88 | }; |
89 | 89 | ||
90 | const struct inode_operations qnx4_dir_inode_operations = | 90 | const struct inode_operations qnx4_dir_inode_operations = |
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c index 867f42b02035..e7033ea10e2f 100644 --- a/fs/qnx4/file.c +++ b/fs/qnx4/file.c | |||
@@ -29,7 +29,7 @@ const struct file_operations qnx4_file_operations = | |||
29 | #ifdef CONFIG_QNX4FS_RW | 29 | #ifdef CONFIG_QNX4FS_RW |
30 | .write = do_sync_write, | 30 | .write = do_sync_write, |
31 | .aio_write = generic_file_aio_write, | 31 | .aio_write = generic_file_aio_write, |
32 | .fsync = qnx4_sync_file, | 32 | .fsync = simple_fsync, |
33 | #endif | 33 | #endif |
34 | }; | 34 | }; |
35 | 35 | ||
diff --git a/fs/qnx4/fsync.c b/fs/qnx4/fsync.c deleted file mode 100644 index aa3b19544bee..000000000000 --- a/fs/qnx4/fsync.c +++ /dev/null | |||
@@ -1,169 +0,0 @@ | |||
1 | /* | ||
2 | * QNX4 file system, Linux implementation. | ||
3 | * | ||
4 | * Version : 0.1 | ||
5 | * | ||
6 | * Using parts of the xiafs filesystem. | ||
7 | * | ||
8 | * History : | ||
9 | * | ||
10 | * 24-03-1998 by Richard Frowijn : first release. | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/time.h> | ||
15 | #include <linux/stat.h> | ||
16 | #include <linux/fcntl.h> | ||
17 | #include <linux/smp_lock.h> | ||
18 | #include <linux/buffer_head.h> | ||
19 | |||
20 | #include <linux/fs.h> | ||
21 | #include <linux/qnx4_fs.h> | ||
22 | |||
23 | #include <asm/system.h> | ||
24 | |||
25 | /* | ||
26 | * The functions for qnx4 fs file synchronization. | ||
27 | */ | ||
28 | |||
29 | #ifdef CONFIG_QNX4FS_RW | ||
30 | |||
31 | static int sync_block(struct inode *inode, unsigned short *block, int wait) | ||
32 | { | ||
33 | struct buffer_head *bh; | ||
34 | unsigned short tmp; | ||
35 | |||
36 | if (!*block) | ||
37 | return 0; | ||
38 | tmp = *block; | ||
39 | bh = sb_find_get_block(inode->i_sb, *block); | ||
40 | if (!bh) | ||
41 | return 0; | ||
42 | if (*block != tmp) { | ||
43 | brelse(bh); | ||
44 | return 1; | ||
45 | } | ||
46 | if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { | ||
47 | brelse(bh); | ||
48 | return -1; | ||
49 | } | ||
50 | if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { | ||
51 | brelse(bh); | ||
52 | return 0; | ||
53 | } | ||
54 | ll_rw_block(WRITE, 1, &bh); | ||
55 | atomic_dec(&bh->b_count); | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | #ifdef WTF | ||
60 | static int sync_iblock(struct inode *inode, unsigned short *iblock, | ||
61 | struct buffer_head **bh, int wait) | ||
62 | { | ||
63 | int rc; | ||
64 | unsigned short tmp; | ||
65 | |||
66 | *bh = NULL; | ||
67 | tmp = *iblock; | ||
68 | if (!tmp) | ||
69 | return 0; | ||
70 | rc = sync_block(inode, iblock, wait); | ||
71 | if (rc) | ||
72 | return rc; | ||
73 | *bh = sb_bread(inode->i_sb, tmp); | ||
74 | if (tmp != *iblock) { | ||
75 | brelse(*bh); | ||
76 | *bh = NULL; | ||
77 | return 1; | ||
78 | } | ||
79 | if (!*bh) | ||
80 | return -1; | ||
81 | return 0; | ||
82 | } | ||
83 | #endif | ||
84 | |||
85 | static int sync_direct(struct inode *inode, int wait) | ||
86 | { | ||
87 | int i; | ||
88 | int rc, err = 0; | ||
89 | |||
90 | for (i = 0; i < 7; i++) { | ||
91 | rc = sync_block(inode, | ||
92 | (unsigned short *) qnx4_raw_inode(inode)->di_first_xtnt.xtnt_blk + i, wait); | ||
93 | if (rc > 0) | ||
94 | break; | ||
95 | if (rc) | ||
96 | err = rc; | ||
97 | } | ||
98 | return err; | ||
99 | } | ||
100 | |||
101 | #ifdef WTF | ||
102 | static int sync_indirect(struct inode *inode, unsigned short *iblock, int wait) | ||
103 | { | ||
104 | int i; | ||
105 | struct buffer_head *ind_bh; | ||
106 | int rc, err = 0; | ||
107 | |||
108 | rc = sync_iblock(inode, iblock, &ind_bh, wait); | ||
109 | if (rc || !ind_bh) | ||
110 | return rc; | ||
111 | |||
112 | for (i = 0; i < 512; i++) { | ||
113 | rc = sync_block(inode, | ||
114 | ((unsigned short *) ind_bh->b_data) + i, | ||
115 | wait); | ||
116 | if (rc > 0) | ||
117 | break; | ||
118 | if (rc) | ||
119 | err = rc; | ||
120 | } | ||
121 | brelse(ind_bh); | ||
122 | return err; | ||
123 | } | ||
124 | |||
125 | static int sync_dindirect(struct inode *inode, unsigned short *diblock, | ||
126 | int wait) | ||
127 | { | ||
128 | int i; | ||
129 | struct buffer_head *dind_bh; | ||
130 | int rc, err = 0; | ||
131 | |||
132 | rc = sync_iblock(inode, diblock, &dind_bh, wait); | ||
133 | if (rc || !dind_bh) | ||
134 | return rc; | ||
135 | |||
136 | for (i = 0; i < 512; i++) { | ||
137 | rc = sync_indirect(inode, | ||
138 | ((unsigned short *) dind_bh->b_data) + i, | ||
139 | wait); | ||
140 | if (rc > 0) | ||
141 | break; | ||
142 | if (rc) | ||
143 | err = rc; | ||
144 | } | ||
145 | brelse(dind_bh); | ||
146 | return err; | ||
147 | } | ||
148 | #endif | ||
149 | |||
150 | int qnx4_sync_file(struct file *file, struct dentry *dentry, int unused) | ||
151 | { | ||
152 | struct inode *inode = dentry->d_inode; | ||
153 | int wait, err = 0; | ||
154 | |||
155 | (void) file; | ||
156 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | ||
157 | S_ISLNK(inode->i_mode))) | ||
158 | return -EINVAL; | ||
159 | |||
160 | lock_kernel(); | ||
161 | for (wait = 0; wait <= 1; wait++) { | ||
162 | err |= sync_direct(inode, wait); | ||
163 | } | ||
164 | err |= qnx4_sync_inode(inode); | ||
165 | unlock_kernel(); | ||
166 | return (err < 0) ? -EIO : 0; | ||
167 | } | ||
168 | |||
169 | #endif | ||
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 95c12fc613f1..40712867b8a8 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/smp_lock.h> | 24 | #include <linux/smp_lock.h> |
25 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
26 | #include <linux/buffer_head.h> | 26 | #include <linux/buffer_head.h> |
27 | #include <linux/writeback.h> | ||
27 | #include <linux/vfs.h> | 28 | #include <linux/vfs.h> |
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
29 | 30 | ||
@@ -34,31 +35,6 @@ static const struct super_operations qnx4_sops; | |||
34 | 35 | ||
35 | #ifdef CONFIG_QNX4FS_RW | 36 | #ifdef CONFIG_QNX4FS_RW |
36 | 37 | ||
37 | int qnx4_sync_inode(struct inode *inode) | ||
38 | { | ||
39 | int err = 0; | ||
40 | # if 0 | ||
41 | struct buffer_head *bh; | ||
42 | |||
43 | bh = qnx4_update_inode(inode); | ||
44 | if (bh && buffer_dirty(bh)) | ||
45 | { | ||
46 | sync_dirty_buffer(bh); | ||
47 | if (buffer_req(bh) && !buffer_uptodate(bh)) | ||
48 | { | ||
49 | printk ("IO error syncing qnx4 inode [%s:%08lx]\n", | ||
50 | inode->i_sb->s_id, inode->i_ino); | ||
51 | err = -1; | ||
52 | } | ||
53 | brelse (bh); | ||
54 | } else if (!bh) { | ||
55 | err = -1; | ||
56 | } | ||
57 | # endif | ||
58 | |||
59 | return err; | ||
60 | } | ||
61 | |||
62 | static void qnx4_delete_inode(struct inode *inode) | 38 | static void qnx4_delete_inode(struct inode *inode) |
63 | { | 39 | { |
64 | QNX4DEBUG(("qnx4: deleting inode [%lu]\n", (unsigned long) inode->i_ino)); | 40 | QNX4DEBUG(("qnx4: deleting inode [%lu]\n", (unsigned long) inode->i_ino)); |
@@ -70,7 +46,7 @@ static void qnx4_delete_inode(struct inode *inode) | |||
70 | unlock_kernel(); | 46 | unlock_kernel(); |
71 | } | 47 | } |
72 | 48 | ||
73 | static int qnx4_write_inode(struct inode *inode, int unused) | 49 | static int qnx4_write_inode(struct inode *inode, int do_sync) |
74 | { | 50 | { |
75 | struct qnx4_inode_entry *raw_inode; | 51 | struct qnx4_inode_entry *raw_inode; |
76 | int block, ino; | 52 | int block, ino; |
@@ -107,6 +83,16 @@ static int qnx4_write_inode(struct inode *inode, int unused) | |||
107 | raw_inode->di_ctime = cpu_to_le32(inode->i_ctime.tv_sec); | 83 | raw_inode->di_ctime = cpu_to_le32(inode->i_ctime.tv_sec); |
108 | raw_inode->di_first_xtnt.xtnt_size = cpu_to_le32(inode->i_blocks); | 84 | raw_inode->di_first_xtnt.xtnt_size = cpu_to_le32(inode->i_blocks); |
109 | mark_buffer_dirty(bh); | 85 | mark_buffer_dirty(bh); |
86 | if (do_sync) { | ||
87 | sync_dirty_buffer(bh); | ||
88 | if (buffer_req(bh) && !buffer_uptodate(bh)) { | ||
89 | printk("qnx4: IO error syncing inode [%s:%08x]\n", | ||
90 | inode->i_sb->s_id, ino); | ||
91 | brelse(bh); | ||
92 | unlock_kernel(); | ||
93 | return -EIO; | ||
94 | } | ||
95 | } | ||
110 | brelse(bh); | 96 | brelse(bh); |
111 | unlock_kernel(); | 97 | unlock_kernel(); |
112 | return 0; | 98 | return 0; |
diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c index 775eed3a4085..123270c53760 100644 --- a/fs/qnx4/namei.c +++ b/fs/qnx4/namei.c | |||
@@ -187,7 +187,7 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry) | |||
187 | de->di_status = 0; | 187 | de->di_status = 0; |
188 | memset(de->di_fname, 0, sizeof de->di_fname); | 188 | memset(de->di_fname, 0, sizeof de->di_fname); |
189 | de->di_mode = 0; | 189 | de->di_mode = 0; |
190 | mark_buffer_dirty(bh); | 190 | mark_buffer_dirty_inode(bh, dir); |
191 | clear_nlink(inode); | 191 | clear_nlink(inode); |
192 | mark_inode_dirty(inode); | 192 | mark_inode_dirty(inode); |
193 | inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; | 193 | inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; |
@@ -232,7 +232,7 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry) | |||
232 | de->di_status = 0; | 232 | de->di_status = 0; |
233 | memset(de->di_fname, 0, sizeof de->di_fname); | 233 | memset(de->di_fname, 0, sizeof de->di_fname); |
234 | de->di_mode = 0; | 234 | de->di_mode = 0; |
235 | mark_buffer_dirty(bh); | 235 | mark_buffer_dirty_inode(bh, dir); |
236 | dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; | 236 | dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; |
237 | mark_inode_dirty(dir); | 237 | mark_inode_dirty(dir); |
238 | inode->i_ctime = dir->i_ctime; | 238 | inode->i_ctime = dir->i_ctime; |
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h index 787d19ea9f46..acbaec3524e0 100644 --- a/include/linux/qnx4_fs.h +++ b/include/linux/qnx4_fs.h | |||
@@ -126,8 +126,6 @@ extern void qnx4_truncate(struct inode *inode); | |||
126 | extern void qnx4_free_inode(struct inode *inode); | 126 | extern void qnx4_free_inode(struct inode *inode); |
127 | extern int qnx4_unlink(struct inode *dir, struct dentry *dentry); | 127 | extern int qnx4_unlink(struct inode *dir, struct dentry *dentry); |
128 | extern int qnx4_rmdir(struct inode *dir, struct dentry *dentry); | 128 | extern int qnx4_rmdir(struct inode *dir, struct dentry *dentry); |
129 | extern int qnx4_sync_file(struct file *file, struct dentry *dentry, int); | ||
130 | extern int qnx4_sync_inode(struct inode *inode); | ||
131 | 129 | ||
132 | static inline struct qnx4_sb_info *qnx4_sb(struct super_block *sb) | 130 | static inline struct qnx4_sb_info *qnx4_sb(struct super_block *sb) |
133 | { | 131 | { |