* [PATCH 1/2] Btrfs: make mapping->writeback_index point to the last written page
@ 2016-03-08 0:56 Liu Bo
2016-03-08 0:56 ` [PATCH 2/2] Btrfs: cleanup error handling in extent_write_cached_pages Liu Bo
2016-03-08 12:34 ` [PATCH 1/2] Btrfs: make mapping->writeback_index point to the last written page Holger Hoffstätte
0 siblings, 2 replies; 3+ messages in thread
From: Liu Bo @ 2016-03-08 0:56 UTC (permalink / raw)
To: linux-btrfs; +Cc: Holger Hoffstätte
If sequential writer is writing in the middle of the page and it just redirties
the last written page by continuing from it.
In the above case this can end up with seeking back to that firstly redirtied
page after writing all the pages at the end of file because btrfs updates
mapping->writeback_index to 1 past the current one.
For non-cow filesystems, the cost is only about extra seek, while for cow
filesystems such as btrfs, it means unnecessary fragments.
To avoid it, we just need to continue writeback from the last written page.
This also updates btrfs to behave like what write_cache_pages() does, ie, bail
out immediately if there is an error in writepage().
<Ref: https://www.spinics.net/lists/linux-btrfs/msg52628.html>
Reported-by: Holger Hoffstätte <holger.hoffstaette@googlemail.com>
Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
---
fs/btrfs/extent_io.c | 32 ++++++++++++++++++++++++++------
1 file changed, 26 insertions(+), 6 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 392592d..1dfcffe 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3204,14 +3204,10 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
return ret;
}
-static noinline void update_nr_written(struct page *page,
- struct writeback_control *wbc,
- unsigned long nr_written)
+static void update_nr_written(struct page *page, struct writeback_control *wbc,
+ unsigned long nr_written)
{
wbc->nr_to_write -= nr_written;
- if (wbc->range_cyclic || (wbc->nr_to_write > 0 &&
- wbc->range_start == 0 && wbc->range_end == LLONG_MAX))
- page->mapping->writeback_index = page->index + nr_written;
}
/*
@@ -3932,6 +3928,8 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
int nr_pages;
pgoff_t index;
pgoff_t end; /* Inclusive */
+ pgoff_t done_index;
+ int range_whole = 0;
int scanned = 0;
int tag;
@@ -3954,6 +3952,8 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
} else {
index = wbc->range_start >> PAGE_CACHE_SHIFT;
end = wbc->range_end >> PAGE_CACHE_SHIFT;
+ if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
+ range_whole = 1;
scanned = 1;
}
if (wbc->sync_mode == WB_SYNC_ALL)
@@ -3963,6 +3963,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
retry:
if (wbc->sync_mode == WB_SYNC_ALL)
tag_pages_for_writeback(mapping, index, end);
+ done_index = index;
while (!done && !nr_to_write_done && (index <= end) &&
(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag,
min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
@@ -3972,6 +3973,7 @@ retry:
for (i = 0; i < nr_pages; i++) {
struct page *page = pvec.pages[i];
+ done_index = page->index;
/*
* At this point we hold neither mapping->tree_lock nor
* lock on the page itself: the page may be truncated or
@@ -4015,6 +4017,20 @@ retry:
}
if (!err && ret < 0)
err = ret;
+ if (ret < 0) {
+ /*
+ * done_index is set past this page,
+ * so media errors will not choke
+ * background writeout for the entire
+ * file. This has consequences for
+ * range_cyclic semantics (ie. it may
+ * not be suitable for data integrity
+ * writeout).
+ */
+ done_index = page->index + 1;
+ done = 1;
+ break;
+ }
/*
* the filesystem may choose to bump up nr_to_write.
@@ -4035,6 +4051,10 @@ retry:
index = 0;
goto retry;
}
+
+ if (wbc->range_cyclic || (wbc->nr_to_write > 0 && range_whole))
+ mapping->writeback_index = done_index;
+
btrfs_add_delayed_iput(inode);
return err;
}
--
2.5.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] Btrfs: cleanup error handling in extent_write_cached_pages
2016-03-08 0:56 [PATCH 1/2] Btrfs: make mapping->writeback_index point to the last written page Liu Bo
@ 2016-03-08 0:56 ` Liu Bo
2016-03-08 12:34 ` [PATCH 1/2] Btrfs: make mapping->writeback_index point to the last written page Holger Hoffstätte
1 sibling, 0 replies; 3+ messages in thread
From: Liu Bo @ 2016-03-08 0:56 UTC (permalink / raw)
To: linux-btrfs; +Cc: Holger Hoffstätte
Now that we bail out immediately if ->writepage() returns an error,
we don't need an extra error to retain the error code.
Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
---
fs/btrfs/extent_io.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 1dfcffe..08282ea 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3922,7 +3922,6 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
struct inode *inode = mapping->host;
int ret = 0;
int done = 0;
- int err = 0;
int nr_to_write_done = 0;
struct pagevec pvec;
int nr_pages;
@@ -4015,8 +4014,6 @@ retry:
unlock_page(page);
ret = 0;
}
- if (!err && ret < 0)
- err = ret;
if (ret < 0) {
/*
* done_index is set past this page,
@@ -4042,7 +4039,7 @@ retry:
pagevec_release(&pvec);
cond_resched();
}
- if (!scanned && !done && !err) {
+ if (!scanned && !done) {
/*
* We hit the last page and there is more work to be done: wrap
* back to the start of the file
@@ -4056,7 +4053,7 @@ retry:
mapping->writeback_index = done_index;
btrfs_add_delayed_iput(inode);
- return err;
+ return ret;
}
static void flush_epd_write_bio(struct extent_page_data *epd)
--
2.5.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] Btrfs: make mapping->writeback_index point to the last written page
2016-03-08 0:56 [PATCH 1/2] Btrfs: make mapping->writeback_index point to the last written page Liu Bo
2016-03-08 0:56 ` [PATCH 2/2] Btrfs: cleanup error handling in extent_write_cached_pages Liu Bo
@ 2016-03-08 12:34 ` Holger Hoffstätte
1 sibling, 0 replies; 3+ messages in thread
From: Holger Hoffstätte @ 2016-03-08 12:34 UTC (permalink / raw)
To: Liu Bo, linux-btrfs
On 03/08/16 01:56, Liu Bo wrote:
> If sequential writer is writing in the middle of the page and it just redirties
> the last written page by continuing from it.
>
> In the above case this can end up with seeking back to that firstly redirtied
> page after writing all the pages at the end of file because btrfs updates
> mapping->writeback_index to 1 past the current one.
>
> For non-cow filesystems, the cost is only about extra seek, while for cow
> filesystems such as btrfs, it means unnecessary fragments.
>
> To avoid it, we just need to continue writeback from the last written page.
>
> This also updates btrfs to behave like what write_cache_pages() does, ie, bail
> out immediately if there is an error in writepage().
>
> <Ref: https://www.spinics.net/lists/linux-btrfs/msg52628.html>
>
> Reported-by: Holger Hoffstätte <holger.hoffstaette@googlemail.com>
> Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
Very nice, seems to work as advertised. Can't speak for the data integrity
implications, but for the functionality of both patches:
Tested-by: Holger Hoffstätte <holger.hoffstaette@googlemail.com>
Thank you!
Holger
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-03-08 12:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-08 0:56 [PATCH 1/2] Btrfs: make mapping->writeback_index point to the last written page Liu Bo
2016-03-08 0:56 ` [PATCH 2/2] Btrfs: cleanup error handling in extent_write_cached_pages Liu Bo
2016-03-08 12:34 ` [PATCH 1/2] Btrfs: make mapping->writeback_index point to the last written page Holger Hoffstätte
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.