diff options
author | Evgeniy Dushistov <dushistov@mail.ru> | 2006-08-05 15:13:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-08-06 11:57:46 -0400 |
commit | 1fb32b7bd8203d0175649a75ede3ee7634d6a941 (patch) | |
tree | 1c0b7bd06835ce37dc2fc18a95fe3fe22c2ce556 /fs | |
parent | e91467ecd1ef381377fd327c0ded922835ec52ab (diff) |
[PATCH] ufs: ufs_get_locked_page() race fix
As discussed earlier:
http://lkml.org/lkml/2006/6/28/136
this patch fixes such issue:
`ufs_get_locked_page' takes page from cache
after that `vmtruncate' takes page and deletes it from cache
`ufs_get_locked_page' locks page, and reports about EIO error.
Also because of find_lock_page always return valid page or NULL, we have no
need to check it if page not NULL.
Signed-off-by: Evgeniy Dushistov <dushistov@mail.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ufs/util.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/fs/ufs/util.c b/fs/ufs/util.c index 337cf2c46d10..005d6815adf5 100644 --- a/fs/ufs/util.c +++ b/fs/ufs/util.c | |||
@@ -257,6 +257,7 @@ try_again: | |||
257 | page = read_cache_page(mapping, index, | 257 | page = read_cache_page(mapping, index, |
258 | (filler_t*)mapping->a_ops->readpage, | 258 | (filler_t*)mapping->a_ops->readpage, |
259 | NULL); | 259 | NULL); |
260 | |||
260 | if (IS_ERR(page)) { | 261 | if (IS_ERR(page)) { |
261 | printk(KERN_ERR "ufs_change_blocknr: " | 262 | printk(KERN_ERR "ufs_change_blocknr: " |
262 | "read_cache_page error: ino %lu, index: %lu\n", | 263 | "read_cache_page error: ino %lu, index: %lu\n", |
@@ -266,6 +267,13 @@ try_again: | |||
266 | 267 | ||
267 | lock_page(page); | 268 | lock_page(page); |
268 | 269 | ||
270 | if (unlikely(page->mapping == NULL)) { | ||
271 | /* Truncate got there first */ | ||
272 | unlock_page(page); | ||
273 | page_cache_release(page); | ||
274 | goto try_again; | ||
275 | } | ||
276 | |||
269 | if (!PageUptodate(page) || PageError(page)) { | 277 | if (!PageUptodate(page) || PageError(page)) { |
270 | unlock_page(page); | 278 | unlock_page(page); |
271 | page_cache_release(page); | 279 | page_cache_release(page); |
@@ -275,15 +283,8 @@ try_again: | |||
275 | mapping->host->i_ino, index); | 283 | mapping->host->i_ino, index); |
276 | 284 | ||
277 | page = ERR_PTR(-EIO); | 285 | page = ERR_PTR(-EIO); |
278 | goto out; | ||
279 | } | 286 | } |
280 | } | 287 | } |
281 | |||
282 | if (unlikely(!page->mapping || !page_has_buffers(page))) { | ||
283 | unlock_page(page); | ||
284 | page_cache_release(page); | ||
285 | goto try_again;/*we really need these buffers*/ | ||
286 | } | ||
287 | out: | 288 | out: |
288 | return page; | 289 | return page; |
289 | } | 290 | } |