diff options
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 136 |
1 files changed, 53 insertions, 83 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index e998009c0f52..b306e25f0f07 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -228,29 +228,13 @@ xfs_map_blocks( | |||
228 | return -error; | 228 | return -error; |
229 | } | 229 | } |
230 | 230 | ||
231 | /* | 231 | STATIC inline int |
232 | * Finds the corresponding mapping in block @map array of the | 232 | xfs_iomap_valid( |
233 | * given @offset within a @page. | ||
234 | */ | ||
235 | STATIC xfs_iomap_t * | ||
236 | xfs_offset_to_map( | ||
237 | struct page *page, | ||
238 | xfs_iomap_t *iomapp, | 233 | xfs_iomap_t *iomapp, |
239 | unsigned long offset) | 234 | loff_t offset) |
240 | { | 235 | { |
241 | xfs_off_t full_offset; /* offset from start of file */ | 236 | return offset >= iomapp->iomap_offset && |
242 | 237 | offset < iomapp->iomap_offset + iomapp->iomap_bsize; | |
243 | ASSERT(offset < PAGE_CACHE_SIZE); | ||
244 | |||
245 | full_offset = page->index; /* NB: using 64bit number */ | ||
246 | full_offset <<= PAGE_CACHE_SHIFT; /* offset from file start */ | ||
247 | full_offset += offset; /* offset from page start */ | ||
248 | |||
249 | if (full_offset < iomapp->iomap_offset) | ||
250 | return NULL; | ||
251 | if (iomapp->iomap_offset + (iomapp->iomap_bsize -1) >= full_offset) | ||
252 | return iomapp; | ||
253 | return NULL; | ||
254 | } | 238 | } |
255 | 239 | ||
256 | /* | 240 | /* |
@@ -461,31 +445,23 @@ xfs_add_to_ioend( | |||
461 | 445 | ||
462 | STATIC void | 446 | STATIC void |
463 | xfs_map_at_offset( | 447 | xfs_map_at_offset( |
464 | struct page *page, | ||
465 | struct buffer_head *bh, | 448 | struct buffer_head *bh, |
466 | unsigned long offset, | 449 | loff_t offset, |
467 | int block_bits, | 450 | int block_bits, |
468 | xfs_iomap_t *iomapp, | 451 | xfs_iomap_t *iomapp) |
469 | xfs_ioend_t *ioend) | ||
470 | { | 452 | { |
471 | xfs_daddr_t bn; | 453 | xfs_daddr_t bn; |
472 | xfs_off_t delta; | ||
473 | int sector_shift; | 454 | int sector_shift; |
474 | 455 | ||
475 | ASSERT(!(iomapp->iomap_flags & IOMAP_HOLE)); | 456 | ASSERT(!(iomapp->iomap_flags & IOMAP_HOLE)); |
476 | ASSERT(!(iomapp->iomap_flags & IOMAP_DELAY)); | 457 | ASSERT(!(iomapp->iomap_flags & IOMAP_DELAY)); |
477 | ASSERT(iomapp->iomap_bn != IOMAP_DADDR_NULL); | 458 | ASSERT(iomapp->iomap_bn != IOMAP_DADDR_NULL); |
478 | 459 | ||
479 | delta = page->index; | ||
480 | delta <<= PAGE_CACHE_SHIFT; | ||
481 | delta += offset; | ||
482 | delta -= iomapp->iomap_offset; | ||
483 | delta >>= block_bits; | ||
484 | |||
485 | sector_shift = block_bits - BBSHIFT; | 460 | sector_shift = block_bits - BBSHIFT; |
486 | bn = iomapp->iomap_bn >> sector_shift; | 461 | bn = (iomapp->iomap_bn >> sector_shift) + |
487 | bn += delta; | 462 | ((offset - iomapp->iomap_offset) >> block_bits); |
488 | BUG_ON(!bn && !(iomapp->iomap_flags & IOMAP_REALTIME)); | 463 | |
464 | ASSERT(bn || (iomapp->iomap_flags & IOMAP_REALTIME)); | ||
489 | ASSERT((bn << sector_shift) >= iomapp->iomap_bn); | 465 | ASSERT((bn << sector_shift) >= iomapp->iomap_bn); |
490 | 466 | ||
491 | lock_buffer(bh); | 467 | lock_buffer(bh); |
@@ -569,8 +545,10 @@ xfs_probe_unmapped_cluster( | |||
569 | if (tindex == tlast) { | 545 | if (tindex == tlast) { |
570 | pg_offset = | 546 | pg_offset = |
571 | i_size_read(inode) & (PAGE_CACHE_SIZE - 1); | 547 | i_size_read(inode) & (PAGE_CACHE_SIZE - 1); |
572 | if (!pg_offset) | 548 | if (!pg_offset) { |
549 | done = 1; | ||
573 | break; | 550 | break; |
551 | } | ||
574 | } else | 552 | } else |
575 | pg_offset = PAGE_CACHE_SIZE; | 553 | pg_offset = PAGE_CACHE_SIZE; |
576 | 554 | ||
@@ -585,6 +563,7 @@ xfs_probe_unmapped_cluster( | |||
585 | } | 563 | } |
586 | 564 | ||
587 | total += len; | 565 | total += len; |
566 | tindex++; | ||
588 | } | 567 | } |
589 | 568 | ||
590 | pagevec_release(&pvec); | 569 | pagevec_release(&pvec); |
@@ -638,19 +617,19 @@ xfs_convert_page( | |||
638 | struct inode *inode, | 617 | struct inode *inode, |
639 | struct page *page, | 618 | struct page *page, |
640 | loff_t tindex, | 619 | loff_t tindex, |
641 | xfs_iomap_t *iomapp, | 620 | xfs_iomap_t *mp, |
642 | xfs_ioend_t **ioendp, | 621 | xfs_ioend_t **ioendp, |
643 | struct writeback_control *wbc, | 622 | struct writeback_control *wbc, |
644 | int startio, | 623 | int startio, |
645 | int all_bh) | 624 | int all_bh) |
646 | { | 625 | { |
647 | struct buffer_head *bh, *head; | 626 | struct buffer_head *bh, *head; |
648 | xfs_iomap_t *mp = iomapp, *tmp; | ||
649 | unsigned long p_offset, end_offset; | 627 | unsigned long p_offset, end_offset; |
650 | unsigned int type; | 628 | unsigned int type; |
651 | int bbits = inode->i_blkbits; | 629 | int bbits = inode->i_blkbits; |
652 | int len, page_dirty; | 630 | int len, page_dirty; |
653 | int count = 0, done = 0, uptodate = 1; | 631 | int count = 0, done = 0, uptodate = 1; |
632 | xfs_off_t f_offset = page_offset(page); | ||
654 | 633 | ||
655 | if (page->index != tindex) | 634 | if (page->index != tindex) |
656 | goto fail; | 635 | goto fail; |
@@ -703,15 +682,15 @@ xfs_convert_page( | |||
703 | } | 682 | } |
704 | continue; | 683 | continue; |
705 | } | 684 | } |
706 | tmp = xfs_offset_to_map(page, mp, p_offset); | 685 | |
707 | if (!tmp) { | 686 | if (!xfs_iomap_valid(mp, f_offset + p_offset)) { |
708 | done = 1; | 687 | done = 1; |
709 | continue; | 688 | continue; |
710 | } | 689 | } |
711 | ASSERT(!(tmp->iomap_flags & IOMAP_HOLE)); | 690 | ASSERT(!(mp->iomap_flags & IOMAP_HOLE)); |
712 | ASSERT(!(tmp->iomap_flags & IOMAP_DELAY)); | 691 | ASSERT(!(mp->iomap_flags & IOMAP_DELAY)); |
713 | 692 | ||
714 | xfs_map_at_offset(page, bh, p_offset, bbits, tmp, *ioendp); | 693 | xfs_map_at_offset(bh, f_offset + p_offset, bbits, mp); |
715 | if (startio) { | 694 | if (startio) { |
716 | xfs_add_to_ioend(inode, bh, p_offset, | 695 | xfs_add_to_ioend(inode, bh, p_offset, |
717 | type, ioendp, done); | 696 | type, ioendp, done); |
@@ -805,15 +784,14 @@ xfs_page_state_convert( | |||
805 | int unmapped) /* also implies page uptodate */ | 784 | int unmapped) /* also implies page uptodate */ |
806 | { | 785 | { |
807 | struct buffer_head *bh, *head; | 786 | struct buffer_head *bh, *head; |
808 | xfs_iomap_t *iomp, iomap; | 787 | xfs_iomap_t iomap; |
809 | xfs_ioend_t *ioend = NULL, *iohead = NULL; | 788 | xfs_ioend_t *ioend = NULL, *iohead = NULL; |
810 | loff_t offset; | 789 | loff_t offset; |
811 | unsigned long p_offset = 0; | 790 | unsigned long p_offset = 0; |
812 | unsigned int type; | 791 | unsigned int type; |
813 | __uint64_t end_offset; | 792 | __uint64_t end_offset; |
814 | pgoff_t end_index, last_index, tlast; | 793 | pgoff_t end_index, last_index, tlast; |
815 | int flags, len, err, done = 1; | 794 | int flags, len, err, iomap_valid = 0, uptodate = 1; |
816 | int uptodate = 1; | ||
817 | int page_dirty, count = 0, trylock_flag = 0; | 795 | int page_dirty, count = 0, trylock_flag = 0; |
818 | 796 | ||
819 | /* wait for other IO threads? */ | 797 | /* wait for other IO threads? */ |
@@ -854,11 +832,9 @@ xfs_page_state_convert( | |||
854 | p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE; | 832 | p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE; |
855 | page_dirty = p_offset / len; | 833 | page_dirty = p_offset / len; |
856 | 834 | ||
857 | iomp = NULL; | ||
858 | bh = head = page_buffers(page); | 835 | bh = head = page_buffers(page); |
859 | offset = page_offset(page); | 836 | offset = page_offset(page); |
860 | 837 | ||
861 | /* TODO: fix up "done" variable and iomap pointer (boolean) */ | ||
862 | /* TODO: cleanup count and page_dirty */ | 838 | /* TODO: cleanup count and page_dirty */ |
863 | 839 | ||
864 | do { | 840 | do { |
@@ -867,14 +843,16 @@ xfs_page_state_convert( | |||
867 | if (!buffer_uptodate(bh)) | 843 | if (!buffer_uptodate(bh)) |
868 | uptodate = 0; | 844 | uptodate = 0; |
869 | if (!(PageUptodate(page) || buffer_uptodate(bh)) && !startio) { | 845 | if (!(PageUptodate(page) || buffer_uptodate(bh)) && !startio) { |
870 | done = 1; | 846 | /* |
847 | * the iomap is actually still valid, but the ioend | ||
848 | * isn't. shouldn't happen too often. | ||
849 | */ | ||
850 | iomap_valid = 0; | ||
871 | continue; | 851 | continue; |
872 | } | 852 | } |
873 | 853 | ||
874 | if (iomp) { | 854 | if (iomap_valid) |
875 | iomp = xfs_offset_to_map(page, &iomap, p_offset); | 855 | iomap_valid = xfs_iomap_valid(&iomap, offset); |
876 | done = (iomp == NULL); | ||
877 | } | ||
878 | 856 | ||
879 | /* | 857 | /* |
880 | * First case, map an unwritten extent and prepare for | 858 | * First case, map an unwritten extent and prepare for |
@@ -894,22 +872,20 @@ xfs_page_state_convert( | |||
894 | flags |= trylock_flag; | 872 | flags |= trylock_flag; |
895 | } | 873 | } |
896 | 874 | ||
897 | if (!iomp) { | 875 | if (!iomap_valid) { |
898 | done = 1; | ||
899 | err = xfs_map_blocks(inode, offset, len, &iomap, | 876 | err = xfs_map_blocks(inode, offset, len, &iomap, |
900 | flags); | 877 | flags); |
901 | if (err) | 878 | if (err) |
902 | goto error; | 879 | goto error; |
903 | iomp = xfs_offset_to_map(page, &iomap, | 880 | iomap_valid = xfs_iomap_valid(&iomap, offset); |
904 | p_offset); | ||
905 | done = (iomp == NULL); | ||
906 | } | 881 | } |
907 | if (iomp) { | 882 | if (iomap_valid) { |
908 | xfs_map_at_offset(page, bh, p_offset, | 883 | xfs_map_at_offset(bh, offset, |
909 | inode->i_blkbits, iomp, ioend); | 884 | inode->i_blkbits, &iomap); |
910 | if (startio) { | 885 | if (startio) { |
911 | xfs_add_to_ioend(inode, bh, p_offset, | 886 | xfs_add_to_ioend(inode, bh, p_offset, |
912 | type, &ioend, done); | 887 | type, &ioend, |
888 | !iomap_valid); | ||
913 | } else { | 889 | } else { |
914 | set_buffer_dirty(bh); | 890 | set_buffer_dirty(bh); |
915 | unlock_buffer(bh); | 891 | unlock_buffer(bh); |
@@ -917,8 +893,6 @@ xfs_page_state_convert( | |||
917 | } | 893 | } |
918 | page_dirty--; | 894 | page_dirty--; |
919 | count++; | 895 | count++; |
920 | } else { | ||
921 | done = 1; | ||
922 | } | 896 | } |
923 | } else if ((buffer_uptodate(bh) || PageUptodate(page)) && | 897 | } else if ((buffer_uptodate(bh) || PageUptodate(page)) && |
924 | (unmapped || startio)) { | 898 | (unmapped || startio)) { |
@@ -931,7 +905,7 @@ xfs_page_state_convert( | |||
931 | * was found, and we are in a path where we | 905 | * was found, and we are in a path where we |
932 | * need to write the whole page out. | 906 | * need to write the whole page out. |
933 | */ | 907 | */ |
934 | if (!iomp) { | 908 | if (!iomap_valid) { |
935 | int size; | 909 | int size; |
936 | 910 | ||
937 | size = xfs_probe_unmapped_cluster( | 911 | size = xfs_probe_unmapped_cluster( |
@@ -939,21 +913,19 @@ xfs_page_state_convert( | |||
939 | err = xfs_map_blocks(inode, offset, | 913 | err = xfs_map_blocks(inode, offset, |
940 | size, &iomap, | 914 | size, &iomap, |
941 | BMAPI_WRITE|BMAPI_MMAP); | 915 | BMAPI_WRITE|BMAPI_MMAP); |
942 | if (err) { | 916 | if (err) |
943 | goto error; | 917 | goto error; |
944 | } | 918 | iomap_valid = xfs_iomap_valid(&iomap, |
945 | iomp = xfs_offset_to_map(page, &iomap, | 919 | offset); |
946 | p_offset); | ||
947 | done = (iomp == NULL); | ||
948 | } | 920 | } |
949 | if (iomp) { | 921 | if (iomap_valid) { |
950 | xfs_map_at_offset(page, bh, p_offset, | 922 | xfs_map_at_offset(bh, offset, |
951 | inode->i_blkbits, iomp, | 923 | inode->i_blkbits, |
952 | ioend); | 924 | &iomap); |
953 | if (startio) { | 925 | if (startio) { |
954 | xfs_add_to_ioend(inode, | 926 | xfs_add_to_ioend(inode, |
955 | bh, p_offset, type, | 927 | bh, p_offset, type, |
956 | &ioend, done); | 928 | &ioend, !iomap_valid); |
957 | } else { | 929 | } else { |
958 | set_buffer_dirty(bh); | 930 | set_buffer_dirty(bh); |
959 | unlock_buffer(bh); | 931 | unlock_buffer(bh); |
@@ -961,8 +933,6 @@ xfs_page_state_convert( | |||
961 | } | 933 | } |
962 | page_dirty--; | 934 | page_dirty--; |
963 | count++; | 935 | count++; |
964 | } else { | ||
965 | done = 1; | ||
966 | } | 936 | } |
967 | } else if (startio) { | 937 | } else if (startio) { |
968 | if (buffer_uptodate(bh) && | 938 | if (buffer_uptodate(bh) && |
@@ -970,14 +940,14 @@ xfs_page_state_convert( | |||
970 | ASSERT(buffer_mapped(bh)); | 940 | ASSERT(buffer_mapped(bh)); |
971 | xfs_add_to_ioend(inode, | 941 | xfs_add_to_ioend(inode, |
972 | bh, p_offset, type, | 942 | bh, p_offset, type, |
973 | &ioend, done); | 943 | &ioend, !iomap_valid); |
974 | page_dirty--; | 944 | page_dirty--; |
975 | count++; | 945 | count++; |
976 | } else { | 946 | } else { |
977 | done = 1; | 947 | iomap_valid = 0; |
978 | } | 948 | } |
979 | } else { | 949 | } else { |
980 | done = 1; | 950 | iomap_valid = 0; |
981 | } | 951 | } |
982 | } | 952 | } |
983 | 953 | ||
@@ -992,11 +962,11 @@ xfs_page_state_convert( | |||
992 | if (startio) | 962 | if (startio) |
993 | xfs_start_page_writeback(page, wbc, 1, count); | 963 | xfs_start_page_writeback(page, wbc, 1, count); |
994 | 964 | ||
995 | if (ioend && iomp && !done) { | 965 | if (ioend && iomap_valid) { |
996 | offset = (iomp->iomap_offset + iomp->iomap_bsize - 1) >> | 966 | offset = (iomap.iomap_offset + iomap.iomap_bsize - 1) >> |
997 | PAGE_CACHE_SHIFT; | 967 | PAGE_CACHE_SHIFT; |
998 | tlast = min_t(pgoff_t, offset, last_index); | 968 | tlast = min_t(pgoff_t, offset, last_index); |
999 | xfs_cluster_write(inode, page->index + 1, iomp, &ioend, | 969 | xfs_cluster_write(inode, page->index + 1, &iomap, &ioend, |
1000 | wbc, startio, unmapped, tlast); | 970 | wbc, startio, unmapped, tlast); |
1001 | } | 971 | } |
1002 | 972 | ||