aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/segment.c
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/nilfs2/segment.c
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/nilfs2/segment.c')
-rw-r--r--fs/nilfs2/segment.c43
1 files changed, 28 insertions, 15 deletions
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);