diff options
| author | Nick Piggin <npiggin@suse.de> | 2007-10-16 04:25:24 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:42:58 -0400 |
| commit | f2b6a16eb8f5b4851b01625a21e0c71207c2ce77 (patch) | |
| tree | 6903e844147078f8f8d817b17eada5a65b4a7623 /fs/affs | |
| parent | b4585729f0b616c95aacafb8c8cb5e1af0d4242f (diff) | |
fs: affs convert to new aops
Cc: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/affs')
| -rw-r--r-- | fs/affs/file.c | 101 |
1 files changed, 59 insertions, 42 deletions
diff --git a/fs/affs/file.c b/fs/affs/file.c index c314a35f09..6e0c939920 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c | |||
| @@ -395,25 +395,33 @@ static int affs_writepage(struct page *page, struct writeback_control *wbc) | |||
| 395 | { | 395 | { |
| 396 | return block_write_full_page(page, affs_get_block, wbc); | 396 | return block_write_full_page(page, affs_get_block, wbc); |
| 397 | } | 397 | } |
| 398 | |||
| 398 | static int affs_readpage(struct file *file, struct page *page) | 399 | static int affs_readpage(struct file *file, struct page *page) |
| 399 | { | 400 | { |
| 400 | return block_read_full_page(page, affs_get_block); | 401 | return block_read_full_page(page, affs_get_block); |
| 401 | } | 402 | } |
| 402 | static int affs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) | 403 | |
| 404 | static int affs_write_begin(struct file *file, struct address_space *mapping, | ||
| 405 | loff_t pos, unsigned len, unsigned flags, | ||
| 406 | struct page **pagep, void **fsdata) | ||
| 403 | { | 407 | { |
| 404 | return cont_prepare_write(page, from, to, affs_get_block, | 408 | *pagep = NULL; |
| 405 | &AFFS_I(page->mapping->host)->mmu_private); | 409 | return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
| 410 | affs_get_block, | ||
| 411 | &AFFS_I(mapping->host)->mmu_private); | ||
| 406 | } | 412 | } |
| 413 | |||
| 407 | static sector_t _affs_bmap(struct address_space *mapping, sector_t block) | 414 | static sector_t _affs_bmap(struct address_space *mapping, sector_t block) |
| 408 | { | 415 | { |
| 409 | return generic_block_bmap(mapping,block,affs_get_block); | 416 | return generic_block_bmap(mapping,block,affs_get_block); |
| 410 | } | 417 | } |
| 418 | |||
| 411 | const struct address_space_operations affs_aops = { | 419 | const struct address_space_operations affs_aops = { |
| 412 | .readpage = affs_readpage, | 420 | .readpage = affs_readpage, |
| 413 | .writepage = affs_writepage, | 421 | .writepage = affs_writepage, |
| 414 | .sync_page = block_sync_page, | 422 | .sync_page = block_sync_page, |
| 415 | .prepare_write = affs_prepare_write, | 423 | .write_begin = affs_write_begin, |
| 416 | .commit_write = generic_commit_write, | 424 | .write_end = generic_write_end, |
| 417 | .bmap = _affs_bmap | 425 | .bmap = _affs_bmap |
| 418 | }; | 426 | }; |
| 419 | 427 | ||
| @@ -603,54 +611,65 @@ affs_readpage_ofs(struct file *file, struct page *page) | |||
| 603 | return err; | 611 | return err; |
| 604 | } | 612 | } |
| 605 | 613 | ||
| 606 | static int affs_prepare_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to) | 614 | static int affs_write_begin_ofs(struct file *file, struct address_space *mapping, |
| 615 | loff_t pos, unsigned len, unsigned flags, | ||
| 616 | struct page **pagep, void **fsdata) | ||
| 607 | { | 617 | { |
| 608 | struct inode *inode = page->mapping->host; | 618 | struct inode *inode = mapping->host; |
| 609 | u32 size, offset; | 619 | struct page *page; |
| 610 | u32 tmp; | 620 | pgoff_t index; |
| 611 | int err = 0; | 621 | int err = 0; |
| 612 | 622 | ||
| 613 | pr_debug("AFFS: prepare_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to); | 623 | pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len); |
| 614 | offset = page->index << PAGE_CACHE_SHIFT; | 624 | if (pos > AFFS_I(inode)->mmu_private) { |
| 615 | if (offset + from > AFFS_I(inode)->mmu_private) { | 625 | /* XXX: this probably leaves a too-big i_size in case of |
| 616 | err = affs_extent_file_ofs(inode, offset + from); | 626 | * failure. Should really be updating i_size at write_end time |
| 627 | */ | ||
| 628 | err = affs_extent_file_ofs(inode, pos); | ||
| 617 | if (err) | 629 | if (err) |
| 618 | return err; | 630 | return err; |
| 619 | } | 631 | } |
| 620 | size = inode->i_size; | 632 | |
| 633 | index = pos >> PAGE_CACHE_SHIFT; | ||
| 634 | page = __grab_cache_page(mapping, index); | ||
| 635 | if (!page) | ||
| 636 | return -ENOMEM; | ||
| 637 | *pagep = page; | ||
| 621 | 638 | ||
| 622 | if (PageUptodate(page)) | 639 | if (PageUptodate(page)) |
| 623 | return 0; | 640 | return 0; |
| 624 | 641 | ||
| 625 | if (from) { | 642 | /* XXX: inefficient but safe in the face of short writes */ |
| 626 | err = affs_do_readpage_ofs(file, page, 0, from); | 643 | err = affs_do_readpage_ofs(file, page, 0, PAGE_CACHE_SIZE); |
| 627 | if (err) | 644 | if (err) { |
| 628 | return err; | 645 | unlock_page(page); |
| 629 | } | 646 | page_cache_release(page); |
| 630 | if (to < PAGE_CACHE_SIZE) { | ||
| 631 | zero_user_page(page, to, PAGE_CACHE_SIZE - to, KM_USER0); | ||
| 632 | if (size > offset + to) { | ||
| 633 | if (size < offset + PAGE_CACHE_SIZE) | ||
| 634 | tmp = size & ~PAGE_CACHE_MASK; | ||
| 635 | else | ||
| 636 | tmp = PAGE_CACHE_SIZE; | ||
| 637 | err = affs_do_readpage_ofs(file, page, to, tmp); | ||
| 638 | } | ||
| 639 | } | 647 | } |
| 640 | return err; | 648 | return err; |
| 641 | } | 649 | } |
| 642 | 650 | ||
| 643 | static int affs_commit_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to) | 651 | static int affs_write_end_ofs(struct file *file, struct address_space *mapping, |
| 652 | loff_t pos, unsigned len, unsigned copied, | ||
| 653 | struct page *page, void *fsdata) | ||
| 644 | { | 654 | { |
| 645 | struct inode *inode = page->mapping->host; | 655 | struct inode *inode = mapping->host; |
| 646 | struct super_block *sb = inode->i_sb; | 656 | struct super_block *sb = inode->i_sb; |
| 647 | struct buffer_head *bh, *prev_bh; | 657 | struct buffer_head *bh, *prev_bh; |
| 648 | char *data; | 658 | char *data; |
| 649 | u32 bidx, boff, bsize; | 659 | u32 bidx, boff, bsize; |
| 660 | unsigned from, to; | ||
| 650 | u32 tmp; | 661 | u32 tmp; |
| 651 | int written; | 662 | int written; |
| 652 | 663 | ||
| 653 | pr_debug("AFFS: commit_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to); | 664 | from = pos & (PAGE_CACHE_SIZE - 1); |
| 665 | to = pos + len; | ||
| 666 | /* | ||
| 667 | * XXX: not sure if this can handle short copies (len < copied), but | ||
| 668 | * we don't have to, because the page should always be uptodate here, | ||
| 669 | * due to write_begin. | ||
| 670 | */ | ||
| 671 | |||
| 672 | pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len); | ||
| 654 | bsize = AFFS_SB(sb)->s_data_blksize; | 673 | bsize = AFFS_SB(sb)->s_data_blksize; |
| 655 | data = page_address(page); | 674 | data = page_address(page); |
| 656 | 675 | ||
| @@ -748,6 +767,9 @@ done: | |||
| 748 | if (tmp > inode->i_size) | 767 | if (tmp > inode->i_size) |
| 749 | inode->i_size = AFFS_I(inode)->mmu_private = tmp; | 768 | inode->i_size = AFFS_I(inode)->mmu_private = tmp; |
| 750 | 769 | ||
| 770 | unlock_page(page); | ||
| 771 | page_cache_release(page); | ||
| 772 | |||
| 751 | return written; | 773 | return written; |
| 752 | 774 | ||
| 753 | out: | 775 | out: |
| @@ -761,8 +783,8 @@ const struct address_space_operations affs_aops_ofs = { | |||
| 761 | .readpage = affs_readpage_ofs, | 783 | .readpage = affs_readpage_ofs, |
| 762 | //.writepage = affs_writepage_ofs, | 784 | //.writepage = affs_writepage_ofs, |
| 763 | //.sync_page = affs_sync_page_ofs, | 785 | //.sync_page = affs_sync_page_ofs, |
| 764 | .prepare_write = affs_prepare_write_ofs, | 786 | .write_begin = affs_write_begin_ofs, |
| 765 | .commit_write = affs_commit_write_ofs | 787 | .write_end = affs_write_end_ofs |
| 766 | }; | 788 | }; |
| 767 | 789 | ||
| 768 | /* Free any preallocated blocks. */ | 790 | /* Free any preallocated blocks. */ |
| @@ -805,18 +827,13 @@ affs_truncate(struct inode *inode) | |||
| 805 | if (inode->i_size > AFFS_I(inode)->mmu_private) { | 827 | if (inode->i_size > AFFS_I(inode)->mmu_private) { |
| 806 | struct address_space *mapping = inode->i_mapping; | 828 | struct address_space *mapping = inode->i_mapping; |
| 807 | struct page *page; | 829 | struct page *page; |
| 808 | u32 size = inode->i_size - 1; | 830 | void *fsdata; |
| 831 | u32 size = inode->i_size; | ||
| 809 | int res; | 832 | int res; |
| 810 | 833 | ||
| 811 | page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT); | 834 | res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata); |
| 812 | if (!page) | ||
| 813 | return; | ||
| 814 | size = (size & (PAGE_CACHE_SIZE - 1)) + 1; | ||
| 815 | res = mapping->a_ops->prepare_write(NULL, page, size, size); | ||
| 816 | if (!res) | 835 | if (!res) |
| 817 | res = mapping->a_ops->commit_write(NULL, page, size, size); | 836 | res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata); |
| 818 | unlock_page(page); | ||
| 819 | page_cache_release(page); | ||
| 820 | mark_inode_dirty(inode); | 837 | mark_inode_dirty(inode); |
| 821 | return; | 838 | return; |
| 822 | } else if (inode->i_size == AFFS_I(inode)->mmu_private) | 839 | } else if (inode->i_size == AFFS_I(inode)->mmu_private) |
