aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-04-06 22:01:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 11:31:17 -0400
commit47420c799830d4676e544dbec56b2a7f787528f5 (patch)
treedd61f6c96942b07f762129c893d9cbbbeff60735 /fs
parenta2e7d2df82cafb76f76809ddf6e2caa8afe4f75e (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')
-rw-r--r--fs/nilfs2/inode.c23
-rw-r--r--fs/nilfs2/ioctl.c58
-rw-r--r--fs/nilfs2/mdt.c5
-rw-r--r--fs/nilfs2/namei.c74
-rw-r--r--fs/nilfs2/nilfs.h3
-rw-r--r--fs/nilfs2/segment.c43
-rw-r--r--fs/nilfs2/the_nilfs.h4
7 files changed, 135 insertions, 75 deletions
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 289d1798decb..4bf1e2c5bac6 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -77,7 +77,6 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff,
77 goto out; 77 goto out;
78 err = nilfs_bmap_insert(ii->i_bmap, (unsigned long)blkoff, 78 err = nilfs_bmap_insert(ii->i_bmap, (unsigned long)blkoff,
79 (unsigned long)bh_result); 79 (unsigned long)bh_result);
80 nilfs_transaction_end(inode->i_sb, !err);
81 if (unlikely(err != 0)) { 80 if (unlikely(err != 0)) {
82 if (err == -EEXIST) { 81 if (err == -EEXIST) {
83 /* 82 /*
@@ -100,8 +99,10 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff,
100 inode->i_ino); 99 inode->i_ino);
101 err = -EIO; 100 err = -EIO;
102 } 101 }
102 nilfs_transaction_abort(inode->i_sb);
103 goto out; 103 goto out;
104 } 104 }
105 nilfs_transaction_commit(inode->i_sb); /* never fails */
105 /* Error handling should be detailed */ 106 /* Error handling should be detailed */
106 set_buffer_new(bh_result); 107 set_buffer_new(bh_result);
107 map_bh(bh_result, inode->i_sb, 0); /* dbn must be changed 108 map_bh(bh_result, inode->i_sb, 0); /* dbn must be changed
@@ -203,7 +204,7 @@ static int nilfs_write_begin(struct file *file, struct address_space *mapping,
203 err = block_write_begin(file, mapping, pos, len, flags, pagep, 204 err = block_write_begin(file, mapping, pos, len, flags, pagep,
204 fsdata, nilfs_get_block); 205 fsdata, nilfs_get_block);
205 if (unlikely(err)) 206 if (unlikely(err))
206 nilfs_transaction_end(inode->i_sb, 0); 207 nilfs_transaction_abort(inode->i_sb);
207 return err; 208 return err;
208} 209}
209 210
@@ -221,7 +222,7 @@ static int nilfs_write_end(struct file *file, struct address_space *mapping,
221 copied = generic_write_end(file, mapping, pos, len, copied, page, 222 copied = generic_write_end(file, mapping, pos, len, copied, page,
222 fsdata); 223 fsdata);
223 nilfs_set_file_dirty(NILFS_SB(inode->i_sb), inode, nr_dirty); 224 nilfs_set_file_dirty(NILFS_SB(inode->i_sb), inode, nr_dirty);
224 err = nilfs_transaction_end(inode->i_sb, 1); 225 err = nilfs_transaction_commit(inode->i_sb);
225 return err ? : copied; 226 return err ? : copied;
226} 227}
227 228
@@ -641,7 +642,7 @@ void nilfs_truncate(struct inode *inode)
641 nilfs_set_transaction_flag(NILFS_TI_SYNC); 642 nilfs_set_transaction_flag(NILFS_TI_SYNC);
642 643
643 nilfs_set_file_dirty(NILFS_SB(sb), inode, 0); 644 nilfs_set_file_dirty(NILFS_SB(sb), inode, 0);
644 nilfs_transaction_end(sb, 1); 645 nilfs_transaction_commit(sb);
645 /* May construct a logical segment and may fail in sync mode. 646 /* May construct a logical segment and may fail in sync mode.
646 But truncate has no return value. */ 647 But truncate has no return value. */
647} 648}
@@ -669,7 +670,7 @@ void nilfs_delete_inode(struct inode *inode)
669 /* nilfs_free_inode() marks inode buffer dirty */ 670 /* nilfs_free_inode() marks inode buffer dirty */
670 if (IS_SYNC(inode)) 671 if (IS_SYNC(inode))
671 nilfs_set_transaction_flag(NILFS_TI_SYNC); 672 nilfs_set_transaction_flag(NILFS_TI_SYNC);
672 nilfs_transaction_end(sb, 1); 673 nilfs_transaction_commit(sb);
673 /* May construct a logical segment and may fail in sync mode. 674 /* May construct a logical segment and may fail in sync mode.
674 But delete_inode has no return value. */ 675 But delete_inode has no return value. */
675} 676}
@@ -679,7 +680,7 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
679 struct nilfs_transaction_info ti; 680 struct nilfs_transaction_info ti;
680 struct inode *inode = dentry->d_inode; 681 struct inode *inode = dentry->d_inode;
681 struct super_block *sb = inode->i_sb; 682 struct super_block *sb = inode->i_sb;
682 int err, err2; 683 int err;
683 684
684 err = inode_change_ok(inode, iattr); 685 err = inode_change_ok(inode, iattr);
685 if (err) 686 if (err)
@@ -691,8 +692,12 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
691 err = inode_setattr(inode, iattr); 692 err = inode_setattr(inode, iattr);
692 if (!err && (iattr->ia_valid & ATTR_MODE)) 693 if (!err && (iattr->ia_valid & ATTR_MODE))
693 err = nilfs_acl_chmod(inode); 694 err = nilfs_acl_chmod(inode);
694 err2 = nilfs_transaction_end(sb, 1); 695 if (likely(!err))
695 return err ? : err2; 696 err = nilfs_transaction_commit(sb);
697 else
698 nilfs_transaction_abort(sb);
699
700 return err;
696} 701}
697 702
698int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode, 703int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode,
@@ -817,5 +822,5 @@ void nilfs_dirty_inode(struct inode *inode)
817 nilfs_transaction_begin(inode->i_sb, &ti, 0); 822 nilfs_transaction_begin(inode->i_sb, &ti, 0);
818 if (likely(inode->i_ino != NILFS_SKETCH_INO)) 823 if (likely(inode->i_ino != NILFS_SKETCH_INO))
819 nilfs_mark_inode_dirty(inode); 824 nilfs_mark_inode_dirty(inode);
820 nilfs_transaction_end(inode->i_sb, 1); /* never fails */ 825 nilfs_transaction_commit(inode->i_sb); /* never fails */
821} 826}
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,
161static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, 170static 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,
208static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, 217static 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;
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index 6ab847578615..e0a632b86feb 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -123,7 +123,10 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
123 brelse(bh); 123 brelse(bh);
124 124
125 failed_unlock: 125 failed_unlock:
126 nilfs_transaction_end(sb, !err); 126 if (likely(!err))
127 err = nilfs_transaction_commit(sb);
128 else
129 nilfs_transaction_abort(sb);
127 if (writer) 130 if (writer)
128 nilfs_put_writer(nilfs); 131 nilfs_put_writer(nilfs);
129 out: 132 out:
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 95d1b29bff3c..df70dadb336f 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -109,7 +109,7 @@ static int nilfs_create(struct inode *dir, struct dentry *dentry, int mode,
109{ 109{
110 struct inode *inode; 110 struct inode *inode;
111 struct nilfs_transaction_info ti; 111 struct nilfs_transaction_info ti;
112 int err, err2; 112 int err;
113 113
114 err = nilfs_transaction_begin(dir->i_sb, &ti, 1); 114 err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
115 if (err) 115 if (err)
@@ -123,8 +123,12 @@ static int nilfs_create(struct inode *dir, struct dentry *dentry, int mode,
123 mark_inode_dirty(inode); 123 mark_inode_dirty(inode);
124 err = nilfs_add_nondir(dentry, inode); 124 err = nilfs_add_nondir(dentry, inode);
125 } 125 }
126 err2 = nilfs_transaction_end(dir->i_sb, !err); 126 if (!err)
127 return err ? : err2; 127 err = nilfs_transaction_commit(dir->i_sb);
128 else
129 nilfs_transaction_abort(dir->i_sb);
130
131 return err;
128} 132}
129 133
130static int 134static int
@@ -132,7 +136,7 @@ nilfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
132{ 136{
133 struct inode *inode; 137 struct inode *inode;
134 struct nilfs_transaction_info ti; 138 struct nilfs_transaction_info ti;
135 int err, err2; 139 int err;
136 140
137 if (!new_valid_dev(rdev)) 141 if (!new_valid_dev(rdev))
138 return -EINVAL; 142 return -EINVAL;
@@ -147,8 +151,12 @@ nilfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
147 mark_inode_dirty(inode); 151 mark_inode_dirty(inode);
148 err = nilfs_add_nondir(dentry, inode); 152 err = nilfs_add_nondir(dentry, inode);
149 } 153 }
150 err2 = nilfs_transaction_end(dir->i_sb, !err); 154 if (!err)
151 return err ? : err2; 155 err = nilfs_transaction_commit(dir->i_sb);
156 else
157 nilfs_transaction_abort(dir->i_sb);
158
159 return err;
152} 160}
153 161
154static int nilfs_symlink(struct inode *dir, struct dentry *dentry, 162static int nilfs_symlink(struct inode *dir, struct dentry *dentry,
@@ -158,7 +166,7 @@ static int nilfs_symlink(struct inode *dir, struct dentry *dentry,
158 struct super_block *sb = dir->i_sb; 166 struct super_block *sb = dir->i_sb;
159 unsigned l = strlen(symname)+1; 167 unsigned l = strlen(symname)+1;
160 struct inode *inode; 168 struct inode *inode;
161 int err, err2; 169 int err;
162 170
163 if (l > sb->s_blocksize) 171 if (l > sb->s_blocksize)
164 return -ENAMETOOLONG; 172 return -ENAMETOOLONG;
@@ -184,8 +192,12 @@ static int nilfs_symlink(struct inode *dir, struct dentry *dentry,
184 192
185 err = nilfs_add_nondir(dentry, inode); 193 err = nilfs_add_nondir(dentry, inode);
186out: 194out:
187 err2 = nilfs_transaction_end(dir->i_sb, !err); 195 if (!err)
188 return err ? : err2; 196 err = nilfs_transaction_commit(dir->i_sb);
197 else
198 nilfs_transaction_abort(dir->i_sb);
199
200 return err;
189 201
190out_fail: 202out_fail:
191 inode_dec_link_count(inode); 203 inode_dec_link_count(inode);
@@ -198,7 +210,7 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
198{ 210{
199 struct inode *inode = old_dentry->d_inode; 211 struct inode *inode = old_dentry->d_inode;
200 struct nilfs_transaction_info ti; 212 struct nilfs_transaction_info ti;
201 int err, err2; 213 int err;
202 214
203 if (inode->i_nlink >= NILFS_LINK_MAX) 215 if (inode->i_nlink >= NILFS_LINK_MAX)
204 return -EMLINK; 216 return -EMLINK;
@@ -212,15 +224,19 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
212 atomic_inc(&inode->i_count); 224 atomic_inc(&inode->i_count);
213 225
214 err = nilfs_add_nondir(dentry, inode); 226 err = nilfs_add_nondir(dentry, inode);
215 err2 = nilfs_transaction_end(dir->i_sb, !err); 227 if (!err)
216 return err ? : err2; 228 err = nilfs_transaction_commit(dir->i_sb);
229 else
230 nilfs_transaction_abort(dir->i_sb);
231
232 return err;
217} 233}
218 234
219static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 235static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
220{ 236{
221 struct inode *inode; 237 struct inode *inode;
222 struct nilfs_transaction_info ti; 238 struct nilfs_transaction_info ti;
223 int err, err2; 239 int err;
224 240
225 if (dir->i_nlink >= NILFS_LINK_MAX) 241 if (dir->i_nlink >= NILFS_LINK_MAX)
226 return -EMLINK; 242 return -EMLINK;
@@ -252,8 +268,12 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
252 268
253 d_instantiate(dentry, inode); 269 d_instantiate(dentry, inode);
254out: 270out:
255 err2 = nilfs_transaction_end(dir->i_sb, !err); 271 if (!err)
256 return err ? : err2; 272 err = nilfs_transaction_commit(dir->i_sb);
273 else
274 nilfs_transaction_abort(dir->i_sb);
275
276 return err;
257 277
258out_fail: 278out_fail:
259 inode_dec_link_count(inode); 279 inode_dec_link_count(inode);
@@ -270,7 +290,7 @@ static int nilfs_unlink(struct inode *dir, struct dentry *dentry)
270 struct nilfs_dir_entry *de; 290 struct nilfs_dir_entry *de;
271 struct page *page; 291 struct page *page;
272 struct nilfs_transaction_info ti; 292 struct nilfs_transaction_info ti;
273 int err, err2; 293 int err;
274 294
275 err = nilfs_transaction_begin(dir->i_sb, &ti, 0); 295 err = nilfs_transaction_begin(dir->i_sb, &ti, 0);
276 if (err) 296 if (err)
@@ -300,15 +320,19 @@ static int nilfs_unlink(struct inode *dir, struct dentry *dentry)
300 inode_dec_link_count(inode); 320 inode_dec_link_count(inode);
301 err = 0; 321 err = 0;
302out: 322out:
303 err2 = nilfs_transaction_end(dir->i_sb, !err); 323 if (!err)
304 return err ? : err2; 324 err = nilfs_transaction_commit(dir->i_sb);
325 else
326 nilfs_transaction_abort(dir->i_sb);
327
328 return err;
305} 329}
306 330
307static int nilfs_rmdir(struct inode *dir, struct dentry *dentry) 331static int nilfs_rmdir(struct inode *dir, struct dentry *dentry)
308{ 332{
309 struct inode *inode = dentry->d_inode; 333 struct inode *inode = dentry->d_inode;
310 struct nilfs_transaction_info ti; 334 struct nilfs_transaction_info ti;
311 int err, err2; 335 int err;
312 336
313 err = nilfs_transaction_begin(dir->i_sb, &ti, 0); 337 err = nilfs_transaction_begin(dir->i_sb, &ti, 0);
314 if (err) 338 if (err)
@@ -323,8 +347,12 @@ static int nilfs_rmdir(struct inode *dir, struct dentry *dentry)
323 inode_dec_link_count(dir); 347 inode_dec_link_count(dir);
324 } 348 }
325 } 349 }
326 err2 = nilfs_transaction_end(dir->i_sb, !err); 350 if (!err)
327 return err ? : err2; 351 err = nilfs_transaction_commit(dir->i_sb);
352 else
353 nilfs_transaction_abort(dir->i_sb);
354
355 return err;
328} 356}
329 357
330static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, 358static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -404,7 +432,7 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
404 inode_dec_link_count(old_dir); 432 inode_dec_link_count(old_dir);
405 } 433 }
406 434
407 err = nilfs_transaction_end(old_dir->i_sb, 1); 435 err = nilfs_transaction_commit(old_dir->i_sb);
408 return err; 436 return err;
409 437
410out_dir: 438out_dir:
@@ -416,7 +444,7 @@ out_old:
416 kunmap(old_page); 444 kunmap(old_page);
417 page_cache_release(old_page); 445 page_cache_release(old_page);
418out: 446out:
419 nilfs_transaction_end(old_dir->i_sb, 0); 447 nilfs_transaction_abort(old_dir->i_sb);
420 return err; 448 return err;
421} 449}
422 450
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 17458ad4a809..48c070676cc5 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -166,7 +166,8 @@ struct nilfs_transaction_info {
166 166
167int nilfs_transaction_begin(struct super_block *, 167int nilfs_transaction_begin(struct super_block *,
168 struct nilfs_transaction_info *, int); 168 struct nilfs_transaction_info *, int);
169int nilfs_transaction_end(struct super_block *, int); 169int nilfs_transaction_commit(struct super_block *);
170void nilfs_transaction_abort(struct super_block *);
170 171
171static inline void nilfs_set_transaction_flag(unsigned int flag) 172static inline void nilfs_set_transaction_flag(unsigned int flag)
172{ 173{
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index ad65a737aff4..6d66c5cb7b51 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -163,8 +163,8 @@ static int nilfs_prepare_segment_lock(struct nilfs_transaction_info *ti)
163 else { 163 else {
164 /* 164 /*
165 * If journal_info field is occupied by other FS, 165 * If journal_info field is occupied by other FS,
166 * we save it and restore on nilfs_transaction_end(). 166 * it is saved and will be restored on
167 * But this should never happen. 167 * nilfs_transaction_commit().
168 */ 168 */
169 printk(KERN_WARNING 169 printk(KERN_WARNING
170 "NILFS warning: journal info from a different " 170 "NILFS warning: journal info from a different "
@@ -195,7 +195,7 @@ static int nilfs_prepare_segment_lock(struct nilfs_transaction_info *ti)
195 * 195 *
196 * nilfs_transaction_begin() acquires a reader/writer semaphore, called 196 * nilfs_transaction_begin() acquires a reader/writer semaphore, called
197 * the segment semaphore, to make a segment construction and write tasks 197 * the segment semaphore, to make a segment construction and write tasks
198 * exclusive. The function is used with nilfs_transaction_end() in pairs. 198 * exclusive. The function is used with nilfs_transaction_commit() in pairs.
199 * The region enclosed by these two functions can be nested. To avoid a 199 * The region enclosed by these two functions can be nested. To avoid a
200 * deadlock, the semaphore is only acquired or released in the outermost call. 200 * deadlock, the semaphore is only acquired or released in the outermost call.
201 * 201 *
@@ -212,8 +212,6 @@ static int nilfs_prepare_segment_lock(struct nilfs_transaction_info *ti)
212 * 212 *
213 * %-ENOMEM - Insufficient memory available. 213 * %-ENOMEM - Insufficient memory available.
214 * 214 *
215 * %-ERESTARTSYS - Interrupted
216 *
217 * %-ENOSPC - No space left on device 215 * %-ENOSPC - No space left on device
218 */ 216 */
219int nilfs_transaction_begin(struct super_block *sb, 217int nilfs_transaction_begin(struct super_block *sb,
@@ -248,16 +246,17 @@ int nilfs_transaction_begin(struct super_block *sb,
248} 246}
249 247
250/** 248/**
251 * nilfs_transaction_end - end indivisible file operations. 249 * nilfs_transaction_commit - commit indivisible file operations.
252 * @sb: super block 250 * @sb: super block
253 * @commit: commit flag (0 for no change)
254 * 251 *
255 * nilfs_transaction_end() releases the read semaphore which is 252 * nilfs_transaction_commit() releases the read semaphore which is
256 * acquired by nilfs_transaction_begin(). Its releasing is only done 253 * acquired by nilfs_transaction_begin(). This is only performed
257 * in outermost call of this function. If the nilfs_transaction_info 254 * in outermost call of this function. If a commit flag is set,
258 * was allocated dynamically, it is given back to a slab cache. 255 * nilfs_transaction_commit() sets a timer to start the segment
256 * constructor. If a sync flag is set, it starts construction
257 * directly.
259 */ 258 */
260int nilfs_transaction_end(struct super_block *sb, int commit) 259int nilfs_transaction_commit(struct super_block *sb)
261{ 260{
262 struct nilfs_transaction_info *ti = current->journal_info; 261 struct nilfs_transaction_info *ti = current->journal_info;
263 struct nilfs_sb_info *sbi; 262 struct nilfs_sb_info *sbi;
@@ -265,9 +264,7 @@ int nilfs_transaction_end(struct super_block *sb, int commit)
265 int err = 0; 264 int err = 0;
266 265
267 BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); 266 BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
268 267 ti->ti_flags |= NILFS_TI_COMMIT;
269 if (commit)
270 ti->ti_flags |= NILFS_TI_COMMIT;
271 if (ti->ti_count > 0) { 268 if (ti->ti_count > 0) {
272 ti->ti_count--; 269 ti->ti_count--;
273 return 0; 270 return 0;
@@ -291,6 +288,22 @@ int nilfs_transaction_end(struct super_block *sb, int commit)
291 return err; 288 return err;
292} 289}
293 290
291void nilfs_transaction_abort(struct super_block *sb)
292{
293 struct nilfs_transaction_info *ti = current->journal_info;
294
295 BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
296 if (ti->ti_count > 0) {
297 ti->ti_count--;
298 return;
299 }
300 up_read(&NILFS_SB(sb)->s_nilfs->ns_segctor_sem);
301
302 current->journal_info = ti->ti_save;
303 if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)
304 kmem_cache_free(nilfs_transaction_cachep, ti);
305}
306
294void nilfs_relax_pressure_in_lock(struct super_block *sb) 307void nilfs_relax_pressure_in_lock(struct super_block *sb)
295{ 308{
296 struct nilfs_sb_info *sbi = NILFS_SB(sb); 309 struct nilfs_sb_info *sbi = NILFS_SB(sb);
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index dee8d83e0549..9cd3c113f052 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -112,8 +112,8 @@ struct the_nilfs {
112 /* 112 /*
113 * Following fields are dedicated to a writable FS-instance. 113 * Following fields are dedicated to a writable FS-instance.
114 * Except for the period seeking checkpoint, code outside the segment 114 * Except for the period seeking checkpoint, code outside the segment
115 * constructor must lock a segment semaphore with transaction_begin() 115 * constructor must lock a segment semaphore while accessing these
116 * and transaction_end(), when accessing these fields. 116 * fields.
117 * The writable FS-instance is sole during a lifetime of the_nilfs. 117 * The writable FS-instance is sole during a lifetime of the_nilfs.
118 */ 118 */
119 u64 ns_seg_seq; 119 u64 ns_seg_seq;