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 /fs/qnx4 | |
| 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>
Diffstat (limited to 'fs/qnx4')
| -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 |
6 files changed, 17 insertions, 200 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; |
