aboutsummaryrefslogtreecommitdiffstats
path: root/mm/filemap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/filemap.c')
-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)
139 page = container_of((page_flags_t *)word, struct page, flags); 139 page = container_of((page_flags_t *)word, struct page, flags);
140 140
141 /* 141 /*
142 * FIXME, fercrissake. What is this barrier here for? 142 * page_mapping() is being called without PG_locked held.
143 * Some knowledge of the state and use of the page is used to
144 * reduce the requirements down to a memory barrier.
145 * The danger here is of a stale page_mapping() return value
146 * indicating a struct address_space different from the one it's
147 * associated with when it is associated with one.
148 * After smp_mb(), it's either the correct page_mapping() for
149 * the page, or an old page_mapping() and the page's own
150 * page_mapping() has gone NULL.
151 * The ->sync_page() address_space operation must tolerate
152 * page_mapping() going NULL. By an amazing coincidence,
153 * this comes about because none of the users of the page
154 * in the ->sync_page() methods make essential use of the
155 * page_mapping(), merely passing the page down to the backing
156 * device's unplug functions when it's non-NULL, which in turn
157 * ignore it for all cases but swap, where only page->private is
158 * of interest. When page_mapping() does go NULL, the entire
159 * call stack gracefully ignores the page and returns.
160 * -- wli
143 */ 161 */
144 smp_mb(); 162 smp_mb();
145 mapping = page_mapping(page); 163 mapping = page_mapping(page);