diff options
Diffstat (limited to 'fs/gfs2/file.c')
| -rw-r--r-- | fs/gfs2/file.c | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index b2682e073eee..e48310885c48 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
| @@ -617,18 +617,51 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 617 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | 617 | return generic_file_aio_write(iocb, iov, nr_segs, pos); |
| 618 | } | 618 | } |
| 619 | 619 | ||
| 620 | static void empty_write_end(struct page *page, unsigned from, | 620 | static int empty_write_end(struct page *page, unsigned from, |
| 621 | unsigned to) | 621 | unsigned to, int mode) |
| 622 | { | 622 | { |
| 623 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); | 623 | struct inode *inode = page->mapping->host; |
| 624 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 625 | struct buffer_head *bh; | ||
| 626 | unsigned offset, blksize = 1 << inode->i_blkbits; | ||
| 627 | pgoff_t end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; | ||
| 624 | 628 | ||
| 625 | zero_user(page, from, to-from); | 629 | zero_user(page, from, to-from); |
| 626 | mark_page_accessed(page); | 630 | mark_page_accessed(page); |
| 627 | 631 | ||
| 628 | if (!gfs2_is_writeback(ip)) | 632 | if (page->index < end_index || !(mode & FALLOC_FL_KEEP_SIZE)) { |
| 629 | gfs2_page_add_databufs(ip, page, from, to); | 633 | if (!gfs2_is_writeback(ip)) |
| 634 | gfs2_page_add_databufs(ip, page, from, to); | ||
| 635 | |||
| 636 | block_commit_write(page, from, to); | ||
| 637 | return 0; | ||
| 638 | } | ||
| 639 | |||
| 640 | offset = 0; | ||
| 641 | bh = page_buffers(page); | ||
| 642 | while (offset < to) { | ||
| 643 | if (offset >= from) { | ||
| 644 | set_buffer_uptodate(bh); | ||
| 645 | mark_buffer_dirty(bh); | ||
| 646 | clear_buffer_new(bh); | ||
| 647 | write_dirty_buffer(bh, WRITE); | ||
| 648 | } | ||
| 649 | offset += blksize; | ||
| 650 | bh = bh->b_this_page; | ||
| 651 | } | ||
| 630 | 652 | ||
| 631 | block_commit_write(page, from, to); | 653 | offset = 0; |
| 654 | bh = page_buffers(page); | ||
| 655 | while (offset < to) { | ||
| 656 | if (offset >= from) { | ||
| 657 | wait_on_buffer(bh); | ||
| 658 | if (!buffer_uptodate(bh)) | ||
| 659 | return -EIO; | ||
| 660 | } | ||
| 661 | offset += blksize; | ||
| 662 | bh = bh->b_this_page; | ||
| 663 | } | ||
| 664 | return 0; | ||
| 632 | } | 665 | } |
| 633 | 666 | ||
| 634 | static int needs_empty_write(sector_t block, struct inode *inode) | 667 | static int needs_empty_write(sector_t block, struct inode *inode) |
| @@ -643,7 +676,8 @@ static int needs_empty_write(sector_t block, struct inode *inode) | |||
| 643 | return !buffer_mapped(&bh_map); | 676 | return !buffer_mapped(&bh_map); |
| 644 | } | 677 | } |
| 645 | 678 | ||
| 646 | static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | 679 | static int write_empty_blocks(struct page *page, unsigned from, unsigned to, |
| 680 | int mode) | ||
| 647 | { | 681 | { |
| 648 | struct inode *inode = page->mapping->host; | 682 | struct inode *inode = page->mapping->host; |
| 649 | unsigned start, end, next, blksize; | 683 | unsigned start, end, next, blksize; |
| @@ -668,7 +702,9 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | |||
| 668 | gfs2_block_map); | 702 | gfs2_block_map); |
| 669 | if (unlikely(ret)) | 703 | if (unlikely(ret)) |
| 670 | return ret; | 704 | return ret; |
| 671 | empty_write_end(page, start, end); | 705 | ret = empty_write_end(page, start, end, mode); |
| 706 | if (unlikely(ret)) | ||
| 707 | return ret; | ||
| 672 | end = 0; | 708 | end = 0; |
| 673 | } | 709 | } |
| 674 | start = next; | 710 | start = next; |
| @@ -682,7 +718,9 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | |||
| 682 | ret = __block_write_begin(page, start, end - start, gfs2_block_map); | 718 | ret = __block_write_begin(page, start, end - start, gfs2_block_map); |
| 683 | if (unlikely(ret)) | 719 | if (unlikely(ret)) |
| 684 | return ret; | 720 | return ret; |
| 685 | empty_write_end(page, start, end); | 721 | ret = empty_write_end(page, start, end, mode); |
| 722 | if (unlikely(ret)) | ||
| 723 | return ret; | ||
| 686 | } | 724 | } |
| 687 | 725 | ||
| 688 | return 0; | 726 | return 0; |
| @@ -731,7 +769,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, | |||
| 731 | 769 | ||
| 732 | if (curr == end) | 770 | if (curr == end) |
| 733 | to = end_offset; | 771 | to = end_offset; |
| 734 | error = write_empty_blocks(page, from, to); | 772 | error = write_empty_blocks(page, from, to, mode); |
| 735 | if (!error && offset + to > inode->i_size && | 773 | if (!error && offset + to > inode->i_size && |
| 736 | !(mode & FALLOC_FL_KEEP_SIZE)) { | 774 | !(mode & FALLOC_FL_KEEP_SIZE)) { |
| 737 | i_size_write(inode, offset + to); | 775 | i_size_write(inode, offset + to); |
