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"); |
