Btrfs: Subpagesize-blocksize: Get rid of whole page I/O
Subsystems (2)
v3 cover Btrfs: Subpagesize-blocksize: Get rid of whole page I/O
This patchset continues with the work posted earlier at
http://www.mail-archive.com/[email protected]/msg34527.html.
Changes from V1:
1. Remove usage of bio_vec->bv_{len,offset} in end_bio_extent_readpage() and end_bio_extent_writepage().
Changes from V2:
1. Get __extent_writepage() to write only the dirty blocks of a page.
2. Fix "page private not zero on page" warning message which is printed when running xfstests.
Xfstests' generic tests were run on an x86_64 machine with the patches applied.
On multiple runs of the tests with 4k blocksize, 'umount' process would sometimes get blocked indefinitely causing 'hung task detector' to print the function call trace.
For 2k blocksize only a few Xfstests' generic tests pass.
The following is a list of known TODO items which will be implemented in future revisions of this patchset:
1. Remove usage of bvec->{bv_offset, bv_len} from btrfs_csum_one_bio.
2. Remove PAGE_CACHE_SIZE delalloc reservation in btrfs_writepage_fixup_worker().
3. Create separate slab caches for 'extent buffer head' and 'extent buffer'.
4. Add 'leak list' tracking for 'extent buffer' instances.
5. Rename EXTENT_BUFFER_TREE_REF and EXTENT_BUFFER_IN_TREE to EXTENT_BUFFER_HEAD_TREE_REF and EXTENT_BUFFER_HEAD_IN_TREE respectively.
6. Get Xfstests' generic tests to successfully run on both 4k and 2k blocksizes.
Chandan Rajendra (7):
Btrfs: subpagesize-blocksize: Get rid of whole page reads.
Btrfs: subpagesize-blocksize: Get rid of whole page writes.
Btrfs: subpagesize-blocksize: __btrfs_buffered_write: Reserve/release
extents aligned to block size.
Btrfs: subpagesize-blocksize: Read tree blocks whose size is
<PAGE_CACHE_SIZE.
Btrfs: subpagesize-blocksize: Write only dirty extent buffers
belonging to a page
Btrfs: subpagesize-blocksize: Compute and look up csums based on
sectorsized blocks.
Btrfs: subpagesize-blocksize: __extent_writepage: Write only dirty
blocks of a page.
Chandra Seetharaman (2):
Btrfs: subpagesize-blocksize: Define extent_buffer_head.
Btrfs: subpagesize-blocksize: Allow mounting filesystems where
sectorsize != PAGE_SIZE
fs/btrfs/backref.c | 2 +- fs/btrfs/ctree.c | 2 +- fs/btrfs/ctree.h | 6 +- fs/btrfs/disk-io.c | 117 ++--- fs/btrfs/disk-io.h | 3 + fs/btrfs/extent-tree.c | 6 +- fs/btrfs/extent_io.c | 1121 ++++++++++++++++++++++++++++++------------ fs/btrfs/extent_io.h | 48 +- fs/btrfs/file-item.c | 85 ++-- fs/btrfs/file.c | 32 +- fs/btrfs/inode.c | 74 ++- fs/btrfs/volumes.c | 2 +- fs/btrfs/volumes.h | 3 + include/trace/events/btrfs.h | 2 +- 14 files changed, 1044 insertions(+), 459 deletions(-)
Signature · 1 line
1.8.3.1
RFC PATCH v3 1/9 Btrfs: subpagesize-blocksize: Get rid of whole page reads.
Based on original patch from Aneesh Kumar K.V <[email protected]>
bio_vec->{bv_offset, bv_len} cannot be relied upon by the end bio functions to track the file offset range operated on by the bio. Hence this patch adds two new members to 'struct btrfs_io_bio' to track the file offset range.
This patch also brings back check_page_locked() to reliably unlock pages in readpage's end bio function.
--- fs/btrfs/extent_io.c | 120 +++++++++++++++++++++++++++++++++------------------ fs/btrfs/volumes.h | 3 ++ 2 files changed, 80 insertions(+), 43 deletions(-)
fs/btrfs/extent_io.c +77 -43
@@ -1943,15 +1943,29 @@ int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end,* helper function to set a given page up to date if all the * extents in the tree for that page are up to date */ -static void check_page_uptodate (struct extent_io_tree *tree,struct page *page) +static void check_page_uptodate (struct extent_io_tree *tree,struct page *page, +struct extent_state *cached) {u64 start =page_offset (page);u64 end = start +PAGE_CACHE_SIZE -1 ; -if (test_range_bit (tree, start, end,EXTENT_UPTODATE ,1 ,NULL )) +if (test_range_bit (tree, start, end,EXTENT_UPTODATE ,1 , cached))SetPageUptodate (page); }/* +* helper function to unlock a page if all the extents in the tree +* for that page are unlocked +*/ +static void check_page_locked (struct extent_io_tree *tree,struct page *page) +{ +u64 start =page_offset (page); +u64 end = start +PAGE_CACHE_SIZE -1 ; + +if (!test_range_bit (tree, start, end,EXTENT_LOCKED ,0 ,NULL )) { +unlock_page (page); + } +} + * When IO fails, either with EIO or csum verification fails, we * try other mirrors that might have a good copy of the data. This * io_failure_record is used to record state as we go through all the
@@ -2414,16 +2428,33 @@ static void end_bio_extent_writepage(struct bio *bio, int err)bio_put (bio); } -static void -endio_readpage_release_extent (struct extent_io_tree *tree,u64 start,u64 len, -int uptodate) +static void unlock_extent_and_page (struct address_space *mapping, +struct extent_io_tree *tree, +struct btrfs_io_bio *io_bio) { -struct extent_state *cached =NULL ; -u64 end = start + len -1 ; +pgoff_t index; +u64 offset, len; +/* +* This btrfs_io_bio may span multiple pages. +* We need to unlock the pages convered by them +* if we got endio callback for all the blocks in the page. +* btrfs_io_bio also contain "contigous blocks of the file" +* look at submit_extent_page for more details. +*/ -if (uptodate && tree->track_uptodate) -set_extent_uptodate (tree, start, end, &cached,GFP_ATOMIC ); -unlock_extent_cached (tree, start, end, &cached,GFP_ATOMIC ); + offset = io_bio->start_offset; + len = io_bio->len; +unlock_extent (tree, offset, offset + len -1 ); + + index = offset >>PAGE_CACHE_SHIFT ; +while (offset < io_bio->start_offset + len) { +struct page *page; + page =find_get_page (mapping, index); +check_page_locked (tree, page); +page_cache_release (page); + index++; + offset +=PAGE_CACHE_SIZE ; + } }/*
@@ -2443,13 +2474,13 @@ static void end_bio_extent_readpage(struct bio *bio, int err)struct bio_vec *bvec_end = bio->bi_io_vec + bio->bi_vcnt -1 ;struct bio_vec *bvec = bio->bi_io_vec;struct btrfs_io_bio *io_bio =btrfs_io_bio (bio); +struct address_space *mapping = bio->bi_io_vec->bv_page->mapping;struct extent_io_tree *tree; +struct extent_state *cached =NULL ;u64 offset =0 ;u64 start;u64 end;u64 len; -u64 extent_start =0 ; -u64 extent_len =0 ;int mirror;int ret;
@@ -2482,8 +2513,8 @@ static void end_bio_extent_readpage(struct bio *bio, int err) bvec->bv_offset, bvec->bv_len); } - start =page_offset (page); - end = start + bvec->bv_offset + bvec->bv_len -1 ; + start =page_offset (page) + bvec->bv_offset; + end = start + bvec->bv_len -1 ; len = bvec->bv_len;if (++bvec <= bvec_end)
@@ -2540,40 +2571,24 @@ readpage_ok: offset = i_size & (PAGE_CACHE_SIZE -1 );if (page->index == end_index && offset)zero_user_segment (page, offset,PAGE_CACHE_SIZE ); -SetPageUptodate (page); +if (tree->track_uptodate) +set_extent_uptodate (tree, start, end, &cached, +GFP_ATOMIC ); }else {ClearPageUptodate (page);SetPageError (page); } -unlock_page (page); - offset += len; -if (unlikely (!uptodate)) { -if (extent_len) { -endio_readpage_release_extent (tree, - extent_start, - extent_len,1 ); - extent_start =0 ; - extent_len =0 ; - } -endio_readpage_release_extent (tree, start, - end - start +1 ,0 ); - }else if (!extent_len) { - extent_start = start; - extent_len = end +1 - start; - }else if (extent_start + extent_len == start) { - extent_len += end +1 - start; - }else { -endio_readpage_release_extent (tree, extent_start, - extent_len, uptodate); - extent_start = start; - extent_len = end +1 - start; - } + offset += len; +/* +* Check whether the page in the bvec can be marked uptodate +*/ +check_page_uptodate (tree, page, cached); }while (bvec <= bvec_end); - -if (extent_len) -endio_readpage_release_extent (tree, extent_start, extent_len, - uptodate); +/* +* Unlock the btrfs_bio and associated page +*/ +unlock_extent_and_page (mapping, tree, io_bio);if (io_bio->end_io) io_bio->end_io (io_bio, err);bio_put (bio);
@@ -2700,6 +2715,18 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,else contig =bio_end_sector (bio) == sector; +if (contig) { +/* +* Check whether we are contig if file offsets. +* We should mostly be for readpage/readpages +* We need to do this because we use btrfs_io_bio +* start_offset and len to unlock in endio routines. +*/ +if ((page_offset (page) + offset) != + (btrfs_io_bio (bio)->start_offset + +btrfs_io_bio (bio)->len)) + contig =0 ; + }if (prev_bio_flags != bio_flags || !contig ||merge_bio (rw, tree, page, offset, page_size, bio, bio_flags) ||bio_add_page (bio, page, page_size, offset) < page_size) {
@@ -2709,6 +2736,11 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,return ret; bio =NULL ; }else { +/* +* update btrfs_io_bio len. So that we can unlock +* correctly in end_io callback. +*/ +btrfs_io_bio (bio)->len += page_size;return 0 ; } }
@@ -2724,6 +2756,8 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,bio_add_page (bio, page, page_size, offset); bio->bi_end_io = end_io_func; bio->bi_private = tree; +btrfs_io_bio (bio)->start_offset =page_offset (page) + offset; +btrfs_io_bio (bio)->len = page_size;if (bio_ret) *bio_ret = bio;
@@ -2914,7 +2948,7 @@ static int __do_readpage(struct extent_io_tree *tree,/* the get_extent function already copied into the page */ if (test_range_bit (tree, cur, cur_end,EXTENT_UPTODATE ,1 ,NULL )) { -check_page_uptodate (tree, page); +check_page_uptodate (tree, page,NULL );if (!parent_locked)unlock_extent (tree, cur, cur + iosize -1 ); cur = cur + iosize;
fs/btrfs/volumes.h +3 -0
@@ -173,6 +173,9 @@ struct btrfs_io_bio {u8 csum_inline[BTRFS_BIO_INLINE_CSUM_SIZE ];u8 *csum_allocated;btrfs_io_bio_end_io_t *end_io; +/* Track file offset range operated on by the bio.*/ +u64 start_offset; +u64 len;struct bio bio; };
Signature · 1 line
1.8.3.1
RFC PATCH v3 2/9 Btrfs: subpagesize-blocksize: Get rid of whole page writes.
In reply to Chandan RajendraThis commit brings back functions that set/clear EXTENT_WRITEBACK bits. These are required to reliably clear PG_writeback page flag.
--- fs/btrfs/extent_io.c | 149 +++++++++++++++++++++++++++++++++++---------------- fs/btrfs/extent_io.h | 2 +- fs/btrfs/inode.c | 50 ++++++++++++----- 3 files changed, 142 insertions(+), 59 deletions(-)
fs/btrfs/extent_io.c +103 -46
@@ -1293,6 +1293,20 @@ int clear_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end, cached_state, mask); } +static int set_extent_writeback (struct extent_io_tree *tree,u64 start,u64 end, +struct extent_state **cached_state,gfp_t mask) +{ +return set_extent_bit (tree, start, end,EXTENT_WRITEBACK ,NULL , + cached_state, mask); +} + +static int clear_extent_writeback (struct extent_io_tree *tree,u64 start,u64 end, +struct extent_state **cached_state,gfp_t mask) +{ +return clear_extent_bit (tree, start, end,EXTENT_WRITEBACK ,1 ,0 , + cached_state, mask); +} +/* * either insert or lock state struct between start and end use mask to tell * us if waiting is desired.
@@ -1399,6 +1413,7 @@ static int set_range_writeback(struct extent_io_tree *tree, u64 start, u64 end)page_cache_release (page); index++; } +set_extent_writeback (tree, start, end,NULL ,GFP_NOFS );return 0 ; }
@@ -1966,6 +1981,16 @@ static void check_page_locked(struct extent_io_tree *tree, struct page *page) } } +static void check_page_writeback (struct extent_io_tree *tree,struct page *page) +{ +u64 start =page_offset (page); +u64 end = start +PAGE_CACHE_SIZE -1 ; + +if (!test_range_bit (tree, start, end,EXTENT_WRITEBACK ,0 ,NULL )) +end_page_writeback (page); +} + +/* * When IO fails, either with EIO or csum verification fails, we * try other mirrors that might have a good copy of the data. This * io_failure_record is used to record state as we go through all the
@@ -2355,27 +2380,71 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, }/* lots and lots of room for performance fixes in the end_bio funcs */ - -int end_extent_writepage (struct page *page,int err,u64 start,u64 end) +void end_extents_write (struct inode *inode,int err,u64 start,u64 end) { +struct extent_io_tree *tree = &BTRFS_I (inode)->io_tree;int uptodate = (err ==0 ); -struct extent_io_tree *tree; +pgoff_t index, end_index; +u64 page_start, page_end; +struct page *page;int ret; - tree = &BTRFS_I (page->mapping->host)->io_tree; + index = start >>PAGE_CACHE_SHIFT ; + end_index = end >>PAGE_CACHE_SHIFT ; -if (tree->ops && tree->ops->writepage_end_io_hook) { - ret = tree->ops->writepage_end_io_hook (page, start, - end,NULL , uptodate); -if (ret) - uptodate =0 ; + page_start = start; + +while (index <= end_index) { + page =find_get_page (inode->i_mapping, index); +BUG_ON (!page); + + page_end =min_t (u64, end,page_offset (page) +PAGE_CACHE_SIZE -1 ); + +if (tree->ops && tree->ops->writepage_end_io_hook) { + ret = tree->ops->writepage_end_io_hook (page, + page_start, page_end, +NULL , uptodate); +if (ret) + uptodate =0 ; + } + + page_start = page_end +1 ; + + ++index; + +if (!uptodate) { +ClearPageUptodate (page); +SetPageError (page); + } + +page_cache_release (page); } +} + +static void clear_extent_and_page_writeback (struct address_space *mapping, +struct extent_io_tree *tree, +struct btrfs_io_bio *io_bio) +{ +struct page *page; +pgoff_t index; +u64 offset, len; + + offset = io_bio->start_offset; + len = io_bio->len; + +clear_extent_writeback (tree, offset, offset + len -1 ,NULL , +GFP_ATOMIC ); -if (!uptodate) { -ClearPageUptodate (page); -SetPageError (page); + index = offset >>PAGE_CACHE_SHIFT ; +while (offset < io_bio->start_offset + len) { + page =find_get_page (mapping, index); +check_page_writeback (tree, page); +page_cache_release (page); + index++; + offset +=page_offset (page) +PAGE_CACHE_SIZE - offset; } -return 0 ; + +unlock_extent (tree, io_bio->start_offset, io_bio->start_offset + len -1 ); }/*
@@ -2389,41 +2458,14 @@ int end_extent_writepage(struct page *page, int err, u64 start, u64 end)*/ static void end_bio_extent_writepage (struct bio *bio,int err) { -struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt -1 ; -u64 start; -u64 end; - -do { -struct page *page = bvec->bv_page; - -/* We always issue full-page reads, but if some block -* in a page fails to read, blk_update_request() will -* advance bv_offset and adjust bv_len to compensate. -* Print a warning for nonzero offsets, and an error -* if they don't add up to a full page. */ -if (bvec->bv_offset || bvec->bv_len !=PAGE_CACHE_SIZE ) { -if (bvec->bv_offset + bvec->bv_len !=PAGE_CACHE_SIZE ) -btrfs_err (BTRFS_I (page->mapping->host)->root->fs_info, -"partial page write in btrfs with offset %u and length %u" , - bvec->bv_offset, bvec->bv_len); -else -btrfs_info (BTRFS_I (page->mapping->host)->root->fs_info, -"incomplete page write in btrfs with offset %u and " -"length %u" , - bvec->bv_offset, bvec->bv_len); - } - - start =page_offset (page); - end = start + bvec->bv_offset + bvec->bv_len -1 ; - -if (--bvec >= bio->bi_io_vec) -prefetchw (&bvec->bv_page->flags); +struct address_space *mapping = bio->bi_io_vec->bv_page->mapping; +struct extent_io_tree *tree = &BTRFS_I (mapping->host)->io_tree; +struct btrfs_io_bio *io_bio =btrfs_io_bio (bio); -if (end_extent_writepage (page, err, start, end)) -continue ; +end_extents_write (mapping->host, err, io_bio->start_offset, + io_bio->start_offset + io_bio->len -1 ); -end_page_writeback (page); - }while (bvec >= bio->bi_io_vec); +clear_extent_and_page_writeback (mapping, tree, io_bio);bio_put (bio); }
@@ -3151,6 +3193,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,u64 last_byte =i_size_read (inode);u64 block_start;u64 iosize; +u64 unlock_start = start;sector_t sector;struct extent_state *cached_state =NULL ;struct extent_map *em;
@@ -3233,6 +3276,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,/* File system has been set read-only */ if (ret) {SetPageError (page); + unlock_start = page_end +1 ; goto done; }/*
@@ -3268,10 +3312,14 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, goto done_unlocked; } } + +lock_extent (tree, start, page_end); +if (tree->ops && tree->ops->writepage_start_hook) { ret = tree->ops->writepage_start_hook (page, start, page_end);if (ret) { +unlock_extent (tree, start, page_end);/* Fixup worker will requeue */ if (ret == -EBUSY ) wbc->pages_skipped++;
@@ -3292,9 +3340,11 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, end = page_end;if (last_byte <= start) { +unlock_extent (tree, start, page_end);if (tree->ops && tree->ops->writepage_end_io_hook) tree->ops->writepage_end_io_hook (page, start, page_end,NULL ,1 ); + unlock_start = page_end +1 ; goto done; }
@@ -3302,9 +3352,11 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,while (cur <= end) {if (cur >= last_byte) { +unlock_extent (tree, unlock_start, page_end);if (tree->ops && tree->ops->writepage_end_io_hook) tree->ops->writepage_end_io_hook (page, cur, page_end,NULL ,1 ); + unlock_start = page_end +1 ;break ; } em = epd->get_extent(inode, page, pg_offset, cur,
@@ -3332,6 +3384,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,*/ if (compressed || block_start ==EXTENT_MAP_HOLE || block_start ==EXTENT_MAP_INLINE ) { +unlock_extent (tree, unlock_start, cur + iosize -1 );/* * end_io notification does not happen here for * compressed extents
@@ -3351,6 +3404,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, cur += iosize; pg_offset += iosize; + unlock_start = cur;continue ; }/* leave this out until we have a page_mkwrite call */
@@ -3397,6 +3451,9 @@ done:set_page_writeback (page);end_page_writeback (page); } +if (unlock_start <= page_end) +unlock_extent (tree, unlock_start, page_end); +unlock_page (page); done_unlocked:
fs/btrfs/extent_io.h +1 -1
@@ -341,7 +341,7 @@ struct btrfs_fs_info;int repair_io_failure (struct btrfs_fs_info *fs_info,u64 start,u64 length,u64 logical,struct page *page,int mirror_num); -int end_extent_writepage (struct page *page,int err,u64 start,u64 end); +void end_extents_write (struct inode *inode,int err,u64 start,u64 end);int repair_eb_io_failure (struct btrfs_root *root,struct extent_buffer *eb,int mirror_num);#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
fs/btrfs/inode.c +38 -12
78 lines not on this page · raw message
Signature · 1 line
1.8.3.1
RFC PATCH v3 3/9 Btrfs: subpagesize-blocksize: __btrfs_buffered_write: Reserve/release extents aligned to block size.
In reply to Chandan RajendraCurrently, the code reserves/releases extents in multiples of PAGE_CACHE_SIZE units. Fix this.
--- fs/btrfs/file.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
fs/btrfs/file.c +20 -12
@@ -1339,18 +1339,21 @@ fail: static noinline intlock_and_cleanup_extent_if_need (struct inode *inode,struct page **pages,size_t num_pages,loff_t pos, +size_t write_bytes,u64 *lockstart,u64 *lockend,struct extent_state **cached_state) { +struct btrfs_root *root =BTRFS_I (inode)->root;u64 start_pos;u64 last_pos;int i;int ret =0 ; - start_pos = pos & ~((u64 )PAGE_CACHE_SIZE -1 ); - last_pos = start_pos + ((u64 )num_pages <<PAGE_CACHE_SHIFT ) -1 ; + start_pos = pos & ~((u64 )root->sectorsize -1 ); + last_pos = start_pos + +ALIGN (pos + write_bytes - start_pos, root->sectorsize) -1 ; -if (start_pos < inode->i_size) { +if (start_pos < inode->i_size) {struct btrfs_ordered_extent *ordered;lock_extent_bits (&BTRFS_I (inode)->io_tree, start_pos, last_pos,0 , cached_state);
@@ -1468,6 +1471,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,while (iov_iter_count (i) >0 ) {size_t offset = pos & (PAGE_CACHE_SIZE -1 ); +size_t sector_offset;size_t write_bytes =min (iov_iter_count (i), nrptrs * (size_t )PAGE_CACHE_SIZE - offset);
@@ -1488,7 +1492,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,break ; } - reserve_bytes = num_pages <<PAGE_CACHE_SHIFT ; + sector_offset = pos & (root->sectorsize -1 ); + reserve_bytes =ALIGN (write_bytes + sector_offset, root->sectorsize); + ret =btrfs_check_data_free_space (inode, reserve_bytes); if (ret == -ENOSPC && (BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
@@ -1503,7 +1509,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, num_pages = (write_bytes + offset +PAGE_CACHE_SIZE -1 ) >>PAGE_CACHE_SHIFT ; - reserve_bytes = num_pages <<PAGE_CACHE_SHIFT ; + + reserve_bytes =ALIGN (write_bytes + sector_offset, + root->sectorsize); ret =0 ; }else { ret = -ENOSPC ;
@@ -1536,8 +1544,8 @@ again:break ; ret =lock_and_cleanup_extent_if_need (inode, pages, num_pages, - pos, &lockstart, &lockend, - &cached_state); + pos, write_bytes, &lockstart, &lockend, + &cached_state);if (ret <0 ) {if (ret == -EAGAIN ) goto again;
@@ -1574,9 +1582,9 @@ again:* we still have an outstanding extent for the chunk we actually * managed to copy. */ -if (num_pages > dirty_pages) { - release_bytes = (num_pages - dirty_pages) << -PAGE_CACHE_SHIFT ; +if (write_bytes > copied) { + release_bytes = (write_bytes - copied) + & ~((u64 )root->sectorsize -1 );if (copied >0 ) {spin_lock (&BTRFS_I (inode)->lock);BTRFS_I (inode)->outstanding_extents++;
@@ -1590,7 +1598,7 @@ again: release_bytes); } - release_bytes = dirty_pages <<PAGE_CACHE_SHIFT ; + release_bytes =ALIGN (copied + sector_offset, root->sectorsize);if (copied >0 ) ret = btrfs_dirty_pages(root, inode, pages,
@@ -1609,7 +1617,7 @@ again:if (only_release_metadata && copied >0 ) {u64 lockstart =round_down (pos, root->sectorsize);u64 lockend = lockstart + - (dirty_pages <<PAGE_CACHE_SHIFT ) -1 ; +ALIGN (copied, root->sectorsize) -1 ; set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, EXTENT_NORESERVE, NULL,
Signature · 1 line
1.8.3.1
RFC PATCH v3 4/9 Btrfs: subpagesize-blocksize: Define extent_buffer_head.
In reply to Chandan RajendraFrom: Chandra Seetharaman <[email protected]>
In order to handle multiple extent buffers per page, first we need to create a way to handle all the extent buffers that are attached to a page.
This patch creates a new data structure 'struct extent_buffer_head', and moves fields that are common to all extent buffers in a page from 'struct extent buffer' to 'struct extent_buffer_head'
Also, this patch moves EXTENT_BUFFER_TREE_REF, EXTENT_BUFFER_DUMMY and EXTENT_BUFFER_IN_TREE flags from extent_buffer->ebflags to extent_buffer_head->bflags.
--- fs/btrfs/backref.c | 2 +- fs/btrfs/ctree.c | 2 +- fs/btrfs/ctree.h | 6 +- fs/btrfs/disk-io.c | 46 ++++-- fs/btrfs/extent-tree.c | 6 +- fs/btrfs/extent_io.c | 372 +++++++++++++++++++++++++++++-------------- fs/btrfs/extent_io.h | 46 ++++-- fs/btrfs/volumes.c | 2 +- include/trace/events/btrfs.h | 2 +- 9 files changed, 326 insertions(+), 158 deletions(-)
fs/btrfs/backref.c +1 -1
@@ -1272,7 +1272,7 @@ char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, eb = path->nodes[0 ];/* make sure we can use eb after releasing the path */ if (eb != eb_in) { -atomic_inc (&eb->refs); +atomic_inc (&eb_head (eb)->refs);btrfs_tree_read_lock (eb);btrfs_set_lock_blocking_rw (eb,BTRFS_READ_LOCK ); }
fs/btrfs/ctree.c +1 -1
@@ -169,7 +169,7 @@ struct extent_buffer *btrfs_root_node(struct btrfs_root *root)* the inc_not_zero dance and if it doesn't work then * synchronize_rcu and try again. */ -if (atomic_inc_not_zero (&eb->refs)) { +if (atomic_inc_not_zero (&eb_head (eb)->refs)) {rcu_read_unlock ();break ; }
fs/btrfs/ctree.h +4 -2
@@ -2138,14 +2138,16 @@ static inline void btrfs_set_token_##name(struct extent_buffer *eb, \#define BTRFS_SETGET_HEADER_FUNCS (name, type, member, bits) \ static inline u##bits btrfs_##name(struct extent_buffer *eb) \ { \ - type *p = page_address(eb->pages[0]); \ + type *p = page_address(eb_head(eb)->pages[0]) + \ + (eb->start & (PAGE_CACHE_SIZE -1)); \ u##bits res = le##bits##_to_cpu(p->member); \ return res; \ } \ static inline void btrfs_set_##name(struct extent_buffer *eb, \ u##bits val) \ { \ - type *p = page_address(eb->pages[0]); \ + type *p = page_address(eb_head(eb)->pages[0]) + \ + (eb->start & (PAGE_CACHE_SIZE -1)); \ p->member = cpu_to_le##bits(val); \ }
fs/btrfs/disk-io.c +30 -16
123 lines not on this page · raw message
fs/btrfs/extent-tree.c +3 -3
@@ -5984,7 +5984,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, goto out; } -WARN_ON (test_bit (EXTENT_BUFFER_DIRTY , &buf->bflags)); +WARN_ON (test_bit (EXTENT_BUFFER_DIRTY , &buf->ebflags));btrfs_add_free_space (cache, buf->start, buf->len);btrfs_update_reserved_bytes (cache, buf->len,RESERVE_FREE );
@@ -6001,7 +6001,7 @@ out:* Deleting the buffer, clear the corrupt flag since it doesn't matter * anymore. */ -clear_bit (EXTENT_BUFFER_CORRUPT , &buf->bflags); +clear_bit (EXTENT_BUFFER_CORRUPT , &buf->ebflags);btrfs_put_block_group (cache); }
@@ -6887,7 +6887,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,btrfs_set_buffer_lockdep_class (root->root_key.objectid, buf, level);btrfs_tree_lock (buf);clean_tree_block (trans, root, buf); -clear_bit (EXTENT_BUFFER_STALE , &buf->bflags); +clear_bit (EXTENT_BUFFER_STALE , &buf->ebflags);btrfs_set_lock_blocking (buf);btrfs_set_buffer_uptodate (buf);
fs/btrfs/extent_io.c +252 -120
704 lines not on this page · raw message
fs/btrfs/extent_io.h +33 -13
86 lines not on this page · raw message
fs/btrfs/volumes.c +1 -1
@@ -5936,7 +5936,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)* to silence the warning eg. on PowerPC 64. */ if (PAGE_CACHE_SIZE >BTRFS_SUPER_INFO_SIZE ) -SetPageUptodate (sb->pages[0 ]); +SetPageUptodate (eb_head (sb)->pages[0 ]);write_extent_buffer (sb, super_copy,0 ,BTRFS_SUPER_INFO_SIZE ); array_size =btrfs_super_sys_array_size (super_copy);
include/trace/events/btrfs.h +1 -1
@@ -695,7 +695,7 @@ TRACE_EVENT(btrfs_cow_block,TP_fast_assign ( __entry->root_objectid = root->root_key.objectid; __entry->buf_start = buf->start; - __entry->refs =atomic_read (&buf->refs); + __entry->refs =atomic_read (&eb_head (buf)->refs); __entry->cow_start = cow->start; __entry->buf_level =btrfs_header_level (buf); __entry->cow_level =btrfs_header_level (cow);
Signature · 1 line
1.8.3.1
RFC PATCH v3 5/9 Btrfs: subpagesize-blocksize: Read tree blocks whose size is <PAGE_CACHE_SIZE.
In reply to Chandan RajendraIn the case of subpagesize-blocksize, this patch makes it possible to read only a single metadata block from the disk instead of all the metadata blocks that map into a page.
--- fs/btrfs/disk-io.c | 45 ++++++++--------- fs/btrfs/disk-io.h | 3 ++ fs/btrfs/extent_io.c | 135 +++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 137 insertions(+), 46 deletions(-)
fs/btrfs/disk-io.c +19 -26
@@ -413,7 +413,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,int mirror_num =0 ;int failed_mirror =0 ; -clear_bit (EXTENT_BUFFER_CORRUPT , &eb->bflags); +clear_bit (EXTENT_BUFFER_CORRUPT , &eb->ebflags); io_tree = &BTRFS_I (root->fs_info->btree_inode)->io_tree;while (1 ) { ret = read_extent_buffer_pages(io_tree, eb, start,
@@ -432,7 +432,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,* there is no reason to read the other copies, they won't be * any less wrong. */ -if (test_bit (EXTENT_BUFFER_CORRUPT , &eb->bflags)) +if (test_bit (EXTENT_BUFFER_CORRUPT , &eb->ebflags))break ; num_copies = btrfs_num_copies(root->fs_info,
@@ -564,12 +564,13 @@ static noinline int check_leaf(struct btrfs_root *root,return 0 ; } -static int btree_readpage_end_io_hook (struct btrfs_io_bio *io_bio, -u64 phy_offset,struct page *page, -u64 start,u64 end,int mirror) +int verify_extent_buffer_read (struct btrfs_io_bio *io_bio, +struct page *page, +u64 start,u64 end,int mirror) {u64 found_start;int found_level; +struct extent_buffer_head *ebh;struct extent_buffer *eb;struct btrfs_root *root =BTRFS_I (page->mapping->host)->root;int ret =0 ;
@@ -579,18 +580,26 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio, goto out; eb = (struct extent_buffer *)page->private; +do { +if ((eb->start <= start) && (eb->start + eb->len -1 > start)) +break ; + }while ((eb = eb->eb_next) !=NULL ); + +BUG_ON (!eb); + + ebh =eb_head (eb);/* the pending IO might have been the only thing that kept this buffer * in memory. Make sure we have a ref for all this other checks */ extent_buffer_get (eb); - reads_done =atomic_dec_and_test (&eb->io_pages); + reads_done =atomic_dec_and_test (&ebh->io_bvecs);if (!reads_done) goto err; eb->read_mirror = mirror; -if (test_bit (EXTENT_BUFFER_IOERR , &eb->bflags)) { +if (test_bit (EXTENT_BUFFER_IOERR , &eb->ebflags)) { ret = -EIO ; goto err; }
@@ -632,7 +641,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,* return -EIO. */ if (found_level ==0 &&check_leaf (root, eb)) { -set_bit (EXTENT_BUFFER_CORRUPT , &eb->bflags); +set_bit (EXTENT_BUFFER_CORRUPT , &eb->ebflags); ret = -EIO ; }
@@ -640,7 +649,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,set_extent_buffer_uptodate (eb); err:if (reads_done && -test_and_clear_bit (EXTENT_BUFFER_READAHEAD , &eb->bflags)) +test_and_clear_bit (EXTENT_BUFFER_READAHEAD , &eb->ebflags))btree_readahead_hook (root, eb, eb->start, ret);if (ret) {
@@ -649,7 +658,7 @@ err:* again, we have to make sure it has something * to decrement */ -atomic_inc (&eb->io_pages); +atomic_inc (&eb_head (eb)->io_bvecs);clear_extent_buffer_uptodate (eb); }free_extent_buffer (eb);
@@ -657,20 +666,6 @@ out:return ret; } -static int btree_io_failed_hook (struct page *page,int failed_mirror) -{ -struct extent_buffer *eb; -struct btrfs_root *root =BTRFS_I (page->mapping->host)->root; - - eb = (struct extent_buffer *)page->private; -set_bit (EXTENT_BUFFER_IOERR , &eb->bflags); - eb->read_mirror = failed_mirror; -atomic_dec (&eb->io_pages); -if (test_and_clear_bit (EXTENT_BUFFER_READAHEAD , &eb->bflags)) -btree_readahead_hook (root, eb, eb->start, -EIO ); -return -EIO ;/* we fixed nothing */ -} -static void end_workqueue_bio (struct bio *bio,int err) {struct end_io_wq *end_io_wq = bio->bi_private;
@@ -4109,8 +4104,6 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) }static struct extent_io_ops btree_extent_io_ops = { - .readpage_end_io_hook = btree_readpage_end_io_hook, - .readpage_io_failed_hook = btree_io_failed_hook, .submit_bio_hook = btree_submit_bio_hook,/* note we're sharing with inode.c for the merge bio hook */ .merge_bio_hook = btrfs_merge_bio_hook,
fs/btrfs/disk-io.h +3 -0
@@ -110,6 +110,9 @@ static inline void btrfs_put_fs_root(struct btrfs_root *root)kfree (root); } +int verify_extent_buffer_read (struct btrfs_io_bio *io_bio, +struct page *page, +u64 start,u64 end,int mirror);void btrfs_mark_buffer_dirty (struct extent_buffer *buf);int btrfs_buffer_uptodate (struct extent_buffer *buf,u64 parent_transid,int atomic);
fs/btrfs/extent_io.c +115 -20
190 lines not on this page · raw message
Signature · 1 line
1.8.3.1
RFC PATCH v3 6/9 Btrfs: subpagesize-blocksize: Write only dirty extent buffers belonging to a page
In reply to Chandan RajendraFor the subpagesize-blocksize scenario, This patch adds the ability to write a single extent buffer to the disk.
--- fs/btrfs/disk-io.c | 20 ++-- fs/btrfs/extent_io.c | 279 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 244 insertions(+), 55 deletions(-)
fs/btrfs/disk-io.c +13 -7
@@ -466,17 +466,23 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,static int csum_dirty_buffer (struct btrfs_root *root,struct page *page) { -u64 start =page_offset (page); -u64 found_start;struct extent_buffer *eb; +u64 found_start; eb = (struct extent_buffer *)page->private; -if (page != eb->pages[0 ]) +if (page !=eb_head (eb)->pages[0 ])return 0 ; - found_start =btrfs_header_bytenr (eb); -if (WARN_ON (found_start != start || !PageUptodate (page))) -return 0 ; -csum_tree_block (root, eb,0 ); +do { +if (!test_bit (EXTENT_BUFFER_WRITEBACK , &eb->ebflags)) +continue ; +if (WARN_ON (!test_bit (EXTENT_BUFFER_UPTODATE , &eb->ebflags))) +continue ; + found_start =btrfs_header_bytenr (eb); +if (WARN_ON (found_start != eb->start)) +return 0 ; +csum_tree_block (root, eb,0 ); + }while ((eb = eb->eb_next) !=NULL ); +return 0 ; }
fs/btrfs/extent_io.c +231 -48
407 lines not on this page · raw message
Signature · 1 line
1.8.3.1
RFC PATCH v3 7/9 Btrfs: subpagesize-blocksize: Allow mounting filesystems where sectorsize != PAGE_SIZE
In reply to Chandan RajendraFrom: Chandra Seetharaman <[email protected]>
This patch allows mounting filesystems with blocksize smaller than the PAGE_SIZE.
--- fs/btrfs/disk-io.c | 6 ------ 1 file changed, 6 deletions(-)
fs/btrfs/disk-io.c +0 -6
@@ -2599,12 +2599,6 @@ int open_ctree(struct super_block *sb, goto fail_sb_buffer; } -if (sectorsize !=PAGE_SIZE ) { -printk (KERN_WARNING "BTRFS: Incompatible sector size(%lu) " -"found on %s\n" , (unsigned long )sectorsize, sb->s_id); - goto fail_sb_buffer; - } -mutex_lock (&fs_info->chunk_mutex); ret =btrfs_read_sys_array (tree_root);mutex_unlock (&fs_info->chunk_mutex);
Signature · 1 line
1.8.3.1
RFC PATCH v3 8/9 Btrfs: subpagesize-blocksize: Compute and look up csums based on sectorsized blocks.
In reply to Chandan RajendraChecksums are applicable to sectorsize units. The current code uses bio->bv_len units to compute and look up checksums. This works on machines where sectorsize == PAGE_CACHE_SIZE. This patch makes the checksum computation and look up code to work with sectorsize units.
--- fs/btrfs/file-item.c | 85 ++++++++++++++++++++++++++++++++-------------------- fs/btrfs/inode.c | 24 ++++++++++----- 2 files changed, 68 insertions(+), 41 deletions(-)
fs/btrfs/file-item.c +52 -33
@@ -172,6 +172,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,u64 item_start_offset =0 ;u64 item_last_offset =0 ;u64 disk_bytenr; +u64 page_bytes_left;u32 diff;int nblocks;int bio_index =0 ;
@@ -220,6 +221,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, disk_bytenr = (u64 )bio->bi_sector <<9 ;if (dio) offset = logical_offset; + + page_bytes_left = bvec->bv_len;while (bio_index < bio->bi_vcnt) {if (!dio) offset =page_offset (bvec->bv_page) + bvec->bv_offset;
@@ -243,7 +246,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,if (BTRFS_I (inode)->root->root_key.objectid ==BTRFS_DATA_RELOC_TREE_OBJECTID ) {set_extent_bits (io_tree, offset, - offset + bvec->bv_len -1 , + offset + root->sectorsize -1 ,EXTENT_NODATASUM ,GFP_NOFS ); }else { btrfs_info(BTRFS_I(inode)->root->fs_info,
@@ -281,11 +284,17 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, found: csum += count * csum_size; nblocks -= count; +while (count--) { - disk_bytenr += bvec->bv_len; - offset += bvec->bv_len; - bio_index++; - bvec++; + disk_bytenr += root->sectorsize; + offset += root->sectorsize; + page_bytes_left -= root->sectorsize; +if (!page_bytes_left) { + bio_index++; + bvec++; + page_bytes_left = bvec->bv_len; + } + } }btrfs_free_path (path);
@@ -442,6 +451,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,struct bio_vec *bvec = bio->bi_io_vec;int bio_index =0 ;int index; +int nr_sectors; +int i;unsigned long total_bytes =0 ;unsigned long this_sum_bytes =0 ;u64 offset;
@@ -468,41 +479,49 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,if (!contig) offset =page_offset (bvec->bv_page) + bvec->bv_offset; -if (offset >= ordered->file_offset + ordered->len || - offset < ordered->file_offset) { -unsigned long bytes_left; - sums->len = this_sum_bytes; - this_sum_bytes =0 ; -btrfs_add_ordered_sum (inode, ordered, sums); -btrfs_put_ordered_extent (ordered); + data =kmap_atomic (bvec->bv_page); - bytes_left = bio->bi_size - total_bytes; + nr_sectors = (bvec->bv_len + root->sectorsize -1 ) + >> root->fs_info->sb->s_blocksize_bits; + +for (i =0 ; i < nr_sectors; i++) { +if (offset >= ordered->file_offset + ordered->len || + offset < ordered->file_offset) { +unsigned long bytes_left; + sums->len = this_sum_bytes; + this_sum_bytes =0 ; +btrfs_add_ordered_sum (inode, ordered, sums); +btrfs_put_ordered_extent (ordered); + + bytes_left = bio->bi_size - total_bytes; + + sums =kzalloc (btrfs_ordered_sum_size (root, bytes_left), +GFP_NOFS ); +BUG_ON (!sums);/* -ENOMEM */ + sums->len = bytes_left; + ordered =btrfs_lookup_ordered_extent (inode, offset); +BUG_ON (!ordered);/* Logic error */ + sums->bytenr = ((u64 )bio->bi_sector <<9 ) + + total_bytes; + index =0 ; + } - sums =kzalloc (btrfs_ordered_sum_size (root, bytes_left), -GFP_NOFS ); -BUG_ON (!sums);/* -ENOMEM */ - sums->len = bytes_left; - ordered =btrfs_lookup_ordered_extent (inode, offset); -BUG_ON (!ordered);/* Logic error */ - sums->bytenr = ((u64 )bio->bi_sector <<9 ) + - total_bytes; - index =0 ; + sums->sums[index] = ~(u32 )0 ; + sums->sums[index] + =btrfs_csum_data (data + bvec->bv_offset + (i * root->sectorsize), + sums->sums[index], + root->sectorsize); +btrfs_csum_final (sums->sums[index], + (char *)(sums->sums + index)); + index++; + offset += root->sectorsize; + this_sum_bytes += root->sectorsize; + total_bytes += root->sectorsize; } - data =kmap_atomic (bvec->bv_page); - sums->sums[index] = ~(u32 )0 ; - sums->sums[index] =btrfs_csum_data (data + bvec->bv_offset, - sums->sums[index], - bvec->bv_len);kunmap_atomic (data); -btrfs_csum_final (sums->sums[index], - (char *)(sums->sums + index)); bio_index++; - index++; - total_bytes += bvec->bv_len; - this_sum_bytes += bvec->bv_len; - offset += bvec->bv_len; bvec++; } this_sum_bytes =0 ;
fs/btrfs/inode.c +16 -8
@@ -2827,7 +2827,9 @@ static int btrfs_readpage_end_io_hook(struct btrfs_io_bio *io_bio,char *kaddr;struct btrfs_root *root =BTRFS_I (inode)->root;u32 csum_expected; -u32 csum = ~(u32 )0 ; +u32 csum; +int nr_sectors; +int i; static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
@@ -2846,14 +2848,20 @@ static int btrfs_readpage_end_io_hook(struct btrfs_io_bio *io_bio,return 0 ; } - phy_offset >>= inode->i_sb->s_blocksize_bits; - csum_expected = *(((u32 *)io_bio->csum) + phy_offset); - kaddr =kmap_atomic (page); - csum =btrfs_csum_data (kaddr + offset, csum, end - start +1 ); -btrfs_csum_final (csum, (char *)&csum); -if (csum != csum_expected) - goto zeroit; + nr_sectors = (end - start +1 ) >> root->fs_info->sb->s_blocksize_bits; +for (i =0 ; i < nr_sectors; i++) { + csum = ~(u32 )0 ; + phy_offset >>= inode->i_sb->s_blocksize_bits; + csum_expected = *(((u32 *)io_bio->csum) + phy_offset); + csum =btrfs_csum_data (kaddr + offset, csum, root->sectorsize); +btrfs_csum_final (csum, (char *)&csum); +if (csum != csum_expected) + goto zeroit; + phy_offset += root->sectorsize; + offset += root->sectorsize; + } +kunmap_atomic (kaddr); good:
Signature · 1 line
1.8.3.1
RFC PATCH v3 9/9 Btrfs: subpagesize-blocksize: __extent_writepage: Write only dirty blocks of a page.
In reply to Chandan RajendraThe code now loops across 'ordered extents' instead of 'extent maps' to figure out the dirty blocks of the page to be submitted for a write operation.
--- fs/btrfs/extent_io.c | 66 +++++++++++++++++++++------------------------------- 1 file changed, 27 insertions(+), 39 deletions(-)
fs/btrfs/extent_io.c +27 -39
@@ -3191,19 +3191,19 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,struct inode *inode = page->mapping->host;struct extent_page_data *epd = data;struct extent_io_tree *tree = epd->tree; +struct btrfs_ordered_extent *ordered;u64 start =page_offset (page);u64 delalloc_start;u64 page_end = start +PAGE_CACHE_SIZE -1 ;u64 end;u64 cur = start;u64 extent_offset; +u64 extent_end;u64 last_byte =i_size_read (inode); -u64 block_start;u64 iosize;u64 unlock_start = start;sector_t sector;struct extent_state *cached_state =NULL ; -struct extent_map *em;struct block_device *bdev;int ret;int nr =0 ;
@@ -3247,7 +3247,6 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,kunmap_atomic (userpage);flush_dcache_page (page); } - pg_offset =0 ;set_page_extent_mapped (page);
@@ -3366,59 +3365,49 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, unlock_start = page_end +1 ;break ; } - em = epd->get_extent (inode, page, pg_offset, cur, - end - cur +1 ,1 ); -if (IS_ERR_OR_NULL (em)) { -SetPageError (page); -break ; + + ordered =btrfs_lookup_ordered_extent (inode, cur); +if (!ordered) { +unlock_extent (tree, unlock_start, unlock_start + blocksize -1 ); + unlock_start += blocksize; + cur += blocksize; +continue ; } - extent_offset = cur - em->start; -BUG_ON (extent_map_end (em) <= cur); + pg_offset = cur & (PAGE_CACHE_SIZE -1 ); + + extent_offset = cur - ordered->file_offset; + extent_end = ordered->file_offset + ordered->len; + extent_end = (extent_end < ordered->file_offset) ?-1 : extent_end; +BUG_ON (extent_end <= cur);BUG_ON (end < cur); - iosize =min (extent_map_end (em) - cur, end - cur +1 ); + iosize =min (extent_end - cur, end - cur +1 ); iosize =ALIGN (iosize, blocksize); - sector = (em->block_start + extent_offset) >>9 ; - bdev = em->bdev; - block_start = em->block_start; - compressed =test_bit (EXTENT_FLAG_COMPRESSED , &em->flags); -free_extent_map (em); - em =NULL ; - + sector = (ordered->start + extent_offset) >>9 ; + bdev =BTRFS_I (inode)->root->fs_info->fs_devices->latest_bdev; + compressed =test_bit (BTRFS_ORDERED_COMPRESSED , &ordered->flags); +btrfs_put_ordered_extent (ordered); + ordered =NULL ;/* * compressed and inline extents are written through other * paths in the FS */ -if (compressed || block_start ==EXTENT_MAP_HOLE || - block_start ==EXTENT_MAP_INLINE ) { +if (compressed) {unlock_extent (tree, unlock_start, cur + iosize -1 ); -/* -* end_io notification does not happen here for -* compressed extents +/* we don't want to end_page_writeback on +* a compressed extent. this happens +* elsewhere */ -if (!compressed && tree->ops && - tree->ops->writepage_end_io_hook) - tree->ops->writepage_end_io_hook (page, cur, - cur + iosize -1 , -NULL ,1 ); -else if (compressed) { -/* we don't want to end_page_writeback on -* a compressed extent. this happens -* elsewhere -*/ - nr++; - } - + nr++; cur += iosize; - pg_offset += iosize; unlock_start = cur;continue ; } +/* leave this out until we have a page_mkwrite call */ if (0 && !test_range_bit (tree, cur, cur + iosize -1 ,EXTENT_DIRTY ,0 ,NULL )) { cur = cur + iosize; - pg_offset += iosize;continue ; }
@@ -3449,7 +3438,6 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,SetPageError (page); } cur = cur + iosize; - pg_offset += iosize; nr++; } done:
Signature · 1 line
1.8.3.1