|
@@ -499,31 +499,34 @@ static int __gfs2_readpage(void *file, struct page *page)
|
|
|
* @file: The file to read
|
|
|
* @page: The page of the file
|
|
|
*
|
|
|
- * This deals with the locking required. We use a trylock in order to
|
|
|
- * avoid the page lock / glock ordering problems returning AOP_TRUNCATED_PAGE
|
|
|
- * in the event that we are unable to get the lock.
|
|
|
+ * This deals with the locking required. We have to unlock and
|
|
|
+ * relock the page in order to get the locking in the right
|
|
|
+ * order.
|
|
|
*/
|
|
|
|
|
|
static int gfs2_readpage(struct file *file, struct page *page)
|
|
|
{
|
|
|
- struct gfs2_inode *ip = GFS2_I(page->mapping->host);
|
|
|
+ struct address_space *mapping = page->mapping;
|
|
|
+ struct gfs2_inode *ip = GFS2_I(mapping->host);
|
|
|
struct gfs2_holder gh;
|
|
|
int error;
|
|
|
|
|
|
- gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
|
|
|
+ unlock_page(page);
|
|
|
+ gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
|
|
|
error = gfs2_glock_nq_atime(&gh);
|
|
|
- if (unlikely(error)) {
|
|
|
- unlock_page(page);
|
|
|
+ if (unlikely(error))
|
|
|
goto out;
|
|
|
- }
|
|
|
- error = __gfs2_readpage(file, page);
|
|
|
+ error = AOP_TRUNCATED_PAGE;
|
|
|
+ lock_page(page);
|
|
|
+ if (page->mapping == mapping && !PageUptodate(page))
|
|
|
+ error = __gfs2_readpage(file, page);
|
|
|
+ else
|
|
|
+ unlock_page(page);
|
|
|
gfs2_glock_dq(&gh);
|
|
|
out:
|
|
|
gfs2_holder_uninit(&gh);
|
|
|
- if (error == GLR_TRYFAILED) {
|
|
|
- yield();
|
|
|
- return AOP_TRUNCATED_PAGE;
|
|
|
- }
|
|
|
+ if (error && error != AOP_TRUNCATED_PAGE)
|
|
|
+ lock_page(page);
|
|
|
return error;
|
|
|
}
|
|
|
|