diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-24 18:11:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-24 18:11:46 -0400 |
commit | dc522adbee91dd17fa31f8e8cf72673fe0e8370e (patch) | |
tree | 3bef22735e85c680c8049b2145ecbeb332f3f59b | |
parent | df3256f9ab7ae2127144de5ba2abca332278a42d (diff) | |
parent | c2b67735e5d3a419e90047b3f4179e54a39637bc (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6:
jbd: Fix comment to match the code in journal_start()
jbd/jbd2: remove obsolete summarise_journal_usage.
jbd: Fix forever sleeping process in do_get_write_access()
ext2: fix error msg when mounting fs with too-large blocksize
jbd: fix fsync() tid wraparound bug
ext3: Fix fs corruption when make_indexed_dir() fails
ext3: Fix lock inversion in ext3_symlink()
-rw-r--r-- | fs/ext2/super.c | 3 | ||||
-rw-r--r-- | fs/ext3/namei.c | 80 | ||||
-rw-r--r-- | fs/jbd/commit.c | 15 | ||||
-rw-r--r-- | fs/jbd/journal.c | 16 | ||||
-rw-r--r-- | fs/jbd/transaction.c | 3 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 6 |
6 files changed, 91 insertions, 32 deletions
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 0a78dae7e2cb..1dd62ed35b85 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -898,7 +898,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
898 | brelse(bh); | 898 | brelse(bh); |
899 | 899 | ||
900 | if (!sb_set_blocksize(sb, blocksize)) { | 900 | if (!sb_set_blocksize(sb, blocksize)) { |
901 | ext2_msg(sb, KERN_ERR, "error: blocksize is too small"); | 901 | ext2_msg(sb, KERN_ERR, |
902 | "error: bad blocksize %d", blocksize); | ||
902 | goto failed_sbi; | 903 | goto failed_sbi; |
903 | } | 904 | } |
904 | 905 | ||
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 32f3b8695859..34b6d9bfc48a 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -1416,10 +1416,19 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1416 | frame->at = entries; | 1416 | frame->at = entries; |
1417 | frame->bh = bh; | 1417 | frame->bh = bh; |
1418 | bh = bh2; | 1418 | bh = bh2; |
1419 | /* | ||
1420 | * Mark buffers dirty here so that if do_split() fails we write a | ||
1421 | * consistent set of buffers to disk. | ||
1422 | */ | ||
1423 | ext3_journal_dirty_metadata(handle, frame->bh); | ||
1424 | ext3_journal_dirty_metadata(handle, bh); | ||
1419 | de = do_split(handle,dir, &bh, frame, &hinfo, &retval); | 1425 | de = do_split(handle,dir, &bh, frame, &hinfo, &retval); |
1420 | dx_release (frames); | 1426 | if (!de) { |
1421 | if (!(de)) | 1427 | ext3_mark_inode_dirty(handle, dir); |
1428 | dx_release(frames); | ||
1422 | return retval; | 1429 | return retval; |
1430 | } | ||
1431 | dx_release(frames); | ||
1423 | 1432 | ||
1424 | return add_dirent_to_buf(handle, dentry, inode, de, bh); | 1433 | return add_dirent_to_buf(handle, dentry, inode, de, bh); |
1425 | } | 1434 | } |
@@ -2189,6 +2198,7 @@ static int ext3_symlink (struct inode * dir, | |||
2189 | handle_t *handle; | 2198 | handle_t *handle; |
2190 | struct inode * inode; | 2199 | struct inode * inode; |
2191 | int l, err, retries = 0; | 2200 | int l, err, retries = 0; |
2201 | int credits; | ||
2192 | 2202 | ||
2193 | l = strlen(symname)+1; | 2203 | l = strlen(symname)+1; |
2194 | if (l > dir->i_sb->s_blocksize) | 2204 | if (l > dir->i_sb->s_blocksize) |
@@ -2196,10 +2206,26 @@ static int ext3_symlink (struct inode * dir, | |||
2196 | 2206 | ||
2197 | dquot_initialize(dir); | 2207 | dquot_initialize(dir); |
2198 | 2208 | ||
2209 | if (l > EXT3_N_BLOCKS * 4) { | ||
2210 | /* | ||
2211 | * For non-fast symlinks, we just allocate inode and put it on | ||
2212 | * orphan list in the first transaction => we need bitmap, | ||
2213 | * group descriptor, sb, inode block, quota blocks. | ||
2214 | */ | ||
2215 | credits = 4 + EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb); | ||
2216 | } else { | ||
2217 | /* | ||
2218 | * Fast symlink. We have to add entry to directory | ||
2219 | * (EXT3_DATA_TRANS_BLOCKS + EXT3_INDEX_EXTRA_TRANS_BLOCKS), | ||
2220 | * allocate new inode (bitmap, group descriptor, inode block, | ||
2221 | * quota blocks, sb is already counted in previous macros). | ||
2222 | */ | ||
2223 | credits = EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + | ||
2224 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + | ||
2225 | EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb); | ||
2226 | } | ||
2199 | retry: | 2227 | retry: |
2200 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + | 2228 | handle = ext3_journal_start(dir, credits); |
2201 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + | ||
2202 | EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); | ||
2203 | if (IS_ERR(handle)) | 2229 | if (IS_ERR(handle)) |
2204 | return PTR_ERR(handle); | 2230 | return PTR_ERR(handle); |
2205 | 2231 | ||
@@ -2211,21 +2237,45 @@ retry: | |||
2211 | if (IS_ERR(inode)) | 2237 | if (IS_ERR(inode)) |
2212 | goto out_stop; | 2238 | goto out_stop; |
2213 | 2239 | ||
2214 | if (l > sizeof (EXT3_I(inode)->i_data)) { | 2240 | if (l > EXT3_N_BLOCKS * 4) { |
2215 | inode->i_op = &ext3_symlink_inode_operations; | 2241 | inode->i_op = &ext3_symlink_inode_operations; |
2216 | ext3_set_aops(inode); | 2242 | ext3_set_aops(inode); |
2217 | /* | 2243 | /* |
2218 | * page_symlink() calls into ext3_prepare/commit_write. | 2244 | * We cannot call page_symlink() with transaction started |
2219 | * We have a transaction open. All is sweetness. It also sets | 2245 | * because it calls into ext3_write_begin() which acquires page |
2220 | * i_size in generic_commit_write(). | 2246 | * lock which ranks below transaction start (and it can also |
2247 | * wait for journal commit if we are running out of space). So | ||
2248 | * we have to stop transaction now and restart it when symlink | ||
2249 | * contents is written. | ||
2250 | * | ||
2251 | * To keep fs consistent in case of crash, we have to put inode | ||
2252 | * to orphan list in the mean time. | ||
2221 | */ | 2253 | */ |
2254 | drop_nlink(inode); | ||
2255 | err = ext3_orphan_add(handle, inode); | ||
2256 | ext3_journal_stop(handle); | ||
2257 | if (err) | ||
2258 | goto err_drop_inode; | ||
2222 | err = __page_symlink(inode, symname, l, 1); | 2259 | err = __page_symlink(inode, symname, l, 1); |
2260 | if (err) | ||
2261 | goto err_drop_inode; | ||
2262 | /* | ||
2263 | * Now inode is being linked into dir (EXT3_DATA_TRANS_BLOCKS | ||
2264 | * + EXT3_INDEX_EXTRA_TRANS_BLOCKS), inode is also modified | ||
2265 | */ | ||
2266 | handle = ext3_journal_start(dir, | ||
2267 | EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + | ||
2268 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 1); | ||
2269 | if (IS_ERR(handle)) { | ||
2270 | err = PTR_ERR(handle); | ||
2271 | goto err_drop_inode; | ||
2272 | } | ||
2273 | inc_nlink(inode); | ||
2274 | err = ext3_orphan_del(handle, inode); | ||
2223 | if (err) { | 2275 | if (err) { |
2276 | ext3_journal_stop(handle); | ||
2224 | drop_nlink(inode); | 2277 | drop_nlink(inode); |
2225 | unlock_new_inode(inode); | 2278 | goto err_drop_inode; |
2226 | ext3_mark_inode_dirty(handle, inode); | ||
2227 | iput (inode); | ||
2228 | goto out_stop; | ||
2229 | } | 2279 | } |
2230 | } else { | 2280 | } else { |
2231 | inode->i_op = &ext3_fast_symlink_inode_operations; | 2281 | inode->i_op = &ext3_fast_symlink_inode_operations; |
@@ -2239,6 +2289,10 @@ out_stop: | |||
2239 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) | 2289 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) |
2240 | goto retry; | 2290 | goto retry; |
2241 | return err; | 2291 | return err; |
2292 | err_drop_inode: | ||
2293 | unlock_new_inode(inode); | ||
2294 | iput(inode); | ||
2295 | return err; | ||
2242 | } | 2296 | } |
2243 | 2297 | ||
2244 | static int ext3_link (struct dentry * old_dentry, | 2298 | static int ext3_link (struct dentry * old_dentry, |
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 69b180459463..72ffa974b0b8 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
@@ -302,12 +302,6 @@ void journal_commit_transaction(journal_t *journal) | |||
302 | * all outstanding updates to complete. | 302 | * all outstanding updates to complete. |
303 | */ | 303 | */ |
304 | 304 | ||
305 | #ifdef COMMIT_STATS | ||
306 | spin_lock(&journal->j_list_lock); | ||
307 | summarise_journal_usage(journal); | ||
308 | spin_unlock(&journal->j_list_lock); | ||
309 | #endif | ||
310 | |||
311 | /* Do we need to erase the effects of a prior journal_flush? */ | 305 | /* Do we need to erase the effects of a prior journal_flush? */ |
312 | if (journal->j_flags & JFS_FLUSHED) { | 306 | if (journal->j_flags & JFS_FLUSHED) { |
313 | jbd_debug(3, "super block updated\n"); | 307 | jbd_debug(3, "super block updated\n"); |
@@ -722,8 +716,13 @@ wait_for_iobuf: | |||
722 | required. */ | 716 | required. */ |
723 | JBUFFER_TRACE(jh, "file as BJ_Forget"); | 717 | JBUFFER_TRACE(jh, "file as BJ_Forget"); |
724 | journal_file_buffer(jh, commit_transaction, BJ_Forget); | 718 | journal_file_buffer(jh, commit_transaction, BJ_Forget); |
725 | /* Wake up any transactions which were waiting for this | 719 | /* |
726 | IO to complete */ | 720 | * Wake up any transactions which were waiting for this |
721 | * IO to complete. The barrier must be here so that changes | ||
722 | * by journal_file_buffer() take effect before wake_up_bit() | ||
723 | * does the waitqueue check. | ||
724 | */ | ||
725 | smp_mb(); | ||
727 | wake_up_bit(&bh->b_state, BH_Unshadow); | 726 | wake_up_bit(&bh->b_state, BH_Unshadow); |
728 | JBUFFER_TRACE(jh, "brelse shadowed buffer"); | 727 | JBUFFER_TRACE(jh, "brelse shadowed buffer"); |
729 | __brelse(bh); | 728 | __brelse(bh); |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index b3713afaaa9e..e2d4285fbe90 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -437,9 +437,12 @@ int __log_space_left(journal_t *journal) | |||
437 | int __log_start_commit(journal_t *journal, tid_t target) | 437 | int __log_start_commit(journal_t *journal, tid_t target) |
438 | { | 438 | { |
439 | /* | 439 | /* |
440 | * Are we already doing a recent enough commit? | 440 | * The only transaction we can possibly wait upon is the |
441 | * currently running transaction (if it exists). Otherwise, | ||
442 | * the target tid must be an old one. | ||
441 | */ | 443 | */ |
442 | if (!tid_geq(journal->j_commit_request, target)) { | 444 | if (journal->j_running_transaction && |
445 | journal->j_running_transaction->t_tid == target) { | ||
443 | /* | 446 | /* |
444 | * We want a new commit: OK, mark the request and wakeup the | 447 | * We want a new commit: OK, mark the request and wakeup the |
445 | * commit thread. We do _not_ do the commit ourselves. | 448 | * commit thread. We do _not_ do the commit ourselves. |
@@ -451,7 +454,14 @@ int __log_start_commit(journal_t *journal, tid_t target) | |||
451 | journal->j_commit_sequence); | 454 | journal->j_commit_sequence); |
452 | wake_up(&journal->j_wait_commit); | 455 | wake_up(&journal->j_wait_commit); |
453 | return 1; | 456 | return 1; |
454 | } | 457 | } else if (!tid_geq(journal->j_commit_request, target)) |
458 | /* This should never happen, but if it does, preserve | ||
459 | the evidence before kjournald goes into a loop and | ||
460 | increments j_commit_sequence beyond all recognition. */ | ||
461 | WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n", | ||
462 | journal->j_commit_request, journal->j_commit_sequence, | ||
463 | target, journal->j_running_transaction ? | ||
464 | journal->j_running_transaction->t_tid : 0); | ||
455 | return 0; | 465 | return 0; |
456 | } | 466 | } |
457 | 467 | ||
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 60d2319651b2..f7ee81a065da 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
@@ -266,7 +266,8 @@ static handle_t *new_handle(int nblocks) | |||
266 | * This function is visible to journal users (like ext3fs), so is not | 266 | * This function is visible to journal users (like ext3fs), so is not |
267 | * called with the journal already locked. | 267 | * called with the journal already locked. |
268 | * | 268 | * |
269 | * Return a pointer to a newly allocated handle, or NULL on failure | 269 | * Return a pointer to a newly allocated handle, or an ERR_PTR() value |
270 | * on failure. | ||
270 | */ | 271 | */ |
271 | handle_t *journal_start(journal_t *journal, int nblocks) | 272 | handle_t *journal_start(journal_t *journal, int nblocks) |
272 | { | 273 | { |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 6e28000a4b21..29148a81c783 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -338,12 +338,6 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
338 | * all outstanding updates to complete. | 338 | * all outstanding updates to complete. |
339 | */ | 339 | */ |
340 | 340 | ||
341 | #ifdef COMMIT_STATS | ||
342 | spin_lock(&journal->j_list_lock); | ||
343 | summarise_journal_usage(journal); | ||
344 | spin_unlock(&journal->j_list_lock); | ||
345 | #endif | ||
346 | |||
347 | /* Do we need to erase the effects of a prior jbd2_journal_flush? */ | 341 | /* Do we need to erase the effects of a prior jbd2_journal_flush? */ |
348 | if (journal->j_flags & JBD2_FLUSHED) { | 342 | if (journal->j_flags & JBD2_FLUSHED) { |
349 | jbd_debug(3, "super block updated\n"); | 343 | jbd_debug(3, "super block updated\n"); |