On 07/04/2016 12:34 AM, Chandan Rajendra wrote:
For the subpage-blocksize scenario, a page can contain multiple
blocks. In such cases, this patch handles writing data to files.

Also, When setting EXTENT_DELALLOC, we no longer set EXTENT_UPTODATE bit on
the extent_io_tree since uptodate status is being tracked by the bitmap
pointed to by page->private.

Signed-off-by: Chandan Rajendra <chan...@linux.vnet.ibm.com>
---
 fs/btrfs/extent_io.c  | 150 ++++++++++++++++++++++++--------------------------
 fs/btrfs/file.c       |  17 ++++++
 fs/btrfs/inode.c      |  75 +++++++++++++++++++++----
 fs/btrfs/relocation.c |   3 +
 4 files changed, 155 insertions(+), 90 deletions(-)

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index a349f99..0adbff5 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1494,24 +1494,6 @@ void extent_range_redirty_for_io(struct inode *inode, 
u64 start, u64 end)
        }
 }

-/*
- * helper function to set both pages and extents in the tree writeback
- */
-static void set_range_writeback(struct extent_io_tree *tree, u64 start, u64 
end)
-{
-       unsigned long index = start >> PAGE_SHIFT;
-       unsigned long end_index = end >> PAGE_SHIFT;
-       struct page *page;
-
-       while (index <= end_index) {
-               page = find_get_page(tree->mapping, index);
-               BUG_ON(!page); /* Pages should be in the extent_io_tree */
-               set_page_writeback(page);
-               put_page(page);
-               index++;
-       }
-}
-
 /* find the first state struct with 'bits' set after 'start', and
  * return it.  tree->lock must be held.  NULL will returned if
  * nothing was found after 'start'
@@ -2585,36 +2567,41 @@ void end_extent_writepage(struct page *page, int err, 
u64 start, u64 end)
  */
 static void end_bio_extent_writepage(struct bio *bio)
 {
+       struct btrfs_page_private *pg_private;
        struct bio_vec *bvec;
+       unsigned long flags;
        u64 start;
        u64 end;
+       int clear_writeback;
        int i;

        bio_for_each_segment_all(bvec, bio, i) {
                struct page *page = bvec->bv_page;
+               struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;

-               /* 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_SIZE) {
-                       if (bvec->bv_offset + bvec->bv_len != PAGE_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);
-               }
+               pg_private = NULL;
+               flags = 0;
+               clear_writeback = 1;

-               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;
+
+               if (root->sectorsize < PAGE_SIZE) {
+                       pg_private = (struct btrfs_page_private *)page->private;
+                       spin_lock_irqsave(&pg_private->io_lock, flags);
+               }

                end_extent_writepage(page, bio->bi_error, start, end);
-               end_page_writeback(page);
+
+               if (root->sectorsize < PAGE_SIZE) {
+                       clear_page_blks_state(page, 1 << BLK_STATE_IO, start,
+                                       end);
+                       clear_writeback = page_io_complete(page);
+                       spin_unlock_irqrestore(&pg_private->io_lock, flags);
+               }
+
+               if (clear_writeback)
+                       end_page_writeback(page);
        }

        bio_put(bio);
@@ -3486,7 +3473,6 @@ static noinline_for_stack int 
__extent_writepage_io(struct inode *inode,
        u64 block_start;
        u64 iosize;
        sector_t sector;
-       struct extent_state *cached_state = NULL;
        struct extent_map *em;
        struct block_device *bdev;
        size_t pg_offset = 0;
@@ -3538,20 +3524,29 @@ static noinline_for_stack int 
__extent_writepage_io(struct inode *inode,
                                                         page_end, NULL, 1);
                        break;
                }
-               em = epd->get_extent(inode, page, pg_offset, cur,
-                                    end - cur + 1, 1);
+
+               if (blocksize < PAGE_SIZE
+                       && !test_page_blks_state(page, BLK_STATE_DIRTY, cur,
+                                               cur + blocksize - 1, 1)) {
+                       cur += blocksize;
+                       continue;
+               }
+
+               pg_offset = cur & (PAGE_SIZE - 1);
+
+               em = epd->get_extent(inode, page, pg_offset, cur, blocksize, 1);
                if (IS_ERR_OR_NULL(em)) {
                        SetPageError(page);
                        ret = PTR_ERR_OR_ZERO(em);
                        break;
                }

-               extent_offset = cur - em->start;
                em_end = extent_map_end(em);
                BUG_ON(em_end <= cur);
                BUG_ON(end < cur);
-               iosize = min(em_end - cur, end - cur + 1);
-               iosize = ALIGN(iosize, blocksize);
+
+               iosize = blocksize;
+               extent_offset = cur - em->start;
                sector = (em->block_start + extent_offset) >> 9;
                bdev = em->bdev;
                block_start = em->block_start;
@@ -3559,65 +3554,64 @@ static noinline_for_stack int 
__extent_writepage_io(struct inode *inode,
                free_extent_map(em);
                em = 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) {
-                       /*
-                        * end_io notification does not happen here for
-                        * compressed extents
-                        */
-                       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++;
-                       }
+               ASSERT(!compressed);
+               ASSERT(block_start != EXTENT_MAP_INLINE);

+               if (block_start == EXTENT_MAP_HOLE) {
+                       if (blocksize < PAGE_SIZE) {
+                               if (test_page_blks_state(page, 
BLK_STATE_UPTODATE,
+                                                               cur, cur + 
iosize - 1,
+                                                               1)) {
+                                       clear_page_blks_state(page,
+                                                       1 << BLK_STATE_DIRTY, 
cur,
+                                                       cur + iosize - 1);
+                               } else {
+                                       BUG();
+                               }
+                       } else if (!PageUptodate(page)) {
+                                       BUG();
+                       }

No new BUG()'s. If we think its actually a possibility then return an error, otherwise use ASSERT.

                        cur += iosize;
-                       pg_offset += iosize;
                        continue;
                }

                max_nr = (i_size >> PAGE_SHIFT) + 1;

-               set_range_writeback(tree, cur, cur + iosize - 1);
+               if (blocksize < PAGE_SIZE)
+                       clear_page_blks_state(page,
+                                       1 << BLK_STATE_DIRTY, cur,
+                                       cur + iosize - 1);
+               set_page_writeback(page);
+
+               if (blocksize < PAGE_SIZE)
+                       set_page_blks_state(page, 1 << BLK_STATE_IO,
+                                       cur, cur + iosize - 1);
+
                if (!PageWriteback(page)) {
                        btrfs_err(BTRFS_I(inode)->root->fs_info,
-                                  "page %lu not writeback, cur %llu end %llu",
-                              page->index, cur, end);
+                               "page %lu not writeback, cur %llu end %llu",
+                               page->index, cur, end);
                }

                ret = submit_extent_page(write_flags, tree, wbc, page,
-                                        sector, iosize, pg_offset,
-                                        bdev, &epd->bio, max_nr,
-                                        end_bio_extent_writepage,
-                                        0, 0, 0, false);
+                                       sector, iosize, pg_offset,
+                                       bdev, &epd->bio, max_nr,
+                                       end_bio_extent_writepage,
+                                       0, 0, 0, false);

Whitespace change?

                if (ret)
                        SetPageError(page);

-               cur = cur + iosize;
-               pg_offset += iosize;
+               cur += iosize;
                nr++;
        }
 done:
        *nr_ret = nr;

 done_unlocked:
-
-       /* drop our reference on any cached states */
-       free_extent_state(cached_state);
        return ret;
 }

+

Random whitespace. Also for the whole series I'd like to see us do away with the if (sectorsize < PAGE_SIZE) everywhere and just push that down into the helpers. Thanks,

Josef
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to