summaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorWilliam Lee Irwin III <wli@holomorphy.com>2005-05-01 08:58:38 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-01 08:58:38 -0700
commitdd1d5afca8d3bda7ff9db773fc08e648d2503dc6 (patch)
treeb0cc49be9dc43558e31be18d6045181661492018 /mm
parent93ea1d0a12623dc1a693642b5758261f35f9bf96 (diff)
downloadlinux-dd1d5afca8d3bda7ff9db773fc08e648d2503dc6.tar.bz2
[PATCH] sync_page() smp_mb() comment
The smp_mb() is becaus sync_page() doesn't have PG_locked while it accesses page_mapping(page). The comments in the patch (the entire patch is the addition of this comment) try to explain further how and why smp_mb() is used. Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/filemap.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 9b74674e36ad..ee79b5d3439f 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -139,7 +139,25 @@ static int sync_page(void *word)
page = container_of((page_flags_t *)word, struct page, flags);
/*
- * FIXME, fercrissake. What is this barrier here for?
+ * page_mapping() is being called without PG_locked held.
+ * Some knowledge of the state and use of the page is used to
+ * reduce the requirements down to a memory barrier.
+ * The danger here is of a stale page_mapping() return value
+ * indicating a struct address_space different from the one it's
+ * associated with when it is associated with one.
+ * After smp_mb(), it's either the correct page_mapping() for
+ * the page, or an old page_mapping() and the page's own
+ * page_mapping() has gone NULL.
+ * The ->sync_page() address_space operation must tolerate
+ * page_mapping() going NULL. By an amazing coincidence,
+ * this comes about because none of the users of the page
+ * in the ->sync_page() methods make essential use of the
+ * page_mapping(), merely passing the page down to the backing
+ * device's unplug functions when it's non-NULL, which in turn
+ * ignore it for all cases but swap, where only page->private is
+ * of interest. When page_mapping() does go NULL, the entire
+ * call stack gracefully ignores the page and returns.
+ * -- wli
*/
smp_mb();
mapping = page_mapping(page);