diff options
| -rw-r--r-- | fs/ocfs2/aops.c | 83 |
1 files changed, 34 insertions, 49 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index f1d1c342ce01..3d7c082a8f58 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -391,31 +391,28 @@ out: | |||
| 391 | static int ocfs2_commit_write(struct file *file, struct page *page, | 391 | static int ocfs2_commit_write(struct file *file, struct page *page, |
| 392 | unsigned from, unsigned to) | 392 | unsigned from, unsigned to) |
| 393 | { | 393 | { |
| 394 | int ret, extending = 0, locklevel = 0; | 394 | int ret; |
| 395 | loff_t new_i_size; | ||
| 396 | struct buffer_head *di_bh = NULL; | 395 | struct buffer_head *di_bh = NULL; |
| 397 | struct inode *inode = page->mapping->host; | 396 | struct inode *inode = page->mapping->host; |
| 398 | struct ocfs2_journal_handle *handle = NULL; | 397 | struct ocfs2_journal_handle *handle = NULL; |
| 398 | struct ocfs2_dinode *di; | ||
| 399 | 399 | ||
| 400 | mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to); | 400 | mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to); |
| 401 | 401 | ||
| 402 | /* NOTE: ocfs2_file_aio_write has ensured that it's safe for | 402 | /* NOTE: ocfs2_file_aio_write has ensured that it's safe for |
| 403 | * us to sample inode->i_size here without the metadata lock: | 403 | * us to continue here without rechecking the I/O against |
| 404 | * changed inode values. | ||
| 404 | * | 405 | * |
| 405 | * 1) We're currently holding the inode alloc lock, so no | 406 | * 1) We're currently holding the inode alloc lock, so no |
| 406 | * nodes can change it underneath us. | 407 | * nodes can change it underneath us. |
| 407 | * | 408 | * |
| 408 | * 2) We've had to take the metadata lock at least once | 409 | * 2) We've had to take the metadata lock at least once |
| 409 | * already to check for extending writes, hence insuring | 410 | * already to check for extending writes, suid removal, etc. |
| 410 | * that our current copy is also up to date. | 411 | * The meta data update code then ensures that we don't get a |
| 412 | * stale inode allocation image (i_size, i_clusters, etc). | ||
| 411 | */ | 413 | */ |
| 412 | new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; | ||
| 413 | if (new_i_size > i_size_read(inode)) { | ||
| 414 | extending = 1; | ||
| 415 | locklevel = 1; | ||
| 416 | } | ||
| 417 | 414 | ||
| 418 | ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, locklevel, page); | 415 | ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, 1, page); |
| 419 | if (ret != 0) { | 416 | if (ret != 0) { |
| 420 | mlog_errno(ret); | 417 | mlog_errno(ret); |
| 421 | goto out; | 418 | goto out; |
| @@ -427,23 +424,20 @@ static int ocfs2_commit_write(struct file *file, struct page *page, | |||
| 427 | goto out_unlock_meta; | 424 | goto out_unlock_meta; |
| 428 | } | 425 | } |
| 429 | 426 | ||
| 430 | if (extending) { | 427 | handle = ocfs2_start_walk_page_trans(inode, page, from, to); |
| 431 | handle = ocfs2_start_walk_page_trans(inode, page, from, to); | 428 | if (IS_ERR(handle)) { |
| 432 | if (IS_ERR(handle)) { | 429 | ret = PTR_ERR(handle); |
| 433 | ret = PTR_ERR(handle); | 430 | goto out_unlock_data; |
| 434 | handle = NULL; | 431 | } |
| 435 | goto out_unlock_data; | ||
| 436 | } | ||
| 437 | 432 | ||
| 438 | /* Mark our buffer early. We'd rather catch this error up here | 433 | /* Mark our buffer early. We'd rather catch this error up here |
| 439 | * as opposed to after a successful commit_write which would | 434 | * as opposed to after a successful commit_write which would |
| 440 | * require us to set back inode->i_size. */ | 435 | * require us to set back inode->i_size. */ |
| 441 | ret = ocfs2_journal_access(handle, inode, di_bh, | 436 | ret = ocfs2_journal_access(handle, inode, di_bh, |
| 442 | OCFS2_JOURNAL_ACCESS_WRITE); | 437 | OCFS2_JOURNAL_ACCESS_WRITE); |
| 443 | if (ret < 0) { | 438 | if (ret < 0) { |
| 444 | mlog_errno(ret); | 439 | mlog_errno(ret); |
| 445 | goto out_commit; | 440 | goto out_commit; |
| 446 | } | ||
| 447 | } | 441 | } |
| 448 | 442 | ||
| 449 | /* might update i_size */ | 443 | /* might update i_size */ |
| @@ -453,37 +447,28 @@ static int ocfs2_commit_write(struct file *file, struct page *page, | |||
| 453 | goto out_commit; | 447 | goto out_commit; |
| 454 | } | 448 | } |
| 455 | 449 | ||
| 456 | if (extending) { | 450 | di = (struct ocfs2_dinode *)di_bh->b_data; |
| 457 | loff_t size = (u64) i_size_read(inode); | ||
| 458 | struct ocfs2_dinode *di = | ||
| 459 | (struct ocfs2_dinode *)di_bh->b_data; | ||
| 460 | 451 | ||
| 461 | /* ocfs2_mark_inode_dirty is too heavy to use here. */ | 452 | /* ocfs2_mark_inode_dirty() is too heavy to use here. */ |
| 462 | inode->i_blocks = ocfs2_align_bytes_to_sectors(size); | 453 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
| 463 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | 454 | di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec); |
| 455 | di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); | ||
| 464 | 456 | ||
| 465 | di->i_size = cpu_to_le64(size); | 457 | inode->i_blocks = ocfs2_align_bytes_to_sectors((u64)(i_size_read(inode))); |
| 466 | di->i_ctime = di->i_mtime = | 458 | di->i_size = cpu_to_le64((u64)i_size_read(inode)); |
| 467 | cpu_to_le64(inode->i_mtime.tv_sec); | ||
| 468 | di->i_ctime_nsec = di->i_mtime_nsec = | ||
| 469 | cpu_to_le32(inode->i_mtime.tv_nsec); | ||
| 470 | 459 | ||
| 471 | ret = ocfs2_journal_dirty(handle, di_bh); | 460 | ret = ocfs2_journal_dirty(handle, di_bh); |
| 472 | if (ret < 0) { | 461 | if (ret < 0) { |
| 473 | mlog_errno(ret); | 462 | mlog_errno(ret); |
| 474 | goto out_commit; | 463 | goto out_commit; |
| 475 | } | ||
| 476 | } | 464 | } |
| 477 | 465 | ||
| 478 | BUG_ON(extending && (i_size_read(inode) != new_i_size)); | ||
| 479 | |||
| 480 | out_commit: | 466 | out_commit: |
| 481 | if (handle) | 467 | ocfs2_commit_trans(handle); |
| 482 | ocfs2_commit_trans(handle); | ||
| 483 | out_unlock_data: | 468 | out_unlock_data: |
| 484 | ocfs2_data_unlock(inode, 1); | 469 | ocfs2_data_unlock(inode, 1); |
| 485 | out_unlock_meta: | 470 | out_unlock_meta: |
| 486 | ocfs2_meta_unlock(inode, locklevel); | 471 | ocfs2_meta_unlock(inode, 1); |
| 487 | out: | 472 | out: |
| 488 | if (di_bh) | 473 | if (di_bh) |
| 489 | brelse(di_bh); | 474 | brelse(di_bh); |
