diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_aops.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 425 |
1 files changed, 173 insertions, 252 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 691f61223ed6..ec7bbb5645b6 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -38,15 +38,6 @@ | |||
38 | #include <linux/pagevec.h> | 38 | #include <linux/pagevec.h> |
39 | #include <linux/writeback.h> | 39 | #include <linux/writeback.h> |
40 | 40 | ||
41 | /* | ||
42 | * Types of I/O for bmap clustering and I/O completion tracking. | ||
43 | */ | ||
44 | enum { | ||
45 | IO_READ, /* mapping for a read */ | ||
46 | IO_DELAY, /* mapping covers delalloc region */ | ||
47 | IO_UNWRITTEN, /* mapping covers allocated but uninitialized data */ | ||
48 | IO_NEW /* just allocated */ | ||
49 | }; | ||
50 | 41 | ||
51 | /* | 42 | /* |
52 | * Prime number of hash buckets since address is used as the key. | 43 | * Prime number of hash buckets since address is used as the key. |
@@ -182,9 +173,6 @@ xfs_setfilesize( | |||
182 | xfs_inode_t *ip = XFS_I(ioend->io_inode); | 173 | xfs_inode_t *ip = XFS_I(ioend->io_inode); |
183 | xfs_fsize_t isize; | 174 | xfs_fsize_t isize; |
184 | 175 | ||
185 | ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG); | ||
186 | ASSERT(ioend->io_type != IO_READ); | ||
187 | |||
188 | if (unlikely(ioend->io_error)) | 176 | if (unlikely(ioend->io_error)) |
189 | return 0; | 177 | return 0; |
190 | 178 | ||
@@ -244,10 +232,8 @@ xfs_end_io( | |||
244 | * We might have to update the on-disk file size after extending | 232 | * We might have to update the on-disk file size after extending |
245 | * writes. | 233 | * writes. |
246 | */ | 234 | */ |
247 | if (ioend->io_type != IO_READ) { | 235 | error = xfs_setfilesize(ioend); |
248 | error = xfs_setfilesize(ioend); | 236 | ASSERT(!error || error == EAGAIN); |
249 | ASSERT(!error || error == EAGAIN); | ||
250 | } | ||
251 | 237 | ||
252 | /* | 238 | /* |
253 | * If we didn't complete processing of the ioend, requeue it to the | 239 | * If we didn't complete processing of the ioend, requeue it to the |
@@ -318,14 +304,63 @@ STATIC int | |||
318 | xfs_map_blocks( | 304 | xfs_map_blocks( |
319 | struct inode *inode, | 305 | struct inode *inode, |
320 | loff_t offset, | 306 | loff_t offset, |
321 | ssize_t count, | ||
322 | struct xfs_bmbt_irec *imap, | 307 | struct xfs_bmbt_irec *imap, |
323 | int flags) | 308 | int type, |
309 | int nonblocking) | ||
324 | { | 310 | { |
325 | int nmaps = 1; | 311 | struct xfs_inode *ip = XFS_I(inode); |
326 | int new = 0; | 312 | struct xfs_mount *mp = ip->i_mount; |
313 | ssize_t count = 1 << inode->i_blkbits; | ||
314 | xfs_fileoff_t offset_fsb, end_fsb; | ||
315 | int error = 0; | ||
316 | int bmapi_flags = XFS_BMAPI_ENTIRE; | ||
317 | int nimaps = 1; | ||
318 | |||
319 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
320 | return -XFS_ERROR(EIO); | ||
321 | |||
322 | if (type == IO_UNWRITTEN) | ||
323 | bmapi_flags |= XFS_BMAPI_IGSTATE; | ||
324 | |||
325 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) { | ||
326 | if (nonblocking) | ||
327 | return -XFS_ERROR(EAGAIN); | ||
328 | xfs_ilock(ip, XFS_ILOCK_SHARED); | ||
329 | } | ||
327 | 330 | ||
328 | return -xfs_iomap(XFS_I(inode), offset, count, flags, imap, &nmaps, &new); | 331 | ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || |
332 | (ip->i_df.if_flags & XFS_IFEXTENTS)); | ||
333 | ASSERT(offset <= mp->m_maxioffset); | ||
334 | |||
335 | if (offset + count > mp->m_maxioffset) | ||
336 | count = mp->m_maxioffset - offset; | ||
337 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); | ||
338 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | ||
339 | error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, | ||
340 | bmapi_flags, NULL, 0, imap, &nimaps, NULL); | ||
341 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
342 | |||
343 | if (error) | ||
344 | return -XFS_ERROR(error); | ||
345 | |||
346 | if (type == IO_DELALLOC && | ||
347 | (!nimaps || isnullstartblock(imap->br_startblock))) { | ||
348 | error = xfs_iomap_write_allocate(ip, offset, count, imap); | ||
349 | if (!error) | ||
350 | trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); | ||
351 | return -XFS_ERROR(error); | ||
352 | } | ||
353 | |||
354 | #ifdef DEBUG | ||
355 | if (type == IO_UNWRITTEN) { | ||
356 | ASSERT(nimaps); | ||
357 | ASSERT(imap->br_startblock != HOLESTARTBLOCK); | ||
358 | ASSERT(imap->br_startblock != DELAYSTARTBLOCK); | ||
359 | } | ||
360 | #endif | ||
361 | if (nimaps) | ||
362 | trace_xfs_map_blocks_found(ip, offset, count, type, imap); | ||
363 | return 0; | ||
329 | } | 364 | } |
330 | 365 | ||
331 | STATIC int | 366 | STATIC int |
@@ -380,26 +415,18 @@ xfs_submit_ioend_bio( | |||
380 | 415 | ||
381 | submit_bio(wbc->sync_mode == WB_SYNC_ALL ? | 416 | submit_bio(wbc->sync_mode == WB_SYNC_ALL ? |
382 | WRITE_SYNC_PLUG : WRITE, bio); | 417 | WRITE_SYNC_PLUG : WRITE, bio); |
383 | ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP)); | ||
384 | bio_put(bio); | ||
385 | } | 418 | } |
386 | 419 | ||
387 | STATIC struct bio * | 420 | STATIC struct bio * |
388 | xfs_alloc_ioend_bio( | 421 | xfs_alloc_ioend_bio( |
389 | struct buffer_head *bh) | 422 | struct buffer_head *bh) |
390 | { | 423 | { |
391 | struct bio *bio; | ||
392 | int nvecs = bio_get_nr_vecs(bh->b_bdev); | 424 | int nvecs = bio_get_nr_vecs(bh->b_bdev); |
393 | 425 | struct bio *bio = bio_alloc(GFP_NOIO, nvecs); | |
394 | do { | ||
395 | bio = bio_alloc(GFP_NOIO, nvecs); | ||
396 | nvecs >>= 1; | ||
397 | } while (!bio); | ||
398 | 426 | ||
399 | ASSERT(bio->bi_private == NULL); | 427 | ASSERT(bio->bi_private == NULL); |
400 | bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); | 428 | bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); |
401 | bio->bi_bdev = bh->b_bdev; | 429 | bio->bi_bdev = bh->b_bdev; |
402 | bio_get(bio); | ||
403 | return bio; | 430 | return bio; |
404 | } | 431 | } |
405 | 432 | ||
@@ -470,9 +497,8 @@ xfs_submit_ioend( | |||
470 | /* Pass 1 - start writeback */ | 497 | /* Pass 1 - start writeback */ |
471 | do { | 498 | do { |
472 | next = ioend->io_list; | 499 | next = ioend->io_list; |
473 | for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) { | 500 | for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) |
474 | xfs_start_buffer_writeback(bh); | 501 | xfs_start_buffer_writeback(bh); |
475 | } | ||
476 | } while ((ioend = next) != NULL); | 502 | } while ((ioend = next) != NULL); |
477 | 503 | ||
478 | /* Pass 2 - submit I/O */ | 504 | /* Pass 2 - submit I/O */ |
@@ -600,117 +626,13 @@ xfs_map_at_offset( | |||
600 | ASSERT(imap->br_startblock != HOLESTARTBLOCK); | 626 | ASSERT(imap->br_startblock != HOLESTARTBLOCK); |
601 | ASSERT(imap->br_startblock != DELAYSTARTBLOCK); | 627 | ASSERT(imap->br_startblock != DELAYSTARTBLOCK); |
602 | 628 | ||
603 | lock_buffer(bh); | ||
604 | xfs_map_buffer(inode, bh, imap, offset); | 629 | xfs_map_buffer(inode, bh, imap, offset); |
605 | bh->b_bdev = xfs_find_bdev_for_inode(inode); | ||
606 | set_buffer_mapped(bh); | 630 | set_buffer_mapped(bh); |
607 | clear_buffer_delay(bh); | 631 | clear_buffer_delay(bh); |
608 | clear_buffer_unwritten(bh); | 632 | clear_buffer_unwritten(bh); |
609 | } | 633 | } |
610 | 634 | ||
611 | /* | 635 | /* |
612 | * Look for a page at index that is suitable for clustering. | ||
613 | */ | ||
614 | STATIC unsigned int | ||
615 | xfs_probe_page( | ||
616 | struct page *page, | ||
617 | unsigned int pg_offset) | ||
618 | { | ||
619 | struct buffer_head *bh, *head; | ||
620 | int ret = 0; | ||
621 | |||
622 | if (PageWriteback(page)) | ||
623 | return 0; | ||
624 | if (!PageDirty(page)) | ||
625 | return 0; | ||
626 | if (!page->mapping) | ||
627 | return 0; | ||
628 | if (!page_has_buffers(page)) | ||
629 | return 0; | ||
630 | |||
631 | bh = head = page_buffers(page); | ||
632 | do { | ||
633 | if (!buffer_uptodate(bh)) | ||
634 | break; | ||
635 | if (!buffer_mapped(bh)) | ||
636 | break; | ||
637 | ret += bh->b_size; | ||
638 | if (ret >= pg_offset) | ||
639 | break; | ||
640 | } while ((bh = bh->b_this_page) != head); | ||
641 | |||
642 | return ret; | ||
643 | } | ||
644 | |||
645 | STATIC size_t | ||
646 | xfs_probe_cluster( | ||
647 | struct inode *inode, | ||
648 | struct page *startpage, | ||
649 | struct buffer_head *bh, | ||
650 | struct buffer_head *head) | ||
651 | { | ||
652 | struct pagevec pvec; | ||
653 | pgoff_t tindex, tlast, tloff; | ||
654 | size_t total = 0; | ||
655 | int done = 0, i; | ||
656 | |||
657 | /* First sum forwards in this page */ | ||
658 | do { | ||
659 | if (!buffer_uptodate(bh) || !buffer_mapped(bh)) | ||
660 | return total; | ||
661 | total += bh->b_size; | ||
662 | } while ((bh = bh->b_this_page) != head); | ||
663 | |||
664 | /* if we reached the end of the page, sum forwards in following pages */ | ||
665 | tlast = i_size_read(inode) >> PAGE_CACHE_SHIFT; | ||
666 | tindex = startpage->index + 1; | ||
667 | |||
668 | /* Prune this back to avoid pathological behavior */ | ||
669 | tloff = min(tlast, startpage->index + 64); | ||
670 | |||
671 | pagevec_init(&pvec, 0); | ||
672 | while (!done && tindex <= tloff) { | ||
673 | unsigned len = min_t(pgoff_t, PAGEVEC_SIZE, tlast - tindex + 1); | ||
674 | |||
675 | if (!pagevec_lookup(&pvec, inode->i_mapping, tindex, len)) | ||
676 | break; | ||
677 | |||
678 | for (i = 0; i < pagevec_count(&pvec); i++) { | ||
679 | struct page *page = pvec.pages[i]; | ||
680 | size_t pg_offset, pg_len = 0; | ||
681 | |||
682 | if (tindex == tlast) { | ||
683 | pg_offset = | ||
684 | i_size_read(inode) & (PAGE_CACHE_SIZE - 1); | ||
685 | if (!pg_offset) { | ||
686 | done = 1; | ||
687 | break; | ||
688 | } | ||
689 | } else | ||
690 | pg_offset = PAGE_CACHE_SIZE; | ||
691 | |||
692 | if (page->index == tindex && trylock_page(page)) { | ||
693 | pg_len = xfs_probe_page(page, pg_offset); | ||
694 | unlock_page(page); | ||
695 | } | ||
696 | |||
697 | if (!pg_len) { | ||
698 | done = 1; | ||
699 | break; | ||
700 | } | ||
701 | |||
702 | total += pg_len; | ||
703 | tindex++; | ||
704 | } | ||
705 | |||
706 | pagevec_release(&pvec); | ||
707 | cond_resched(); | ||
708 | } | ||
709 | |||
710 | return total; | ||
711 | } | ||
712 | |||
713 | /* | ||
714 | * Test if a given page is suitable for writing as part of an unwritten | 636 | * Test if a given page is suitable for writing as part of an unwritten |
715 | * or delayed allocate extent. | 637 | * or delayed allocate extent. |
716 | */ | 638 | */ |
@@ -731,9 +653,9 @@ xfs_is_delayed_page( | |||
731 | if (buffer_unwritten(bh)) | 653 | if (buffer_unwritten(bh)) |
732 | acceptable = (type == IO_UNWRITTEN); | 654 | acceptable = (type == IO_UNWRITTEN); |
733 | else if (buffer_delay(bh)) | 655 | else if (buffer_delay(bh)) |
734 | acceptable = (type == IO_DELAY); | 656 | acceptable = (type == IO_DELALLOC); |
735 | else if (buffer_dirty(bh) && buffer_mapped(bh)) | 657 | else if (buffer_dirty(bh) && buffer_mapped(bh)) |
736 | acceptable = (type == IO_NEW); | 658 | acceptable = (type == IO_OVERWRITE); |
737 | else | 659 | else |
738 | break; | 660 | break; |
739 | } while ((bh = bh->b_this_page) != head); | 661 | } while ((bh = bh->b_this_page) != head); |
@@ -758,8 +680,7 @@ xfs_convert_page( | |||
758 | loff_t tindex, | 680 | loff_t tindex, |
759 | struct xfs_bmbt_irec *imap, | 681 | struct xfs_bmbt_irec *imap, |
760 | xfs_ioend_t **ioendp, | 682 | xfs_ioend_t **ioendp, |
761 | struct writeback_control *wbc, | 683 | struct writeback_control *wbc) |
762 | int all_bh) | ||
763 | { | 684 | { |
764 | struct buffer_head *bh, *head; | 685 | struct buffer_head *bh, *head; |
765 | xfs_off_t end_offset; | 686 | xfs_off_t end_offset; |
@@ -814,37 +735,30 @@ xfs_convert_page( | |||
814 | continue; | 735 | continue; |
815 | } | 736 | } |
816 | 737 | ||
817 | if (buffer_unwritten(bh) || buffer_delay(bh)) { | 738 | if (buffer_unwritten(bh) || buffer_delay(bh) || |
739 | buffer_mapped(bh)) { | ||
818 | if (buffer_unwritten(bh)) | 740 | if (buffer_unwritten(bh)) |
819 | type = IO_UNWRITTEN; | 741 | type = IO_UNWRITTEN; |
742 | else if (buffer_delay(bh)) | ||
743 | type = IO_DELALLOC; | ||
820 | else | 744 | else |
821 | type = IO_DELAY; | 745 | type = IO_OVERWRITE; |
822 | 746 | ||
823 | if (!xfs_imap_valid(inode, imap, offset)) { | 747 | if (!xfs_imap_valid(inode, imap, offset)) { |
824 | done = 1; | 748 | done = 1; |
825 | continue; | 749 | continue; |
826 | } | 750 | } |
827 | 751 | ||
828 | ASSERT(imap->br_startblock != HOLESTARTBLOCK); | 752 | lock_buffer(bh); |
829 | ASSERT(imap->br_startblock != DELAYSTARTBLOCK); | 753 | if (type != IO_OVERWRITE) |
830 | 754 | xfs_map_at_offset(inode, bh, imap, offset); | |
831 | xfs_map_at_offset(inode, bh, imap, offset); | ||
832 | xfs_add_to_ioend(inode, bh, offset, type, | 755 | xfs_add_to_ioend(inode, bh, offset, type, |
833 | ioendp, done); | 756 | ioendp, done); |
834 | 757 | ||
835 | page_dirty--; | 758 | page_dirty--; |
836 | count++; | 759 | count++; |
837 | } else { | 760 | } else { |
838 | type = IO_NEW; | 761 | done = 1; |
839 | if (buffer_mapped(bh) && all_bh) { | ||
840 | lock_buffer(bh); | ||
841 | xfs_add_to_ioend(inode, bh, offset, | ||
842 | type, ioendp, done); | ||
843 | count++; | ||
844 | page_dirty--; | ||
845 | } else { | ||
846 | done = 1; | ||
847 | } | ||
848 | } | 762 | } |
849 | } while (offset += len, (bh = bh->b_this_page) != head); | 763 | } while (offset += len, (bh = bh->b_this_page) != head); |
850 | 764 | ||
@@ -876,7 +790,6 @@ xfs_cluster_write( | |||
876 | struct xfs_bmbt_irec *imap, | 790 | struct xfs_bmbt_irec *imap, |
877 | xfs_ioend_t **ioendp, | 791 | xfs_ioend_t **ioendp, |
878 | struct writeback_control *wbc, | 792 | struct writeback_control *wbc, |
879 | int all_bh, | ||
880 | pgoff_t tlast) | 793 | pgoff_t tlast) |
881 | { | 794 | { |
882 | struct pagevec pvec; | 795 | struct pagevec pvec; |
@@ -891,7 +804,7 @@ xfs_cluster_write( | |||
891 | 804 | ||
892 | for (i = 0; i < pagevec_count(&pvec); i++) { | 805 | for (i = 0; i < pagevec_count(&pvec); i++) { |
893 | done = xfs_convert_page(inode, pvec.pages[i], tindex++, | 806 | done = xfs_convert_page(inode, pvec.pages[i], tindex++, |
894 | imap, ioendp, wbc, all_bh); | 807 | imap, ioendp, wbc); |
895 | if (done) | 808 | if (done) |
896 | break; | 809 | break; |
897 | } | 810 | } |
@@ -935,7 +848,7 @@ xfs_aops_discard_page( | |||
935 | struct buffer_head *bh, *head; | 848 | struct buffer_head *bh, *head; |
936 | loff_t offset = page_offset(page); | 849 | loff_t offset = page_offset(page); |
937 | 850 | ||
938 | if (!xfs_is_delayed_page(page, IO_DELAY)) | 851 | if (!xfs_is_delayed_page(page, IO_DELALLOC)) |
939 | goto out_invalidate; | 852 | goto out_invalidate; |
940 | 853 | ||
941 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 854 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) |
@@ -1002,10 +915,10 @@ xfs_vm_writepage( | |||
1002 | unsigned int type; | 915 | unsigned int type; |
1003 | __uint64_t end_offset; | 916 | __uint64_t end_offset; |
1004 | pgoff_t end_index, last_index; | 917 | pgoff_t end_index, last_index; |
1005 | ssize_t size, len; | 918 | ssize_t len; |
1006 | int flags, err, imap_valid = 0, uptodate = 1; | 919 | int err, imap_valid = 0, uptodate = 1; |
1007 | int count = 0; | 920 | int count = 0; |
1008 | int all_bh = 0; | 921 | int nonblocking = 0; |
1009 | 922 | ||
1010 | trace_xfs_writepage(inode, page, 0); | 923 | trace_xfs_writepage(inode, page, 0); |
1011 | 924 | ||
@@ -1056,10 +969,14 @@ xfs_vm_writepage( | |||
1056 | 969 | ||
1057 | bh = head = page_buffers(page); | 970 | bh = head = page_buffers(page); |
1058 | offset = page_offset(page); | 971 | offset = page_offset(page); |
1059 | flags = BMAPI_READ; | 972 | type = IO_OVERWRITE; |
1060 | type = IO_NEW; | 973 | |
974 | if (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking) | ||
975 | nonblocking = 1; | ||
1061 | 976 | ||
1062 | do { | 977 | do { |
978 | int new_ioend = 0; | ||
979 | |||
1063 | if (offset >= end_offset) | 980 | if (offset >= end_offset) |
1064 | break; | 981 | break; |
1065 | if (!buffer_uptodate(bh)) | 982 | if (!buffer_uptodate(bh)) |
@@ -1076,90 +993,54 @@ xfs_vm_writepage( | |||
1076 | continue; | 993 | continue; |
1077 | } | 994 | } |
1078 | 995 | ||
1079 | if (imap_valid) | 996 | if (buffer_unwritten(bh)) { |
1080 | imap_valid = xfs_imap_valid(inode, &imap, offset); | 997 | if (type != IO_UNWRITTEN) { |
1081 | |||
1082 | if (buffer_unwritten(bh) || buffer_delay(bh)) { | ||
1083 | int new_ioend = 0; | ||
1084 | |||
1085 | /* | ||
1086 | * Make sure we don't use a read-only iomap | ||
1087 | */ | ||
1088 | if (flags == BMAPI_READ) | ||
1089 | imap_valid = 0; | ||
1090 | |||
1091 | if (buffer_unwritten(bh)) { | ||
1092 | type = IO_UNWRITTEN; | 998 | type = IO_UNWRITTEN; |
1093 | flags = BMAPI_WRITE | BMAPI_IGNSTATE; | 999 | imap_valid = 0; |
1094 | } else if (buffer_delay(bh)) { | ||
1095 | type = IO_DELAY; | ||
1096 | flags = BMAPI_ALLOCATE; | ||
1097 | |||
1098 | if (wbc->sync_mode == WB_SYNC_NONE) | ||
1099 | flags |= BMAPI_TRYLOCK; | ||
1100 | } | ||
1101 | |||
1102 | if (!imap_valid) { | ||
1103 | /* | ||
1104 | * If we didn't have a valid mapping then we | ||
1105 | * need to ensure that we put the new mapping | ||
1106 | * in a new ioend structure. This needs to be | ||
1107 | * done to ensure that the ioends correctly | ||
1108 | * reflect the block mappings at io completion | ||
1109 | * for unwritten extent conversion. | ||
1110 | */ | ||
1111 | new_ioend = 1; | ||
1112 | err = xfs_map_blocks(inode, offset, len, | ||
1113 | &imap, flags); | ||
1114 | if (err) | ||
1115 | goto error; | ||
1116 | imap_valid = xfs_imap_valid(inode, &imap, | ||
1117 | offset); | ||
1118 | } | 1000 | } |
1119 | if (imap_valid) { | 1001 | } else if (buffer_delay(bh)) { |
1120 | xfs_map_at_offset(inode, bh, &imap, offset); | 1002 | if (type != IO_DELALLOC) { |
1121 | xfs_add_to_ioend(inode, bh, offset, type, | 1003 | type = IO_DELALLOC; |
1122 | &ioend, new_ioend); | 1004 | imap_valid = 0; |
1123 | count++; | ||
1124 | } | 1005 | } |
1125 | } else if (buffer_uptodate(bh)) { | 1006 | } else if (buffer_uptodate(bh)) { |
1126 | /* | 1007 | if (type != IO_OVERWRITE) { |
1127 | * we got here because the buffer is already mapped. | 1008 | type = IO_OVERWRITE; |
1128 | * That means it must already have extents allocated | 1009 | imap_valid = 0; |
1129 | * underneath it. Map the extent by reading it. | ||
1130 | */ | ||
1131 | if (!imap_valid || flags != BMAPI_READ) { | ||
1132 | flags = BMAPI_READ; | ||
1133 | size = xfs_probe_cluster(inode, page, bh, head); | ||
1134 | err = xfs_map_blocks(inode, offset, size, | ||
1135 | &imap, flags); | ||
1136 | if (err) | ||
1137 | goto error; | ||
1138 | imap_valid = xfs_imap_valid(inode, &imap, | ||
1139 | offset); | ||
1140 | } | 1010 | } |
1011 | } else { | ||
1012 | if (PageUptodate(page)) { | ||
1013 | ASSERT(buffer_mapped(bh)); | ||
1014 | imap_valid = 0; | ||
1015 | } | ||
1016 | continue; | ||
1017 | } | ||
1141 | 1018 | ||
1019 | if (imap_valid) | ||
1020 | imap_valid = xfs_imap_valid(inode, &imap, offset); | ||
1021 | if (!imap_valid) { | ||
1142 | /* | 1022 | /* |
1143 | * We set the type to IO_NEW in case we are doing a | 1023 | * If we didn't have a valid mapping then we need to |
1144 | * small write at EOF that is extending the file but | 1024 | * put the new mapping into a separate ioend structure. |
1145 | * without needing an allocation. We need to update the | 1025 | * This ensures non-contiguous extents always have |
1146 | * file size on I/O completion in this case so it is | 1026 | * separate ioends, which is particularly important |
1147 | * the same case as having just allocated a new extent | 1027 | * for unwritten extent conversion at I/O completion |
1148 | * that we are writing into for the first time. | 1028 | * time. |
1149 | */ | 1029 | */ |
1150 | type = IO_NEW; | 1030 | new_ioend = 1; |
1151 | if (trylock_buffer(bh)) { | 1031 | err = xfs_map_blocks(inode, offset, &imap, type, |
1152 | if (imap_valid) | 1032 | nonblocking); |
1153 | all_bh = 1; | 1033 | if (err) |
1154 | xfs_add_to_ioend(inode, bh, offset, type, | 1034 | goto error; |
1155 | &ioend, !imap_valid); | 1035 | imap_valid = xfs_imap_valid(inode, &imap, offset); |
1156 | count++; | 1036 | } |
1157 | } else { | 1037 | if (imap_valid) { |
1158 | imap_valid = 0; | 1038 | lock_buffer(bh); |
1159 | } | 1039 | if (type != IO_OVERWRITE) |
1160 | } else if (PageUptodate(page)) { | 1040 | xfs_map_at_offset(inode, bh, &imap, offset); |
1161 | ASSERT(buffer_mapped(bh)); | 1041 | xfs_add_to_ioend(inode, bh, offset, type, &ioend, |
1162 | imap_valid = 0; | 1042 | new_ioend); |
1043 | count++; | ||
1163 | } | 1044 | } |
1164 | 1045 | ||
1165 | if (!iohead) | 1046 | if (!iohead) |
@@ -1188,7 +1069,7 @@ xfs_vm_writepage( | |||
1188 | end_index = last_index; | 1069 | end_index = last_index; |
1189 | 1070 | ||
1190 | xfs_cluster_write(inode, page->index + 1, &imap, &ioend, | 1071 | xfs_cluster_write(inode, page->index + 1, &imap, &ioend, |
1191 | wbc, all_bh, end_index); | 1072 | wbc, end_index); |
1192 | } | 1073 | } |
1193 | 1074 | ||
1194 | if (iohead) | 1075 | if (iohead) |
@@ -1257,13 +1138,19 @@ __xfs_get_blocks( | |||
1257 | int create, | 1138 | int create, |
1258 | int direct) | 1139 | int direct) |
1259 | { | 1140 | { |
1260 | int flags = create ? BMAPI_WRITE : BMAPI_READ; | 1141 | struct xfs_inode *ip = XFS_I(inode); |
1142 | struct xfs_mount *mp = ip->i_mount; | ||
1143 | xfs_fileoff_t offset_fsb, end_fsb; | ||
1144 | int error = 0; | ||
1145 | int lockmode = 0; | ||
1261 | struct xfs_bmbt_irec imap; | 1146 | struct xfs_bmbt_irec imap; |
1147 | int nimaps = 1; | ||
1262 | xfs_off_t offset; | 1148 | xfs_off_t offset; |
1263 | ssize_t size; | 1149 | ssize_t size; |
1264 | int nimap = 1; | ||
1265 | int new = 0; | 1150 | int new = 0; |
1266 | int error; | 1151 | |
1152 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
1153 | return -XFS_ERROR(EIO); | ||
1267 | 1154 | ||
1268 | offset = (xfs_off_t)iblock << inode->i_blkbits; | 1155 | offset = (xfs_off_t)iblock << inode->i_blkbits; |
1269 | ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); | 1156 | ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); |
@@ -1272,15 +1159,45 @@ __xfs_get_blocks( | |||
1272 | if (!create && direct && offset >= i_size_read(inode)) | 1159 | if (!create && direct && offset >= i_size_read(inode)) |
1273 | return 0; | 1160 | return 0; |
1274 | 1161 | ||
1275 | if (direct && create) | 1162 | if (create) { |
1276 | flags |= BMAPI_DIRECT; | 1163 | lockmode = XFS_ILOCK_EXCL; |
1164 | xfs_ilock(ip, lockmode); | ||
1165 | } else { | ||
1166 | lockmode = xfs_ilock_map_shared(ip); | ||
1167 | } | ||
1168 | |||
1169 | ASSERT(offset <= mp->m_maxioffset); | ||
1170 | if (offset + size > mp->m_maxioffset) | ||
1171 | size = mp->m_maxioffset - offset; | ||
1172 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); | ||
1173 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | ||
1277 | 1174 | ||
1278 | error = xfs_iomap(XFS_I(inode), offset, size, flags, &imap, &nimap, | 1175 | error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, |
1279 | &new); | 1176 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, &nimaps, NULL); |
1280 | if (error) | 1177 | if (error) |
1281 | return -error; | 1178 | goto out_unlock; |
1282 | if (nimap == 0) | 1179 | |
1283 | return 0; | 1180 | if (create && |
1181 | (!nimaps || | ||
1182 | (imap.br_startblock == HOLESTARTBLOCK || | ||
1183 | imap.br_startblock == DELAYSTARTBLOCK))) { | ||
1184 | if (direct) { | ||
1185 | error = xfs_iomap_write_direct(ip, offset, size, | ||
1186 | &imap, nimaps); | ||
1187 | } else { | ||
1188 | error = xfs_iomap_write_delay(ip, offset, size, &imap); | ||
1189 | } | ||
1190 | if (error) | ||
1191 | goto out_unlock; | ||
1192 | |||
1193 | trace_xfs_get_blocks_alloc(ip, offset, size, 0, &imap); | ||
1194 | } else if (nimaps) { | ||
1195 | trace_xfs_get_blocks_found(ip, offset, size, 0, &imap); | ||
1196 | } else { | ||
1197 | trace_xfs_get_blocks_notfound(ip, offset, size); | ||
1198 | goto out_unlock; | ||
1199 | } | ||
1200 | xfs_iunlock(ip, lockmode); | ||
1284 | 1201 | ||
1285 | if (imap.br_startblock != HOLESTARTBLOCK && | 1202 | if (imap.br_startblock != HOLESTARTBLOCK && |
1286 | imap.br_startblock != DELAYSTARTBLOCK) { | 1203 | imap.br_startblock != DELAYSTARTBLOCK) { |
@@ -1347,6 +1264,10 @@ __xfs_get_blocks( | |||
1347 | } | 1264 | } |
1348 | 1265 | ||
1349 | return 0; | 1266 | return 0; |
1267 | |||
1268 | out_unlock: | ||
1269 | xfs_iunlock(ip, lockmode); | ||
1270 | return -error; | ||
1350 | } | 1271 | } |
1351 | 1272 | ||
1352 | int | 1273 | int |
@@ -1434,7 +1355,7 @@ xfs_vm_direct_IO( | |||
1434 | ssize_t ret; | 1355 | ssize_t ret; |
1435 | 1356 | ||
1436 | if (rw & WRITE) { | 1357 | if (rw & WRITE) { |
1437 | iocb->private = xfs_alloc_ioend(inode, IO_NEW); | 1358 | iocb->private = xfs_alloc_ioend(inode, IO_DIRECT); |
1438 | 1359 | ||
1439 | ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, | 1360 | ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, |
1440 | offset, nr_segs, | 1361 | offset, nr_segs, |