diff options
-rw-r--r-- | fs/gfs2/ops_address.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 2b556dd034bb..e64a1b04117a 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -499,31 +499,34 @@ static int __gfs2_readpage(void *file, struct page *page) | |||
499 | * @file: The file to read | 499 | * @file: The file to read |
500 | * @page: The page of the file | 500 | * @page: The page of the file |
501 | * | 501 | * |
502 | * This deals with the locking required. We use a trylock in order to | 502 | * This deals with the locking required. We have to unlock and |
503 | * avoid the page lock / glock ordering problems returning AOP_TRUNCATED_PAGE | 503 | * relock the page in order to get the locking in the right |
504 | * in the event that we are unable to get the lock. | 504 | * order. |
505 | */ | 505 | */ |
506 | 506 | ||
507 | static int gfs2_readpage(struct file *file, struct page *page) | 507 | static int gfs2_readpage(struct file *file, struct page *page) |
508 | { | 508 | { |
509 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); | 509 | struct address_space *mapping = page->mapping; |
510 | struct gfs2_inode *ip = GFS2_I(mapping->host); | ||
510 | struct gfs2_holder gh; | 511 | struct gfs2_holder gh; |
511 | int error; | 512 | int error; |
512 | 513 | ||
513 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh); | 514 | unlock_page(page); |
515 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); | ||
514 | error = gfs2_glock_nq_atime(&gh); | 516 | error = gfs2_glock_nq_atime(&gh); |
515 | if (unlikely(error)) { | 517 | if (unlikely(error)) |
516 | unlock_page(page); | ||
517 | goto out; | 518 | goto out; |
518 | } | 519 | error = AOP_TRUNCATED_PAGE; |
519 | error = __gfs2_readpage(file, page); | 520 | lock_page(page); |
521 | if (page->mapping == mapping && !PageUptodate(page)) | ||
522 | error = __gfs2_readpage(file, page); | ||
523 | else | ||
524 | unlock_page(page); | ||
520 | gfs2_glock_dq(&gh); | 525 | gfs2_glock_dq(&gh); |
521 | out: | 526 | out: |
522 | gfs2_holder_uninit(&gh); | 527 | gfs2_holder_uninit(&gh); |
523 | if (error == GLR_TRYFAILED) { | 528 | if (error && error != AOP_TRUNCATED_PAGE) |
524 | yield(); | 529 | lock_page(page); |
525 | return AOP_TRUNCATED_PAGE; | ||
526 | } | ||
527 | return error; | 530 | return error; |
528 | } | 531 | } |
529 | 532 | ||