diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-04-06 22:01:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 11:31:17 -0400 |
commit | 47420c799830d4676e544dbec56b2a7f787528f5 (patch) | |
tree | dd61f6c96942b07f762129c893d9cbbbeff60735 /fs/nilfs2/ioctl.c | |
parent | a2e7d2df82cafb76f76809ddf6e2caa8afe4f75e (diff) |
nilfs2: avoid double error caused by nilfs_transaction_end
Pekka Enberg pointed out that double error handlings found after
nilfs_transaction_end() can be avoided by separating abort operation:
OK, I don't understand this. The only way nilfs_transaction_end() can
fail is if we have NILFS_TI_SYNC set and we fail to construct the
segment. But why do we want to construct a segment if we don't commit?
I guess what I'm asking is why don't we have a separate
nilfs_transaction_abort() function that can't fail for the erroneous
case to avoid this double error value tracking thing?
This does the separation and renames nilfs_transaction_end() to
nilfs_transaction_commit() for clarification.
Since, some calls of these functions were used just for exclusion control
against the segment constructor, they are replaced with semaphore
operations.
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nilfs2/ioctl.c')
-rw-r--r-- | fs/nilfs2/ioctl.c | 58 |
1 files changed, 34 insertions, 24 deletions
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 02e91e167ca2..5ce06a01c7ec 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
@@ -105,7 +105,11 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, | |||
105 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 105 | nilfs_transaction_begin(inode->i_sb, &ti, 0); |
106 | ret = nilfs_cpfile_change_cpmode( | 106 | ret = nilfs_cpfile_change_cpmode( |
107 | cpfile, cpmode.cm_cno, cpmode.cm_mode); | 107 | cpfile, cpmode.cm_cno, cpmode.cm_mode); |
108 | nilfs_transaction_end(inode->i_sb, !ret); | 108 | if (unlikely(ret < 0)) { |
109 | nilfs_transaction_abort(inode->i_sb); | ||
110 | return ret; | ||
111 | } | ||
112 | nilfs_transaction_commit(inode->i_sb); /* never fails */ | ||
109 | return ret; | 113 | return ret; |
110 | } | 114 | } |
111 | 115 | ||
@@ -125,7 +129,11 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, | |||
125 | 129 | ||
126 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 130 | nilfs_transaction_begin(inode->i_sb, &ti, 0); |
127 | ret = nilfs_cpfile_delete_checkpoint(cpfile, cno); | 131 | ret = nilfs_cpfile_delete_checkpoint(cpfile, cno); |
128 | nilfs_transaction_end(inode->i_sb, !ret); | 132 | if (unlikely(ret < 0)) { |
133 | nilfs_transaction_abort(inode->i_sb); | ||
134 | return ret; | ||
135 | } | ||
136 | nilfs_transaction_commit(inode->i_sb); /* never fails */ | ||
129 | return ret; | 137 | return ret; |
130 | } | 138 | } |
131 | 139 | ||
@@ -142,16 +150,17 @@ static int nilfs_ioctl_get_cpinfo(struct inode *inode, struct file *filp, | |||
142 | { | 150 | { |
143 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; | 151 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; |
144 | struct nilfs_argv argv; | 152 | struct nilfs_argv argv; |
145 | struct nilfs_transaction_info ti; | ||
146 | int ret; | 153 | int ret; |
147 | 154 | ||
148 | if (copy_from_user(&argv, argp, sizeof(argv))) | 155 | if (copy_from_user(&argv, argp, sizeof(argv))) |
149 | return -EFAULT; | 156 | return -EFAULT; |
150 | 157 | ||
151 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 158 | down_read(&nilfs->ns_segctor_sem); |
152 | ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), | 159 | ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), |
153 | nilfs_ioctl_do_get_cpinfo); | 160 | nilfs_ioctl_do_get_cpinfo); |
154 | nilfs_transaction_end(inode->i_sb, 0); | 161 | up_read(&nilfs->ns_segctor_sem); |
162 | if (ret < 0) | ||
163 | return ret; | ||
155 | 164 | ||
156 | if (copy_to_user(argp, &argv, sizeof(argv))) | 165 | if (copy_to_user(argp, &argv, sizeof(argv))) |
157 | ret = -EFAULT; | 166 | ret = -EFAULT; |
@@ -161,14 +170,13 @@ static int nilfs_ioctl_get_cpinfo(struct inode *inode, struct file *filp, | |||
161 | static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, | 170 | static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, |
162 | unsigned int cmd, void __user *argp) | 171 | unsigned int cmd, void __user *argp) |
163 | { | 172 | { |
164 | struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile; | 173 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; |
165 | struct nilfs_cpstat cpstat; | 174 | struct nilfs_cpstat cpstat; |
166 | struct nilfs_transaction_info ti; | ||
167 | int ret; | 175 | int ret; |
168 | 176 | ||
169 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 177 | down_read(&nilfs->ns_segctor_sem); |
170 | ret = nilfs_cpfile_get_stat(cpfile, &cpstat); | 178 | ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat); |
171 | nilfs_transaction_end(inode->i_sb, 0); | 179 | up_read(&nilfs->ns_segctor_sem); |
172 | if (ret < 0) | 180 | if (ret < 0) |
173 | return ret; | 181 | return ret; |
174 | 182 | ||
@@ -189,16 +197,17 @@ static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp, | |||
189 | { | 197 | { |
190 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; | 198 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; |
191 | struct nilfs_argv argv; | 199 | struct nilfs_argv argv; |
192 | struct nilfs_transaction_info ti; | ||
193 | int ret; | 200 | int ret; |
194 | 201 | ||
195 | if (copy_from_user(&argv, argp, sizeof(argv))) | 202 | if (copy_from_user(&argv, argp, sizeof(argv))) |
196 | return -EFAULT; | 203 | return -EFAULT; |
197 | 204 | ||
198 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 205 | down_read(&nilfs->ns_segctor_sem); |
199 | ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), | 206 | ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), |
200 | nilfs_ioctl_do_get_suinfo); | 207 | nilfs_ioctl_do_get_suinfo); |
201 | nilfs_transaction_end(inode->i_sb, 0); | 208 | up_read(&nilfs->ns_segctor_sem); |
209 | if (ret < 0) | ||
210 | return ret; | ||
202 | 211 | ||
203 | if (copy_to_user(argp, &argv, sizeof(argv))) | 212 | if (copy_to_user(argp, &argv, sizeof(argv))) |
204 | ret = -EFAULT; | 213 | ret = -EFAULT; |
@@ -208,14 +217,13 @@ static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp, | |||
208 | static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, | 217 | static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, |
209 | unsigned int cmd, void __user *argp) | 218 | unsigned int cmd, void __user *argp) |
210 | { | 219 | { |
211 | struct inode *sufile = NILFS_SB(inode->i_sb)->s_nilfs->ns_sufile; | 220 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; |
212 | struct nilfs_sustat sustat; | 221 | struct nilfs_sustat sustat; |
213 | struct nilfs_transaction_info ti; | ||
214 | int ret; | 222 | int ret; |
215 | 223 | ||
216 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 224 | down_read(&nilfs->ns_segctor_sem); |
217 | ret = nilfs_sufile_get_stat(sufile, &sustat); | 225 | ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat); |
218 | nilfs_transaction_end(inode->i_sb, 0); | 226 | up_read(&nilfs->ns_segctor_sem); |
219 | if (ret < 0) | 227 | if (ret < 0) |
220 | return ret; | 228 | return ret; |
221 | 229 | ||
@@ -236,16 +244,17 @@ static int nilfs_ioctl_get_vinfo(struct inode *inode, struct file *filp, | |||
236 | { | 244 | { |
237 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; | 245 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; |
238 | struct nilfs_argv argv; | 246 | struct nilfs_argv argv; |
239 | struct nilfs_transaction_info ti; | ||
240 | int ret; | 247 | int ret; |
241 | 248 | ||
242 | if (copy_from_user(&argv, argp, sizeof(argv))) | 249 | if (copy_from_user(&argv, argp, sizeof(argv))) |
243 | return -EFAULT; | 250 | return -EFAULT; |
244 | 251 | ||
245 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 252 | down_read(&nilfs->ns_segctor_sem); |
246 | ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), | 253 | ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), |
247 | nilfs_ioctl_do_get_vinfo); | 254 | nilfs_ioctl_do_get_vinfo); |
248 | nilfs_transaction_end(inode->i_sb, 0); | 255 | up_read(&nilfs->ns_segctor_sem); |
256 | if (ret < 0) | ||
257 | return ret; | ||
249 | 258 | ||
250 | if (copy_to_user(argp, &argv, sizeof(argv))) | 259 | if (copy_to_user(argp, &argv, sizeof(argv))) |
251 | ret = -EFAULT; | 260 | ret = -EFAULT; |
@@ -280,16 +289,17 @@ static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp, | |||
280 | { | 289 | { |
281 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; | 290 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; |
282 | struct nilfs_argv argv; | 291 | struct nilfs_argv argv; |
283 | struct nilfs_transaction_info ti; | ||
284 | int ret; | 292 | int ret; |
285 | 293 | ||
286 | if (copy_from_user(&argv, argp, sizeof(argv))) | 294 | if (copy_from_user(&argv, argp, sizeof(argv))) |
287 | return -EFAULT; | 295 | return -EFAULT; |
288 | 296 | ||
289 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 297 | down_read(&nilfs->ns_segctor_sem); |
290 | ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), | 298 | ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), |
291 | nilfs_ioctl_do_get_bdescs); | 299 | nilfs_ioctl_do_get_bdescs); |
292 | nilfs_transaction_end(inode->i_sb, 0); | 300 | up_read(&nilfs->ns_segctor_sem); |
301 | if (ret < 0) | ||
302 | return ret; | ||
293 | 303 | ||
294 | if (copy_to_user(argp, &argv, sizeof(argv))) | 304 | if (copy_to_user(argp, &argv, sizeof(argv))) |
295 | ret = -EFAULT; | 305 | ret = -EFAULT; |