* (unknown),
@ 2010-06-16 16:33 Jan Kara
2010-06-16 16:33 ` [PATCH 1/2] radix-tree: Implement function radix_tree_range_tag_if_tagged Jan Kara
` (4 more replies)
0 siblings, 5 replies; 25+ messages in thread
From: Jan Kara @ 2010-06-16 16:33 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-mm, Andrew Morton, npiggin
Hello,
here is the fourth version of the writeback livelock avoidance patches
for data integrity writes. To quickly summarize the idea: we tag dirty
pages at the beginning of write_cache_pages with a new TOWRITE tag and
then write only tagged pages to avoid parallel writers to livelock us.
See changelogs of the patches for more details.
I have tested the patches with fsx and a test program I wrote which
checks that if we crash after fsync, the data is indeed on disk.
If there are no more concerns, can these patches get merged?
Honza
Changes since last version:
- tagging function was changed to stop after given amount of pages to
avoid keeping tree_lock and irqs disabled for too long
- changed names and updated comments as Andrew suggested
- measured memory impact and reported it in the changelog
Things suggested but not changed (I want to avoid going in circles ;):
- use tagging also for WB_SYNC_NONE writeback - there's problem with an
interaction with wbc->nr_to_write. If we tag all dirty pages, we can
spend too much time tagging when we write only a few pages in the end
because of nr_to_write. If we tag only say nr_to_write pages, we may
not have enough pages tagged because some pages are written out by
someone else and so we would have to restart and tagging would become
essentially useless. So my option is - switch to tagging for WB_SYNC_NONE
writeback if we can get rid of nr_to_write. But that's a story for
a different patch set.
- implement function for clearing several tags (TOWRITE, DIRTY) at once
- IMHO not worth it because we would save only conversion of page index
to radix tree offsets. The rest would have to be separate anyways. And
the interface would be incosistent as well...
- use __lookup_tag to implement radix_tree_range_tag_if_tagged - doesn't
quite work because __lookup_tag returns only leaf nodes so we'd have to
implement tree traversal anyways to tag also internal nodes.
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 1/2] radix-tree: Implement function radix_tree_range_tag_if_tagged
2010-06-16 16:33 (unknown), Jan Kara
@ 2010-06-16 16:33 ` Jan Kara
2010-06-18 22:18 ` Andrew Morton
2010-06-16 16:33 ` [PATCH 2/2] mm: Implement writeback livelock avoidance using page tagging Jan Kara
` (3 subsequent siblings)
4 siblings, 1 reply; 25+ messages in thread
From: Jan Kara @ 2010-06-16 16:33 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-mm, Andrew Morton, npiggin, Jan Kara
Implement function for setting one tag if another tag is set
for each item in given range.
Signed-off-by: Jan Kara <jack@suse.cz>
---
include/linux/radix-tree.h | 4 ++
lib/radix-tree.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 96 insertions(+), 0 deletions(-)
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 55ca73c..a4b00e9 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -192,6 +192,10 @@ unsigned int
radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results,
unsigned long first_index, unsigned int max_items,
unsigned int tag);
+unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
+ unsigned long *first_indexp, unsigned long last_index,
+ unsigned long nr_to_tag,
+ unsigned int fromtag, unsigned int totag);
int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag);
static inline void radix_tree_preload_end(void)
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 05da38b..549ce9c 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -609,6 +609,98 @@ int radix_tree_tag_get(struct radix_tree_root *root,
EXPORT_SYMBOL(radix_tree_tag_get);
/**
+ * radix_tree_range_tag_if_tagged - for each item in given range set given
+ * tag if item has another tag set
+ * @root: radix tree root
+ * @first_indexp: pointer to a starting index of a range to scan
+ * @last_index: last index of a range to scan
+ * @nr_to_tag: maximum number items to tag
+ * @iftag: tag index to test
+ * @settag: tag index to set if tested tag is set
+ *
+ * This function scans range of radix tree from first_index to last_index
+ * (inclusive). For each item in the range if iftag is set, the function sets
+ * also settag. The function stops either after tagging nr_to_tag items or
+ * after reaching last_index.
+ *
+ * The function returns number of leaves where the tag was set and sets
+ * *first_indexp to the first unscanned index.
+ */
+unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
+ unsigned long *first_indexp, unsigned long last_index,
+ unsigned long nr_to_tag,
+ unsigned int iftag, unsigned int settag)
+{
+ unsigned int height = root->height, shift;
+ unsigned long tagged = 0, index = *first_indexp;
+ struct radix_tree_node *open_slots[height], *slot;
+
+ last_index = min(last_index, radix_tree_maxindex(height));
+ if (index > last_index)
+ return 0;
+ if (!root_tag_get(root, iftag)) {
+ *first_indexp = last_index + 1;
+ return 0;
+ }
+ if (height == 0) {
+ *first_indexp = last_index + 1;
+ root_tag_set(root, settag);
+ return 1;
+ }
+
+ shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
+ slot = radix_tree_indirect_to_ptr(root->rnode);
+
+ for (;;) {
+ int offset;
+
+ offset = (index >> shift) & RADIX_TREE_MAP_MASK;
+ if (!slot->slots[offset])
+ goto next;
+ if (!tag_get(slot, iftag, offset))
+ goto next;
+ tag_set(slot, settag, offset);
+ if (height == 1) {
+ tagged++;
+ goto next;
+ }
+ /* Go down one level */
+ height--;
+ shift -= RADIX_TREE_MAP_SHIFT;
+ open_slots[height] = slot;
+ slot = slot->slots[offset];
+ continue;
+next:
+ /* Go to next item at level determined by 'shift' */
+ index = ((index >> shift) + 1) << shift;
+ if (index > last_index)
+ break;
+ if (tagged > nr_to_tag)
+ break;
+ while (((index >> shift) & RADIX_TREE_MAP_MASK) == 0) {
+ /*
+ * We've fully scanned this node. Go up. Because
+ * last_index is guaranteed to be in the tree, what
+ * we do below cannot wander astray.
+ */
+ slot = open_slots[height];
+ height++;
+ shift += RADIX_TREE_MAP_SHIFT;
+ }
+ }
+ /*
+ * The iftag must have been set somewhere because otherwise
+ * we would return immediated at the beginning of the function
+ */
+ root_tag_set(root, settag);
+ *first_indexp = index;
+
+ return tagged;
+}
+EXPORT_SYMBOL(radix_tree_range_tag_if_tagged);
+
+
+/**
* radix_tree_next_hole - find the next hole (not-present entry)
* @root: tree root
* @index: index key
--
1.6.4.2
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 2/2] mm: Implement writeback livelock avoidance using page tagging
2010-06-16 16:33 (unknown), Jan Kara
2010-06-16 16:33 ` [PATCH 1/2] radix-tree: Implement function radix_tree_range_tag_if_tagged Jan Kara
@ 2010-06-16 16:33 ` Jan Kara
2010-06-18 22:21 ` Andrew Morton
2010-06-16 22:15 ` your mail Dave Chinner
` (2 subsequent siblings)
4 siblings, 1 reply; 25+ messages in thread
From: Jan Kara @ 2010-06-16 16:33 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-mm, Andrew Morton, npiggin, Jan Kara
We try to avoid livelocks of writeback when some steadily creates
dirty pages in a mapping we are writing out. For memory-cleaning
writeback, using nr_to_write works reasonably well but we cannot
really use it for data integrity writeback. This patch tries to
solve the problem.
The idea is simple: Tag all pages that should be written back
with a special tag (TOWRITE) in the radix tree. This can be done
rather quickly and thus livelocks should not happen in practice.
Then we start doing the hard work of locking pages and sending
them to disk only for those pages that have TOWRITE tag set.
Note: Adding new radix tree tag grows radix tree node from 288 to
296 bytes for 32-bit archs and from 552 to 560 bytes for 64-bit archs.
However, the number of slab/slub items per page remains the same
(13 and 7 respectively).
Signed-off-by: Jan Kara <jack@suse.cz>
---
include/linux/fs.h | 1 +
include/linux/radix-tree.h | 2 +-
mm/page-writeback.c | 69 +++++++++++++++++++++++++++++++++-----------
3 files changed, 54 insertions(+), 18 deletions(-)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 471e1ff..664674e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -685,6 +685,7 @@ struct block_device {
*/
#define PAGECACHE_TAG_DIRTY 0
#define PAGECACHE_TAG_WRITEBACK 1
+#define PAGECACHE_TAG_TOWRITE 2
int mapping_tagged(struct address_space *mapping, int tag);
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index a4b00e9..634b8e6 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -55,7 +55,7 @@ static inline int radix_tree_is_indirect_ptr(void *ptr)
/*** radix-tree API starts here ***/
-#define RADIX_TREE_MAX_TAGS 2
+#define RADIX_TREE_MAX_TAGS 3
/* root tags are stored in gfp_mask, shifted by __GFP_BITS_SHIFT */
struct radix_tree_root {
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index bbd396a..1cb043e 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -807,6 +807,40 @@ void __init page_writeback_init(void)
}
/**
+ * tag_pages_for_writeback - tag pages to be written by write_cache_pages
+ * @mapping: address space structure to write
+ * @start: starting page index
+ * @end: ending page index (inclusive)
+ *
+ * This function scans the page range from @start to @end (inclusive) and tags
+ * all pages that have DIRTY tag set with a special TOWRITE tag. The idea is
+ * that write_cache_pages (or whoever calls this function) will then use
+ * TOWRITE tag to identify pages eligible for writeback. This mechanism is
+ * used to avoid livelocking of writeback by a process steadily creating new
+ * dirty pages in the file (thus it is important for this function to be quick
+ * so that it can tag pages faster than a dirtying process can create them).
+ */
+/*
+ * We tag pages in batches of WRITEBACK_TAG_BATCH to reduce tree_lock latency.
+ */
+#define WRITEBACK_TAG_BATCH 4096
+void tag_pages_for_writeback(struct address_space *mapping,
+ pgoff_t start, pgoff_t end)
+{
+ unsigned long tagged;
+
+ do {
+ spin_lock_irq(&mapping->tree_lock);
+ tagged = radix_tree_range_tag_if_tagged(&mapping->page_tree,
+ &start, end, WRITEBACK_TAG_BATCH,
+ PAGECACHE_TAG_DIRTY, PAGECACHE_TAG_TOWRITE);
+ spin_unlock_irq(&mapping->tree_lock);
+ cond_resched();
+ } while (tagged >= WRITEBACK_TAG_BATCH);
+}
+EXPORT_SYMBOL(tag_pages_for_writeback);
+
+/**
* write_cache_pages - walk the list of dirty pages of the given address space and write all of them.
* @mapping: address space structure to write
* @wbc: subtract the number of written pages from *@wbc->nr_to_write
@@ -820,6 +854,13 @@ void __init page_writeback_init(void)
* the call was made get new I/O started against them. If wbc->sync_mode is
* WB_SYNC_ALL then we were called for data integrity and we must wait for
* existing IO to complete.
+ *
+ * To avoid livelocks (when other process dirties new pages), we first tag
+ * pages which should be written back with TOWRITE tag and only then start
+ * writing them. For data-integrity sync we have to be careful so that we do
+ * not miss some pages (e.g., because some other process has cleared TOWRITE
+ * tag we set). The rule we follow is that TOWRITE tag can be cleared only
+ * by the process clearing the DIRTY tag (and submitting the page for IO).
*/
int write_cache_pages(struct address_space *mapping,
struct writeback_control *wbc, writepage_t writepage,
@@ -835,6 +876,7 @@ int write_cache_pages(struct address_space *mapping,
pgoff_t done_index;
int cycled;
int range_whole = 0;
+ int tag;
pagevec_init(&pvec, 0);
if (wbc->range_cyclic) {
@@ -851,29 +893,19 @@ int write_cache_pages(struct address_space *mapping,
if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
range_whole = 1;
cycled = 1; /* ignore range_cyclic tests */
-
- /*
- * If this is a data integrity sync, cap the writeback to the
- * current end of file. Any extension to the file that occurs
- * after this is a new write and we don't need to write those
- * pages out to fulfil our data integrity requirements. If we
- * try to write them out, we can get stuck in this scan until
- * the concurrent writer stops adding dirty pages and extending
- * EOF.
- */
- if (wbc->sync_mode == WB_SYNC_ALL &&
- wbc->range_end == LLONG_MAX) {
- end = i_size_read(mapping->host) >> PAGE_CACHE_SHIFT;
- }
}
-
+ if (wbc->sync_mode == WB_SYNC_ALL)
+ tag = PAGECACHE_TAG_TOWRITE;
+ else
+ tag = PAGECACHE_TAG_DIRTY;
retry:
+ if (wbc->sync_mode == WB_SYNC_ALL)
+ tag_pages_for_writeback(mapping, index, end);
done_index = index;
while (!done && (index <= end)) {
int i;
- nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
- PAGECACHE_TAG_DIRTY,
+ nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag,
min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
if (nr_pages == 0)
break;
@@ -1329,6 +1361,9 @@ int test_set_page_writeback(struct page *page)
radix_tree_tag_clear(&mapping->page_tree,
page_index(page),
PAGECACHE_TAG_DIRTY);
+ radix_tree_tag_clear(&mapping->page_tree,
+ page_index(page),
+ PAGECACHE_TAG_TOWRITE);
spin_unlock_irqrestore(&mapping->tree_lock, flags);
} else {
ret = TestSetPageWriteback(page);
--
1.6.4.2
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: your mail
2010-06-16 16:33 (unknown), Jan Kara
2010-06-16 16:33 ` [PATCH 1/2] radix-tree: Implement function radix_tree_range_tag_if_tagged Jan Kara
2010-06-16 16:33 ` [PATCH 2/2] mm: Implement writeback livelock avoidance using page tagging Jan Kara
@ 2010-06-16 22:15 ` Dave Chinner
2010-06-17 7:43 ` [PATCH 0/2 v4] Writeback livelock avoidance for data integrity writes Jan Kara
2010-06-17 9:11 ` Jan Kara
2010-06-22 2:59 ` your mail Wu Fengguang
4 siblings, 1 reply; 25+ messages in thread
From: Dave Chinner @ 2010-06-16 22:15 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-mm, Andrew Morton, npiggin
On Wed, Jun 16, 2010 at 06:33:49PM +0200, Jan Kara wrote:
> Hello,
>
> here is the fourth version of the writeback livelock avoidance patches
> for data integrity writes. To quickly summarize the idea: we tag dirty
> pages at the beginning of write_cache_pages with a new TOWRITE tag and
> then write only tagged pages to avoid parallel writers to livelock us.
> See changelogs of the patches for more details.
> I have tested the patches with fsx and a test program I wrote which
> checks that if we crash after fsync, the data is indeed on disk.
> If there are no more concerns, can these patches get merged?
Has it been run through xfstests? I'd suggest doing that at least
with XFS as there are several significant sync sanity tests for XFS
in the suite...
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/2 v4] Writeback livelock avoidance for data integrity writes
2010-06-16 22:15 ` your mail Dave Chinner
@ 2010-06-17 7:43 ` Jan Kara
2010-06-18 6:11 ` Dave Chinner
0 siblings, 1 reply; 25+ messages in thread
From: Jan Kara @ 2010-06-17 7:43 UTC (permalink / raw)
To: Dave Chinner; +Cc: Jan Kara, linux-fsdevel, linux-mm, Andrew Morton, npiggin
On Thu 17-06-10 08:15:41, Dave Chinner wrote:
> On Wed, Jun 16, 2010 at 06:33:49PM +0200, Jan Kara wrote:
> > Hello,
> >
> > here is the fourth version of the writeback livelock avoidance patches
> > for data integrity writes. To quickly summarize the idea: we tag dirty
> > pages at the beginning of write_cache_pages with a new TOWRITE tag and
> > then write only tagged pages to avoid parallel writers to livelock us.
> > See changelogs of the patches for more details.
> > I have tested the patches with fsx and a test program I wrote which
> > checks that if we crash after fsync, the data is indeed on disk.
> > If there are no more concerns, can these patches get merged?
>
> Has it been run through xfstests? I'd suggest doing that at least
> with XFS as there are several significant sync sanity tests for XFS
> in the suite...
I've run it through XFSQA with ext3 & ext4 before submitting. I'm running
a test with xfs now.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 0/2 v4] Writeback livelock avoidance for data integrity writes
2010-06-16 16:33 (unknown), Jan Kara
` (2 preceding siblings ...)
2010-06-16 22:15 ` your mail Dave Chinner
@ 2010-06-17 9:11 ` Jan Kara
2010-06-22 2:59 ` your mail Wu Fengguang
4 siblings, 0 replies; 25+ messages in thread
From: Jan Kara @ 2010-06-17 9:11 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-mm, Andrew Morton, npiggin
Sorry for replying to my email but I forgot to set a subject while doing
git send-email. So at least set it now.
Honza
On Wed 16-06-10 18:33:49, Jan Kara wrote:
> Hello,
>
> here is the fourth version of the writeback livelock avoidance patches
> for data integrity writes. To quickly summarize the idea: we tag dirty
> pages at the beginning of write_cache_pages with a new TOWRITE tag and
> then write only tagged pages to avoid parallel writers to livelock us.
> See changelogs of the patches for more details.
> I have tested the patches with fsx and a test program I wrote which
> checks that if we crash after fsync, the data is indeed on disk.
> If there are no more concerns, can these patches get merged?
>
> Honza
>
> Changes since last version:
> - tagging function was changed to stop after given amount of pages to
> avoid keeping tree_lock and irqs disabled for too long
> - changed names and updated comments as Andrew suggested
> - measured memory impact and reported it in the changelog
>
> Things suggested but not changed (I want to avoid going in circles ;):
> - use tagging also for WB_SYNC_NONE writeback - there's problem with an
> interaction with wbc->nr_to_write. If we tag all dirty pages, we can
> spend too much time tagging when we write only a few pages in the end
> because of nr_to_write. If we tag only say nr_to_write pages, we may
> not have enough pages tagged because some pages are written out by
> someone else and so we would have to restart and tagging would become
> essentially useless. So my option is - switch to tagging for WB_SYNC_NONE
> writeback if we can get rid of nr_to_write. But that's a story for
> a different patch set.
> - implement function for clearing several tags (TOWRITE, DIRTY) at once
> - IMHO not worth it because we would save only conversion of page index
> to radix tree offsets. The rest would have to be separate anyways. And
> the interface would be incosistent as well...
> - use __lookup_tag to implement radix_tree_range_tag_if_tagged - doesn't
> quite work because __lookup_tag returns only leaf nodes so we'd have to
> implement tree traversal anyways to tag also internal nodes.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/2 v4] Writeback livelock avoidance for data integrity writes
2010-06-17 7:43 ` [PATCH 0/2 v4] Writeback livelock avoidance for data integrity writes Jan Kara
@ 2010-06-18 6:11 ` Dave Chinner
2010-06-18 7:01 ` Nick Piggin
0 siblings, 1 reply; 25+ messages in thread
From: Dave Chinner @ 2010-06-18 6:11 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-mm, Andrew Morton, npiggin
On Thu, Jun 17, 2010 at 09:43:50AM +0200, Jan Kara wrote:
> On Thu 17-06-10 08:15:41, Dave Chinner wrote:
> > On Wed, Jun 16, 2010 at 06:33:49PM +0200, Jan Kara wrote:
> > > Hello,
> > >
> > > here is the fourth version of the writeback livelock avoidance patches
> > > for data integrity writes. To quickly summarize the idea: we tag dirty
> > > pages at the beginning of write_cache_pages with a new TOWRITE tag and
> > > then write only tagged pages to avoid parallel writers to livelock us.
> > > See changelogs of the patches for more details.
> > > I have tested the patches with fsx and a test program I wrote which
> > > checks that if we crash after fsync, the data is indeed on disk.
> > > If there are no more concerns, can these patches get merged?
> >
> > Has it been run through xfstests? I'd suggest doing that at least
> > with XFS as there are several significant sync sanity tests for XFS
> > in the suite...
> I've run it through XFSQA with ext3 & ext4 before submitting. I'm running
> a test with xfs now.
Cool. if there are no problems then I'm happy with this ;)
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/2 v4] Writeback livelock avoidance for data integrity writes
2010-06-18 6:11 ` Dave Chinner
@ 2010-06-18 7:01 ` Nick Piggin
0 siblings, 0 replies; 25+ messages in thread
From: Nick Piggin @ 2010-06-18 7:01 UTC (permalink / raw)
To: Dave Chinner; +Cc: Jan Kara, linux-fsdevel, linux-mm, Andrew Morton
On Fri, Jun 18, 2010 at 04:11:11PM +1000, Dave Chinner wrote:
> On Thu, Jun 17, 2010 at 09:43:50AM +0200, Jan Kara wrote:
> > On Thu 17-06-10 08:15:41, Dave Chinner wrote:
> > > On Wed, Jun 16, 2010 at 06:33:49PM +0200, Jan Kara wrote:
> > > > Hello,
> > > >
> > > > here is the fourth version of the writeback livelock avoidance patches
> > > > for data integrity writes. To quickly summarize the idea: we tag dirty
> > > > pages at the beginning of write_cache_pages with a new TOWRITE tag and
> > > > then write only tagged pages to avoid parallel writers to livelock us.
> > > > See changelogs of the patches for more details.
> > > > I have tested the patches with fsx and a test program I wrote which
> > > > checks that if we crash after fsync, the data is indeed on disk.
> > > > If there are no more concerns, can these patches get merged?
> > >
> > > Has it been run through xfstests? I'd suggest doing that at least
> > > with XFS as there are several significant sync sanity tests for XFS
> > > in the suite...
> > I've run it through XFSQA with ext3 & ext4 before submitting. I'm running
> > a test with xfs now.
>
> Cool. if there are no problems then I'm happy with this ;)
Agreed.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/2] radix-tree: Implement function radix_tree_range_tag_if_tagged
2010-06-16 16:33 ` [PATCH 1/2] radix-tree: Implement function radix_tree_range_tag_if_tagged Jan Kara
@ 2010-06-18 22:18 ` Andrew Morton
2010-06-21 12:09 ` Nick Piggin
0 siblings, 1 reply; 25+ messages in thread
From: Andrew Morton @ 2010-06-18 22:18 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-mm, npiggin
On Wed, 16 Jun 2010 18:33:50 +0200
Jan Kara <jack@suse.cz> wrote:
> Implement function for setting one tag if another tag is set
> for each item in given range.
>
These two patches look OK to me.
fwiw I have a userspace test harness for radix-tree.c:
http://userweb.kernel.org/~akpm/stuff/rtth.tar.gz. Nick used it for a
while and updated it somewhat, but it's probably rather bitrotted and
surely needs to be taught how to test the post-2006 additions.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] mm: Implement writeback livelock avoidance using page tagging
2010-06-16 16:33 ` [PATCH 2/2] mm: Implement writeback livelock avoidance using page tagging Jan Kara
@ 2010-06-18 22:21 ` Andrew Morton
2010-06-21 12:42 ` Jan Kara
0 siblings, 1 reply; 25+ messages in thread
From: Andrew Morton @ 2010-06-18 22:21 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-mm, npiggin
On Wed, 16 Jun 2010 18:33:51 +0200
Jan Kara <jack@suse.cz> wrote:
> We try to avoid livelocks of writeback when some steadily creates
> dirty pages in a mapping we are writing out. For memory-cleaning
> writeback, using nr_to_write works reasonably well but we cannot
> really use it for data integrity writeback. This patch tries to
> solve the problem.
>
> The idea is simple: Tag all pages that should be written back
> with a special tag (TOWRITE) in the radix tree. This can be done
> rather quickly and thus livelocks should not happen in practice.
> Then we start doing the hard work of locking pages and sending
> them to disk only for those pages that have TOWRITE tag set.
>
> Note: Adding new radix tree tag grows radix tree node from 288 to
> 296 bytes for 32-bit archs and from 552 to 560 bytes for 64-bit archs.
> However, the number of slab/slub items per page remains the same
> (13 and 7 respectively).
>
>
> ...
>
> +void tag_pages_for_writeback(struct address_space *mapping,
> + pgoff_t start, pgoff_t end)
> +{
> + unsigned long tagged;
> +
> + do {
> + spin_lock_irq(&mapping->tree_lock);
> + tagged = radix_tree_range_tag_if_tagged(&mapping->page_tree,
> + &start, end, WRITEBACK_TAG_BATCH,
> + PAGECACHE_TAG_DIRTY, PAGECACHE_TAG_TOWRITE);
> + spin_unlock_irq(&mapping->tree_lock);
> + cond_resched();
> + } while (tagged >= WRITEBACK_TAG_BATCH);
> +}
grumble. (tagged > WRITEBACK_TAG_BATCH) would be a bug, wouldn't it?
So the ">=" is hiding a bug.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/2] radix-tree: Implement function radix_tree_range_tag_if_tagged
2010-06-18 22:18 ` Andrew Morton
@ 2010-06-21 12:09 ` Nick Piggin
2010-06-21 22:43 ` Jan Kara
2010-06-23 13:42 ` Jan Kara
0 siblings, 2 replies; 25+ messages in thread
From: Nick Piggin @ 2010-06-21 12:09 UTC (permalink / raw)
To: Andrew Morton; +Cc: Jan Kara, linux-fsdevel, linux-mm
On Fri, Jun 18, 2010 at 03:18:24PM -0700, Andrew Morton wrote:
> On Wed, 16 Jun 2010 18:33:50 +0200
> Jan Kara <jack@suse.cz> wrote:
>
> > Implement function for setting one tag if another tag is set
> > for each item in given range.
> >
>
> These two patches look OK to me.
>
> fwiw I have a userspace test harness for radix-tree.c:
> http://userweb.kernel.org/~akpm/stuff/rtth.tar.gz. Nick used it for a
> while and updated it somewhat, but it's probably rather bitrotted and
> surely needs to be taught how to test the post-2006 additions.
>
Main thing I did was add RCU support (pretty dumb RCU but it found
a couple of bugs), and add some more tests. I'll try to find it...
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] mm: Implement writeback livelock avoidance using page tagging
2010-06-18 22:21 ` Andrew Morton
@ 2010-06-21 12:42 ` Jan Kara
0 siblings, 0 replies; 25+ messages in thread
From: Jan Kara @ 2010-06-21 12:42 UTC (permalink / raw)
To: Andrew Morton; +Cc: Jan Kara, linux-fsdevel, linux-mm, npiggin
On Fri 18-06-10 15:21:28, Andrew Morton wrote:
> On Wed, 16 Jun 2010 18:33:51 +0200
> Jan Kara <jack@suse.cz> wrote:
>
> > We try to avoid livelocks of writeback when some steadily creates
> > dirty pages in a mapping we are writing out. For memory-cleaning
> > writeback, using nr_to_write works reasonably well but we cannot
> > really use it for data integrity writeback. This patch tries to
> > solve the problem.
> >
> > The idea is simple: Tag all pages that should be written back
> > with a special tag (TOWRITE) in the radix tree. This can be done
> > rather quickly and thus livelocks should not happen in practice.
> > Then we start doing the hard work of locking pages and sending
> > them to disk only for those pages that have TOWRITE tag set.
> >
> > Note: Adding new radix tree tag grows radix tree node from 288 to
> > 296 bytes for 32-bit archs and from 552 to 560 bytes for 64-bit archs.
> > However, the number of slab/slub items per page remains the same
> > (13 and 7 respectively).
> >
> >
> > ...
> >
> > +void tag_pages_for_writeback(struct address_space *mapping,
> > + pgoff_t start, pgoff_t end)
> > +{
> > + unsigned long tagged;
> > +
> > + do {
> > + spin_lock_irq(&mapping->tree_lock);
> > + tagged = radix_tree_range_tag_if_tagged(&mapping->page_tree,
> > + &start, end, WRITEBACK_TAG_BATCH,
> > + PAGECACHE_TAG_DIRTY, PAGECACHE_TAG_TOWRITE);
> > + spin_unlock_irq(&mapping->tree_lock);
> > + cond_resched();
> > + } while (tagged >= WRITEBACK_TAG_BATCH);
> > +}
>
> grumble. (tagged > WRITEBACK_TAG_BATCH) would be a bug, wouldn't it?
> So the ">=" is hiding a bug.
Good point. I'll add WARN_ON_ONCE when tagged is > WRITEBACK_TAG_BATCH.
That will make the bug vissible while still continuing the writeback
(because it's a situation in which we can still happily continue). Should
I send you a new version of the patch or will you just fold that one line
in?
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/2] radix-tree: Implement function radix_tree_range_tag_if_tagged
2010-06-21 12:09 ` Nick Piggin
@ 2010-06-21 22:43 ` Jan Kara
2010-06-23 13:42 ` Jan Kara
1 sibling, 0 replies; 25+ messages in thread
From: Jan Kara @ 2010-06-21 22:43 UTC (permalink / raw)
To: Nick Piggin; +Cc: Andrew Morton, Jan Kara, linux-fsdevel, linux-mm
On Mon 21-06-10 22:09:34, Nick Piggin wrote:
> On Fri, Jun 18, 2010 at 03:18:24PM -0700, Andrew Morton wrote:
> > On Wed, 16 Jun 2010 18:33:50 +0200
> > Jan Kara <jack@suse.cz> wrote:
> >
> > > Implement function for setting one tag if another tag is set
> > > for each item in given range.
> > >
> >
> > These two patches look OK to me.
> >
> > fwiw I have a userspace test harness for radix-tree.c:
> > http://userweb.kernel.org/~akpm/stuff/rtth.tar.gz. Nick used it for a
> > while and updated it somewhat, but it's probably rather bitrotted and
> > surely needs to be taught how to test the post-2006 additions.
> >
>
> Main thing I did was add RCU support (pretty dumb RCU but it found
> a couple of bugs), and add some more tests. I'll try to find it...
Please send them my way if you can find them. I'll gladly run those tests
(and extend them to check also my new function).
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2010-06-16 16:33 (unknown), Jan Kara
` (3 preceding siblings ...)
2010-06-17 9:11 ` Jan Kara
@ 2010-06-22 2:59 ` Wu Fengguang
2010-06-22 13:54 ` Jan Kara
4 siblings, 1 reply; 25+ messages in thread
From: Wu Fengguang @ 2010-06-22 2:59 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-mm, Andrew Morton, npiggin
> - use tagging also for WB_SYNC_NONE writeback - there's problem with an
> interaction with wbc->nr_to_write. If we tag all dirty pages, we can
> spend too much time tagging when we write only a few pages in the end
> because of nr_to_write. If we tag only say nr_to_write pages, we may
> not have enough pages tagged because some pages are written out by
> someone else and so we would have to restart and tagging would become
This could be addressed by ignoring nr_to_write for the WB_SYNC_NONE
writeback triggered by sync(). write_cache_pages() already ignored
nr_to_write for WB_SYNC_ALL.
> essentially useless. So my option is - switch to tagging for WB_SYNC_NONE
> writeback if we can get rid of nr_to_write. But that's a story for
> a different patch set.
Besides introducing overheads, it will be a policy change in which the
system loses control to somehow "throttle" writeback of huge files.
So it may be safer to enlarge nr_to_write instead of canceling it totally.
Thanks,
Fengguang
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2010-06-22 2:59 ` your mail Wu Fengguang
@ 2010-06-22 13:54 ` Jan Kara
2010-06-22 14:12 ` Wu Fengguang
0 siblings, 1 reply; 25+ messages in thread
From: Jan Kara @ 2010-06-22 13:54 UTC (permalink / raw)
To: Wu Fengguang; +Cc: Jan Kara, linux-fsdevel, linux-mm, Andrew Morton, npiggin
On Tue 22-06-10 10:59:41, Wu Fengguang wrote:
> > - use tagging also for WB_SYNC_NONE writeback - there's problem with an
> > interaction with wbc->nr_to_write. If we tag all dirty pages, we can
> > spend too much time tagging when we write only a few pages in the end
> > because of nr_to_write. If we tag only say nr_to_write pages, we may
> > not have enough pages tagged because some pages are written out by
> > someone else and so we would have to restart and tagging would become
>
> This could be addressed by ignoring nr_to_write for the WB_SYNC_NONE
> writeback triggered by sync(). write_cache_pages() already ignored
> nr_to_write for WB_SYNC_ALL.
We could do that but frankly, I'm not very fond of adding more special
cases to writeback code than strictly necessary...
> > essentially useless. So my option is - switch to tagging for WB_SYNC_NONE
> > writeback if we can get rid of nr_to_write. But that's a story for
> > a different patch set.
>
> Besides introducing overheads, it will be a policy change in which the
> system loses control to somehow "throttle" writeback of huge files.
Yes, but if we guarantee we cannot livelock on a single file, do we care?
Memory management does not care because it's getting rid of dirty pages
which is what it wants. User might care but actually writing out files in
the order they were dirtied (i.e., the order user written them) is quite
natural so it's not a "surprising" behavior. And I don't think we can
assume that data in those small files are more valuable than data in the
large file and thus should be written earlier...
With the overhead you are right that tagging is more expensive than
checking nr_to_write limit...
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2010-06-22 13:54 ` Jan Kara
@ 2010-06-22 14:12 ` Wu Fengguang
0 siblings, 0 replies; 25+ messages in thread
From: Wu Fengguang @ 2010-06-22 14:12 UTC (permalink / raw)
To: Jan Kara
Cc: linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Andrew Morton,
npiggin@suse.de
On Tue, Jun 22, 2010 at 09:54:58PM +0800, Jan Kara wrote:
> On Tue 22-06-10 10:59:41, Wu Fengguang wrote:
> > > - use tagging also for WB_SYNC_NONE writeback - there's problem with an
> > > interaction with wbc->nr_to_write. If we tag all dirty pages, we can
> > > spend too much time tagging when we write only a few pages in the end
> > > because of nr_to_write. If we tag only say nr_to_write pages, we may
> > > not have enough pages tagged because some pages are written out by
> > > someone else and so we would have to restart and tagging would become
> >
> > This could be addressed by ignoring nr_to_write for the WB_SYNC_NONE
> > writeback triggered by sync(). write_cache_pages() already ignored
> > nr_to_write for WB_SYNC_ALL.
> We could do that but frankly, I'm not very fond of adding more special
> cases to writeback code than strictly necessary...
So do me. However for this case we only need to broaden the special case test:
if (nr_to_write > 0) {
nr_to_write--;
if (nr_to_write == 0 &&
- wbc->sync_mode == WB_SYNC_NONE) {
+ !wbc->for_sync) {
> > > essentially useless. So my option is - switch to tagging for WB_SYNC_NONE
> > > writeback if we can get rid of nr_to_write. But that's a story for
> > > a different patch set.
> >
> > Besides introducing overheads, it will be a policy change in which the
> > system loses control to somehow "throttle" writeback of huge files.
> Yes, but if we guarantee we cannot livelock on a single file, do we care?
> Memory management does not care because it's getting rid of dirty pages
> which is what it wants. User might care but actually writing out files in
> the order they were dirtied (i.e., the order user written them) is quite
> natural so it's not a "surprising" behavior. And I don't think we can
> assume that data in those small files are more valuable than data in the
> large file and thus should be written earlier...
It could be a surprising behavior when, there is a 4GB dirty file and
100 small dirty files. The user may expect the 100 small dirty files
be synced to disk after 30s. However without nr_to_write, they could
be delayed by the 4GB file for 40 more seconds. Now if something goes
wrong in between and the small dirty files happen to include some
.c/.tex/.txt/... files.
Small files are more likely your precious documents that are typed in
word-by-word and perhaps the most important data you want to protect.
Naturally you'll want them enjoy more priority than large files.
> With the overhead you are right that tagging is more expensive than
> checking nr_to_write limit...
Thanks,
Fengguang
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/2] radix-tree: Implement function radix_tree_range_tag_if_tagged
2010-06-21 12:09 ` Nick Piggin
2010-06-21 22:43 ` Jan Kara
@ 2010-06-23 13:42 ` Jan Kara
1 sibling, 0 replies; 25+ messages in thread
From: Jan Kara @ 2010-06-23 13:42 UTC (permalink / raw)
To: Nick Piggin; +Cc: Andrew Morton, Jan Kara, linux-fsdevel, linux-mm
On Mon 21-06-10 22:09:34, Nick Piggin wrote:
> On Fri, Jun 18, 2010 at 03:18:24PM -0700, Andrew Morton wrote:
> > On Wed, 16 Jun 2010 18:33:50 +0200
> > Jan Kara <jack@suse.cz> wrote:
> >
> > > Implement function for setting one tag if another tag is set
> > > for each item in given range.
> > >
> >
> > These two patches look OK to me.
> >
> > fwiw I have a userspace test harness for radix-tree.c:
> > http://userweb.kernel.org/~akpm/stuff/rtth.tar.gz. Nick used it for a
> > while and updated it somewhat, but it's probably rather bitrotted and
> > surely needs to be taught how to test the post-2006 additions.
> >
>
> Main thing I did was add RCU support (pretty dumb RCU but it found
> a couple of bugs), and add some more tests. I'll try to find it...
Nick, any luck with finding updated tests?
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2011-05-03 13:08 ` (unknown), Surbhi Palande
@ 2011-05-03 13:46 ` Jan Kara
2011-05-03 13:56 ` Surbhi Palande
0 siblings, 1 reply; 25+ messages in thread
From: Jan Kara @ 2011-05-03 13:46 UTC (permalink / raw)
To: Surbhi Palande
Cc: jack, toshi.okajima, tytso, m.mizuma, adilger.kernel, linux-ext4,
linux-fsdevel, sandeen
On Tue 03-05-11 16:08:36, Surbhi Palande wrote:
> On munmap() zap_pte_range() is called which dirties the PTE dirty pages as
> Toshiyuki pointed out.
>
> zap_pte_range()
> mapping->a_ops->set_page_dirty (= ext4_journalled_set_page_dirty)
>
> So, I think that it is here that we should do the checking for a ext4 F.S
> frozen state and also prevent a parallel ext4 F.S freeze from happening.
>
> Attaching a patch for initial review. Please do let me know your thoughts!
This is definitely the wrong place. ->set_page_dirty() callbacks are
called with various locks held and the page need not be locked (thus
dereferencing page->mapping is oopsable). Moreover this particular callback
is called only in data=journal mode.
Believe me, the right place is page_mkwrite() - you have to catch the
read-only => read-write page transition. Once the page is mapped
read-write, you've already lost the race.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2011-05-03 13:46 ` your mail Jan Kara
@ 2011-05-03 13:56 ` Surbhi Palande
2011-05-03 15:26 ` Surbhi Palande
2011-05-03 15:36 ` Jan Kara
0 siblings, 2 replies; 25+ messages in thread
From: Surbhi Palande @ 2011-05-03 13:56 UTC (permalink / raw)
To: Jan Kara
Cc: toshi.okajima, tytso, m.mizuma, adilger.kernel, linux-ext4,
linux-fsdevel, sandeen
On 05/03/2011 04:46 PM, Jan Kara wrote:
> On Tue 03-05-11 16:08:36, Surbhi Palande wrote:
Sorry for missing the subject line :(
>> On munmap() zap_pte_range() is called which dirties the PTE dirty pages as
>> Toshiyuki pointed out.
>>
>> zap_pte_range()
>> mapping->a_ops->set_page_dirty (= ext4_journalled_set_page_dirty)
>>
>> So, I think that it is here that we should do the checking for a ext4 F.S
>> frozen state and also prevent a parallel ext4 F.S freeze from happening.
>>
>> Attaching a patch for initial review. Please do let me know your thoughts!
> This is definitely the wrong place. ->set_page_dirty() callbacks are
> called with various locks held and the page need not be locked (thus
> dereferencing page->mapping is oopsable). Moreover this particular callback
> is called only in data=journal mode.
Ok! Thanks for that!
>
> Believe me, the right place is page_mkwrite() - you have to catch the
> read-only => read-write page transition. Once the page is mapped
> read-write, you've already lost the race.
My only point is:
1) something should prevent the freeze from happening. We cant merely
check the vfs_check_frozen()?
And this should be done where the page is marked dirty.Also, I thought
that the page is marked read-write only in the page table in the
__do_page_fault()? i.e the zap_pte_range() marks them dirty in the page
cache? Is this understanding right?
IMHO, whatever code dirties the page in the page cache should call a F.S
specific function and let it _prevent_ a fsfreeze while the page is
getting dirtied, so that a freeze called after this point flushes this page!
Warm Regards,
Surbhi.
>
> Honza
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2011-05-03 13:56 ` Surbhi Palande
@ 2011-05-03 15:26 ` Surbhi Palande
2011-05-03 15:36 ` Jan Kara
1 sibling, 0 replies; 25+ messages in thread
From: Surbhi Palande @ 2011-05-03 15:26 UTC (permalink / raw)
To: surbhi.palande
Cc: Jan Kara, toshi.okajima, tytso, m.mizuma, adilger.kernel,
linux-ext4, linux-fsdevel, sandeen
On 05/03/2011 04:56 PM, Surbhi Palande wrote:
> On 05/03/2011 04:46 PM, Jan Kara wrote:
>> On Tue 03-05-11 16:08:36, Surbhi Palande wrote:
>
> Sorry for missing the subject line :(
>>> On munmap() zap_pte_range() is called which dirties the PTE dirty
>>> pages as
>>> Toshiyuki pointed out.
>>>
>>> zap_pte_range()
>>> mapping->a_ops->set_page_dirty (= ext4_journalled_set_page_dirty)
>>>
>>> So, I think that it is here that we should do the checking for a ext4
>>> F.S
>>> frozen state and also prevent a parallel ext4 F.S freeze from happening.
>>>
>>> Attaching a patch for initial review. Please do let me know your
>>> thoughts!
>> This is definitely the wrong place. ->set_page_dirty() callbacks are
>> called with various locks held and the page need not be locked (thus
>> dereferencing page->mapping is oopsable). Moreover this particular
>> callback
>> is called only in data=journal mode.
> Ok! Thanks for that!
>
>>
>> Believe me, the right place is page_mkwrite() - you have to catch the
>> read-only => read-write page transition. Once the page is mapped
>> read-write, you've already lost the race.
Also, we then need to prevent a munmap()/zap_pte_range() call from
dirtying a mmapped file page when the F.S is frozen?
Warm Regards,
Surbhi.
>
> My only point is:
> 1) something should prevent the freeze from happening. We cant merely
> check the vfs_check_frozen()?
>
> And this should be done where the page is marked dirty.Also, I thought
> that the page is marked read-write only in the page table in the
> __do_page_fault()? i.e the zap_pte_range() marks them dirty in the page
> cache? Is this understanding right?
>
> IMHO, whatever code dirties the page in the page cache should call a F.S
> specific function and let it _prevent_ a fsfreeze while the page is
> getting dirtied, so that a freeze called after this point flushes this
> page!
>
> Warm Regards,
> Surbhi.
>
>
>
>
>
>
>
>
>
>
>>
>> Honza
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2011-05-03 13:56 ` Surbhi Palande
2011-05-03 15:26 ` Surbhi Palande
@ 2011-05-03 15:36 ` Jan Kara
2011-05-03 15:43 ` Surbhi Palande
1 sibling, 1 reply; 25+ messages in thread
From: Jan Kara @ 2011-05-03 15:36 UTC (permalink / raw)
To: Surbhi Palande
Cc: Jan Kara, toshi.okajima, tytso, m.mizuma, adilger.kernel,
linux-ext4, linux-fsdevel, sandeen
On Tue 03-05-11 16:56:57, Surbhi Palande wrote:
> On 05/03/2011 04:46 PM, Jan Kara wrote:
> >On Tue 03-05-11 16:08:36, Surbhi Palande wrote:
>
> Sorry for missing the subject line :(
> >>On munmap() zap_pte_range() is called which dirties the PTE dirty pages as
> >>Toshiyuki pointed out.
> >>
> >>zap_pte_range()
> >> mapping->a_ops->set_page_dirty (= ext4_journalled_set_page_dirty)
> >>
> >>So, I think that it is here that we should do the checking for a ext4 F.S
> >>frozen state and also prevent a parallel ext4 F.S freeze from happening.
> >>
> >>Attaching a patch for initial review. Please do let me know your thoughts!
> > This is definitely the wrong place. ->set_page_dirty() callbacks are
> >called with various locks held and the page need not be locked (thus
> >dereferencing page->mapping is oopsable). Moreover this particular callback
> >is called only in data=journal mode.
> Ok! Thanks for that!
>
> >
> >Believe me, the right place is page_mkwrite() - you have to catch the
> >read-only => read-write page transition. Once the page is mapped
> >read-write, you've already lost the race.
>
> My only point is:
> 1) something should prevent the freeze from happening. We cant
> merely check the vfs_check_frozen()?
Yes, I agree - see my other email with patches.
> And this should be done where the page is marked dirty.Also, I
> thought that the page is marked read-write only in the page table in
> the __do_page_fault()? i.e the zap_pte_range() marks them dirty in
> the page cache? Is this understanding right?
The page can become dirty either because it was written via standard
write - write_begin is responsible for reliable check here - or it was
written via mmap - here we rely on page_mkwrite to do a reliable check -
it is analogous to write_begin callback. There should be no other way
to dirty a page.
With dirty bits it is a bit complicated. We have two of them in fact. One
in page table entry maintained by mmu and one in page structure maintained
by kernel. Some functions (such as zap_pte_range()) copy the dirty bits
from page table into struct page. This is a lazy process so page can in
principle have new data without a dirty bit set in struct page because we
have not yet copied the dirty bit from page table. Only at moments where it
is important (like when we want to unmap the page, or throw away the page,
or so), we make sure struct page and page table bits are in sync.
Another subtle thing you need not be aware of it that when we clear page
dirty bit, we also writeprotect the page. So we are guaranteed to get a
page fault when the page is written to again.
> IMHO, whatever code dirties the page in the page cache should call a
> F.S specific function and let it _prevent_ a fsfreeze while the page
> is getting dirtied, so that a freeze called after this point flushes
> this page!
Agreed, that's what code in write_begin() and page_mkwrite() should
achieve.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2011-05-03 15:36 ` Jan Kara
@ 2011-05-03 15:43 ` Surbhi Palande
2011-05-04 19:24 ` Jan Kara
0 siblings, 1 reply; 25+ messages in thread
From: Surbhi Palande @ 2011-05-03 15:43 UTC (permalink / raw)
To: Jan Kara
Cc: toshi.okajima, tytso, m.mizuma, adilger.kernel, linux-ext4,
linux-fsdevel, sandeen
On 05/03/2011 06:36 PM, Jan Kara wrote:
> On Tue 03-05-11 16:56:57, Surbhi Palande wrote:
>> On 05/03/2011 04:46 PM, Jan Kara wrote:
>>> On Tue 03-05-11 16:08:36, Surbhi Palande wrote:
>>
>> Sorry for missing the subject line :(
>>>> On munmap() zap_pte_range() is called which dirties the PTE dirty pages as
>>>> Toshiyuki pointed out.
>>>>
>>>> zap_pte_range()
>>>> mapping->a_ops->set_page_dirty (= ext4_journalled_set_page_dirty)
>>>>
>>>> So, I think that it is here that we should do the checking for a ext4 F.S
>>>> frozen state and also prevent a parallel ext4 F.S freeze from happening.
>>>>
>>>> Attaching a patch for initial review. Please do let me know your thoughts!
>>> This is definitely the wrong place. ->set_page_dirty() callbacks are
>>> called with various locks held and the page need not be locked (thus
>>> dereferencing page->mapping is oopsable). Moreover this particular callback
>>> is called only in data=journal mode.
>> Ok! Thanks for that!
>>
>>>
>>> Believe me, the right place is page_mkwrite() - you have to catch the
>>> read-only => read-write page transition. Once the page is mapped
>>> read-write, you've already lost the race.
>>
>> My only point is:
>> 1) something should prevent the freeze from happening. We cant
>> merely check the vfs_check_frozen()?
> Yes, I agree - see my other email with patches.
>
>> And this should be done where the page is marked dirty.Also, I
>> thought that the page is marked read-write only in the page table in
>> the __do_page_fault()? i.e the zap_pte_range() marks them dirty in
>> the page cache? Is this understanding right?
> The page can become dirty either because it was written via standard
> write - write_begin is responsible for reliable check here - or it was
> written via mmap - here we rely on page_mkwrite to do a reliable check -
> it is analogous to write_begin callback. There should be no other way
> to dirty a page.
>
> With dirty bits it is a bit complicated. We have two of them in fact. One
> in page table entry maintained by mmu and one in page structure maintained
> by kernel. Some functions (such as zap_pte_range()) copy the dirty bits
> from page table into struct page. This is a lazy process so page can in
> principle have new data without a dirty bit set in struct page because we
> have not yet copied the dirty bit from page table. Only at moments where it
> is important (like when we want to unmap the page, or throw away the page,
> or so), we make sure struct page and page table bits are in sync.
>
> Another subtle thing you need not be aware of it that when we clear page
> dirty bit, we also writeprotect the page. So we are guaranteed to get a
> page fault when the page is written to again.
>
>> IMHO, whatever code dirties the page in the page cache should call a
>> F.S specific function and let it _prevent_ a fsfreeze while the page
>> is getting dirtied, so that a freeze called after this point flushes
>> this page!
> Agreed, that's what code in write_begin() and page_mkwrite() should
> achieve.
> Honza
Thanks a lot for the wonderful explanation :)
How about the revert : i.e calling jbd2_journal_unlock_updates() from
ext4_unfreeze() instead of the ext4_freeze()? Do you agree to that?
Warm Regards,
Surbhi.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2011-05-03 15:43 ` Surbhi Palande
@ 2011-05-04 19:24 ` Jan Kara
0 siblings, 0 replies; 25+ messages in thread
From: Jan Kara @ 2011-05-04 19:24 UTC (permalink / raw)
To: Surbhi Palande
Cc: Jan Kara, toshi.okajima, tytso, m.mizuma, adilger.kernel,
linux-ext4, linux-fsdevel, sandeen
On Tue 03-05-11 18:43:48, Surbhi Palande wrote:
> On 05/03/2011 06:36 PM, Jan Kara wrote:
> >On Tue 03-05-11 16:56:57, Surbhi Palande wrote:
> >>On 05/03/2011 04:46 PM, Jan Kara wrote:
> >>>On Tue 03-05-11 16:08:36, Surbhi Palande wrote:
> >>
> >>Sorry for missing the subject line :(
> >>>>On munmap() zap_pte_range() is called which dirties the PTE dirty pages as
> >>>>Toshiyuki pointed out.
> >>>>
> >>>>zap_pte_range()
> >>>> mapping->a_ops->set_page_dirty (= ext4_journalled_set_page_dirty)
> >>>>
> >>>>So, I think that it is here that we should do the checking for a ext4 F.S
> >>>>frozen state and also prevent a parallel ext4 F.S freeze from happening.
> >>>>
> >>>>Attaching a patch for initial review. Please do let me know your thoughts!
> >>> This is definitely the wrong place. ->set_page_dirty() callbacks are
> >>>called with various locks held and the page need not be locked (thus
> >>>dereferencing page->mapping is oopsable). Moreover this particular callback
> >>>is called only in data=journal mode.
> >>Ok! Thanks for that!
> >>
> >>>
> >>>Believe me, the right place is page_mkwrite() - you have to catch the
> >>>read-only => read-write page transition. Once the page is mapped
> >>>read-write, you've already lost the race.
> >>
> >>My only point is:
> >>1) something should prevent the freeze from happening. We cant
> >>merely check the vfs_check_frozen()?
> > Yes, I agree - see my other email with patches.
> >
> >>And this should be done where the page is marked dirty.Also, I
> >>thought that the page is marked read-write only in the page table in
> >>the __do_page_fault()? i.e the zap_pte_range() marks them dirty in
> >>the page cache? Is this understanding right?
> > The page can become dirty either because it was written via standard
> >write - write_begin is responsible for reliable check here - or it was
> >written via mmap - here we rely on page_mkwrite to do a reliable check -
> >it is analogous to write_begin callback. There should be no other way
> >to dirty a page.
> >
> >With dirty bits it is a bit complicated. We have two of them in fact. One
> >in page table entry maintained by mmu and one in page structure maintained
> >by kernel. Some functions (such as zap_pte_range()) copy the dirty bits
> >from page table into struct page. This is a lazy process so page can in
> >principle have new data without a dirty bit set in struct page because we
> >have not yet copied the dirty bit from page table. Only at moments where it
> >is important (like when we want to unmap the page, or throw away the page,
> >or so), we make sure struct page and page table bits are in sync.
> >
> >Another subtle thing you need not be aware of it that when we clear page
> >dirty bit, we also writeprotect the page. So we are guaranteed to get a
> >page fault when the page is written to again.
> >
> >>IMHO, whatever code dirties the page in the page cache should call a
> >>F.S specific function and let it _prevent_ a fsfreeze while the page
> >>is getting dirtied, so that a freeze called after this point flushes
> >>this page!
> > Agreed, that's what code in write_begin() and page_mkwrite() should
> >achieve.
> > Honza
> Thanks a lot for the wonderful explanation :)
>
> How about the revert : i.e calling jbd2_journal_unlock_updates()
> from ext4_unfreeze() instead of the ext4_freeze()? Do you agree to
> that?
Sorry, I don't agree with revert. We could talk about changing
jbd2_journal_unlock_updates() to not return with mutex held (and handle
synchronization of locked journal operations differently) as an alternative
to doing "freeze" reference counting. But returning with mutex held to user
space is no-go. It will cause problems in lockdep, violates kernel locking
rules, and generally is a bad programming ;).
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2021-08-16 2:46 Kari Argillander
@ 2021-08-16 12:27 ` Christoph Hellwig
0 siblings, 0 replies; 25+ messages in thread
From: Christoph Hellwig @ 2021-08-16 12:27 UTC (permalink / raw)
To: Kari Argillander
Cc: Konstantin Komarov, Christoph Hellwig, ntfs3, linux-kernel,
linux-fsdevel, Pali Rohár, Matthew Wilcox
On Mon, Aug 16, 2021 at 05:46:59AM +0300, Kari Argillander wrote:
> I would like really like to get fsparam_flag_no also for no_acs_rules
> but then we have to make new name for it. Other possibility is to
> modify mount api so it mount option can be no/no_. I think that would
> maybe be good change.
I don't think adding another no_ alias is a good idea. I'd suggest
to just rename the existing flag before the ntfs3 driver ever hits
mainline.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: your mail
2021-08-21 8:59 Kari Argillander
@ 2021-08-22 13:13 ` CGEL
0 siblings, 0 replies; 25+ messages in thread
From: CGEL @ 2021-08-22 13:13 UTC (permalink / raw)
To: Kari Argillander
Cc: viro, christian.brauner, jamorris, gladkov.alexey, yang.yang29,
tj, paul.gortmaker, linux-fsdevel, linux-kernel, Zeal Robot
O
Sat, Aug 21, 2021 at 11:59:39AM +0300, Kari Argillander wrote:
> Bcc:
> Subject: Re: [PATCH] proc: prevent mount proc on same mountpoint in one pid
> namespace
> Reply-To:
> In-Reply-To: <20210821083105.30336-1-yang.yang29@zte.com.cn>
>
> On Sat, Aug 21, 2021 at 01:31:05AM -0700, cgel.zte@gmail.com wrote:
> > From: Yang Yang <yang.yang29@zte.com.cn>
> >
> > Patch "proc: allow to mount many instances of proc in one pid namespace"
> > aims to mount many instances of proc on different mountpoint, see
> > tools/testing/selftests/proc/proc-multiple-procfs.c.
> >
> > But there is a side-effects, user can mount many instances of proc on
> > the same mountpoint in one pid namespace, which is not allowed before.
> > This duplicate mount makes no sense but wastes memory and CPU, and user
> > may be confused why kernel allows it.
> >
> > The logic of this patch is: when try to mount proc on /mnt, check if
> > there is a proc instance mount on /mnt in the same pid namespace. If
> > answer is yes, return -EBUSY.
> >
> > Since this check can't be done in proc_get_tree(), which call
> > get_tree_nodev() and will create new super_block unconditionally.
> > And other nodev fs may faces the same case, so add a new hook in
> > fs_context_operations.
> >
> > Reported-by: Zeal Robot <zealci@zte.com.cn>
> > Signed-off-by: Yang Yang <yang.yang29@zte.com.cn>
> > ---
> > fs/namespace.c | 9 +++++++++
> > fs/proc/root.c | 15 +++++++++++++++
> > include/linux/fs_context.h | 1 +
> > 3 files changed, 25 insertions(+)
> >
> > diff --git a/fs/namespace.c b/fs/namespace.c
> > index f79d9471cb76..84da649a70c5 100644
> > --- a/fs/namespace.c
> > +++ b/fs/namespace.c
> > @@ -2878,6 +2878,7 @@ static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
> > static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
> > int mnt_flags, const char *name, void *data)
> > {
> > + int (*check_mntpoint)(struct fs_context *fc, struct path *path);
> > struct file_system_type *type;
> > struct fs_context *fc;
> > const char *subtype = NULL;
> > @@ -2906,6 +2907,13 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
> > if (IS_ERR(fc))
> > return PTR_ERR(fc);
> >
> > + /* check if there is a same super_block mount on path*/
> > + check_mntpoint = fc->ops->check_mntpoint;
> > + if (check_mntpoint)
> > + err = check_mntpoint(fc, path);
> > + if (err < 0)
> > + goto err_fc;
> > +
> > if (subtype)
> > err = vfs_parse_fs_string(fc, "subtype",
> > subtype, strlen(subtype));
> > @@ -2920,6 +2928,7 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
> > if (!err)
> > err = do_new_mount_fc(fc, path, mnt_flags);
> >
> > +err_fc:
> > put_fs_context(fc);
> > return err;
> > }
> > diff --git a/fs/proc/root.c b/fs/proc/root.c
> > index c7e3b1350ef8..0971d6b0bec2 100644
> > --- a/fs/proc/root.c
> > +++ b/fs/proc/root.c
> > @@ -237,11 +237,26 @@ static void proc_fs_context_free(struct fs_context *fc)
> > kfree(ctx);
> > }
> >
> > +static int proc_check_mntpoint(struct fs_context *fc, struct path *path)
> > +{
> > + struct super_block *mnt_sb = path->mnt->mnt_sb;
> > + struct proc_fs_info *fs_info;
> > +
> > + if (strcmp(mnt_sb->s_type->name, "proc") == 0) {
> > + fs_info = mnt_sb->s_fs_info;
> > + if (fs_info->pid_ns == task_active_pid_ns(current) &&
> > + path->mnt->mnt_root == path->dentry)
> > + return -EBUSY;
> > + }
> > + return 0;
> > +}
> > +
> > static const struct fs_context_operations proc_fs_context_ops = {
> > .free = proc_fs_context_free,
> > .parse_param = proc_parse_param,
> > .get_tree = proc_get_tree,
> > .reconfigure = proc_reconfigure,
> > + .check_mntpoint = proc_check_mntpoint,
> > };
> >
> > static int proc_init_fs_context(struct fs_context *fc)
> > diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h
> > index 6b54982fc5f3..090a05fb2d7d 100644
> > --- a/include/linux/fs_context.h
> > +++ b/include/linux/fs_context.h
> > @@ -119,6 +119,7 @@ struct fs_context_operations {
> > int (*parse_monolithic)(struct fs_context *fc, void *data);
> > int (*get_tree)(struct fs_context *fc);
> > int (*reconfigure)(struct fs_context *fc);
> > + int (*check_mntpoint)(struct fs_context *fc, struct path *path);
>
> Don't you think this should be it's own patch. It is after all internal
> api change. This also needs documentation. It would be confusing if
> someone convert to new mount api and there is one line which just
> address some proc stuff but even commit message does not address does
> every fs needs to add this.
>
> Documentation is very good shape right now and we are in face that
> everyone is migrating to use new mount api so everyting should be well
> documented.
> i
Thanks for your reply!
I will take commit message more carefully next time.
Sinece I am not quit sure about this patch, so I didn't write
Documentation for patch v1. AIViro had made it clear, so this
patch is abondoned.
> > };
> >
> > /*
> > --
> > 2.25.1
> >
^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2021-08-22 13:14 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-16 16:33 (unknown), Jan Kara
2010-06-16 16:33 ` [PATCH 1/2] radix-tree: Implement function radix_tree_range_tag_if_tagged Jan Kara
2010-06-18 22:18 ` Andrew Morton
2010-06-21 12:09 ` Nick Piggin
2010-06-21 22:43 ` Jan Kara
2010-06-23 13:42 ` Jan Kara
2010-06-16 16:33 ` [PATCH 2/2] mm: Implement writeback livelock avoidance using page tagging Jan Kara
2010-06-18 22:21 ` Andrew Morton
2010-06-21 12:42 ` Jan Kara
2010-06-16 22:15 ` your mail Dave Chinner
2010-06-17 7:43 ` [PATCH 0/2 v4] Writeback livelock avoidance for data integrity writes Jan Kara
2010-06-18 6:11 ` Dave Chinner
2010-06-18 7:01 ` Nick Piggin
2010-06-17 9:11 ` Jan Kara
2010-06-22 2:59 ` your mail Wu Fengguang
2010-06-22 13:54 ` Jan Kara
2010-06-22 14:12 ` Wu Fengguang
-- strict thread matches above, loose matches on Subject: below --
2011-05-03 11:01 [RFC][PATCH] Re: [BUG] ext4: cannot unfreeze a filesystem due to a deadlock Surbhi Palande
2011-05-03 13:08 ` (unknown), Surbhi Palande
2011-05-03 13:46 ` your mail Jan Kara
2011-05-03 13:56 ` Surbhi Palande
2011-05-03 15:26 ` Surbhi Palande
2011-05-03 15:36 ` Jan Kara
2011-05-03 15:43 ` Surbhi Palande
2011-05-04 19:24 ` Jan Kara
2021-08-16 2:46 Kari Argillander
2021-08-16 12:27 ` your mail Christoph Hellwig
2021-08-21 8:59 Kari Argillander
2021-08-22 13:13 ` your mail CGEL
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).