diff options
Diffstat (limited to 'fs/ocfs2/aops.c')
| -rw-r--r-- | fs/ocfs2/aops.c | 69 |
1 files changed, 61 insertions, 8 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index c1efe939c774..78b68af3b0e3 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -290,7 +290,15 @@ static int ocfs2_readpage(struct file *file, struct page *page) | |||
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | if (down_read_trylock(&oi->ip_alloc_sem) == 0) { | 292 | if (down_read_trylock(&oi->ip_alloc_sem) == 0) { |
| 293 | /* | ||
| 294 | * Unlock the page and cycle ip_alloc_sem so that we don't | ||
| 295 | * busyloop waiting for ip_alloc_sem to unlock | ||
| 296 | */ | ||
| 293 | ret = AOP_TRUNCATED_PAGE; | 297 | ret = AOP_TRUNCATED_PAGE; |
| 298 | unlock_page(page); | ||
| 299 | unlock = 0; | ||
| 300 | down_read(&oi->ip_alloc_sem); | ||
| 301 | up_read(&oi->ip_alloc_sem); | ||
| 294 | goto out_inode_unlock; | 302 | goto out_inode_unlock; |
| 295 | } | 303 | } |
| 296 | 304 | ||
| @@ -563,6 +571,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, | |||
| 563 | { | 571 | { |
| 564 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; | 572 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; |
| 565 | int level; | 573 | int level; |
| 574 | wait_queue_head_t *wq = ocfs2_ioend_wq(inode); | ||
| 566 | 575 | ||
| 567 | /* this io's submitter should not have unlocked this before we could */ | 576 | /* this io's submitter should not have unlocked this before we could */ |
| 568 | BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); | 577 | BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); |
| @@ -570,6 +579,15 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, | |||
| 570 | if (ocfs2_iocb_is_sem_locked(iocb)) | 579 | if (ocfs2_iocb_is_sem_locked(iocb)) |
| 571 | ocfs2_iocb_clear_sem_locked(iocb); | 580 | ocfs2_iocb_clear_sem_locked(iocb); |
| 572 | 581 | ||
| 582 | if (ocfs2_iocb_is_unaligned_aio(iocb)) { | ||
| 583 | ocfs2_iocb_clear_unaligned_aio(iocb); | ||
| 584 | |||
| 585 | if (atomic_dec_and_test(&OCFS2_I(inode)->ip_unaligned_aio) && | ||
| 586 | waitqueue_active(wq)) { | ||
| 587 | wake_up_all(wq); | ||
| 588 | } | ||
| 589 | } | ||
| 590 | |||
| 573 | ocfs2_iocb_clear_rw_locked(iocb); | 591 | ocfs2_iocb_clear_rw_locked(iocb); |
| 574 | 592 | ||
| 575 | level = ocfs2_iocb_rw_locked_level(iocb); | 593 | level = ocfs2_iocb_rw_locked_level(iocb); |
| @@ -863,6 +881,12 @@ struct ocfs2_write_ctxt { | |||
| 863 | struct page *w_target_page; | 881 | struct page *w_target_page; |
| 864 | 882 | ||
| 865 | /* | 883 | /* |
| 884 | * w_target_locked is used for page_mkwrite path indicating no unlocking | ||
| 885 | * against w_target_page in ocfs2_write_end_nolock. | ||
| 886 | */ | ||
| 887 | unsigned int w_target_locked:1; | ||
| 888 | |||
| 889 | /* | ||
| 866 | * ocfs2_write_end() uses this to know what the real range to | 890 | * ocfs2_write_end() uses this to know what the real range to |
| 867 | * write in the target should be. | 891 | * write in the target should be. |
| 868 | */ | 892 | */ |
| @@ -895,6 +919,24 @@ void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages) | |||
| 895 | 919 | ||
| 896 | static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) | 920 | static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) |
| 897 | { | 921 | { |
| 922 | int i; | ||
| 923 | |||
| 924 | /* | ||
| 925 | * w_target_locked is only set to true in the page_mkwrite() case. | ||
| 926 | * The intent is to allow us to lock the target page from write_begin() | ||
| 927 | * to write_end(). The caller must hold a ref on w_target_page. | ||
| 928 | */ | ||
| 929 | if (wc->w_target_locked) { | ||
| 930 | BUG_ON(!wc->w_target_page); | ||
| 931 | for (i = 0; i < wc->w_num_pages; i++) { | ||
| 932 | if (wc->w_target_page == wc->w_pages[i]) { | ||
| 933 | wc->w_pages[i] = NULL; | ||
| 934 | break; | ||
| 935 | } | ||
| 936 | } | ||
| 937 | mark_page_accessed(wc->w_target_page); | ||
| 938 | page_cache_release(wc->w_target_page); | ||
| 939 | } | ||
| 898 | ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages); | 940 | ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages); |
| 899 | 941 | ||
| 900 | brelse(wc->w_di_bh); | 942 | brelse(wc->w_di_bh); |
| @@ -1132,20 +1174,17 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping, | |||
| 1132 | */ | 1174 | */ |
| 1133 | lock_page(mmap_page); | 1175 | lock_page(mmap_page); |
| 1134 | 1176 | ||
| 1177 | /* Exit and let the caller retry */ | ||
| 1135 | if (mmap_page->mapping != mapping) { | 1178 | if (mmap_page->mapping != mapping) { |
| 1179 | WARN_ON(mmap_page->mapping); | ||
| 1136 | unlock_page(mmap_page); | 1180 | unlock_page(mmap_page); |
| 1137 | /* | 1181 | ret = -EAGAIN; |
| 1138 | * Sanity check - the locking in | ||
| 1139 | * ocfs2_pagemkwrite() should ensure | ||
| 1140 | * that this code doesn't trigger. | ||
| 1141 | */ | ||
| 1142 | ret = -EINVAL; | ||
| 1143 | mlog_errno(ret); | ||
| 1144 | goto out; | 1182 | goto out; |
| 1145 | } | 1183 | } |
| 1146 | 1184 | ||
| 1147 | page_cache_get(mmap_page); | 1185 | page_cache_get(mmap_page); |
| 1148 | wc->w_pages[i] = mmap_page; | 1186 | wc->w_pages[i] = mmap_page; |
| 1187 | wc->w_target_locked = true; | ||
| 1149 | } else { | 1188 | } else { |
| 1150 | wc->w_pages[i] = find_or_create_page(mapping, index, | 1189 | wc->w_pages[i] = find_or_create_page(mapping, index, |
| 1151 | GFP_NOFS); | 1190 | GFP_NOFS); |
| @@ -1160,6 +1199,8 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping, | |||
| 1160 | wc->w_target_page = wc->w_pages[i]; | 1199 | wc->w_target_page = wc->w_pages[i]; |
| 1161 | } | 1200 | } |
| 1162 | out: | 1201 | out: |
| 1202 | if (ret) | ||
| 1203 | wc->w_target_locked = false; | ||
| 1163 | return ret; | 1204 | return ret; |
| 1164 | } | 1205 | } |
| 1165 | 1206 | ||
| @@ -1817,11 +1858,23 @@ try_again: | |||
| 1817 | */ | 1858 | */ |
| 1818 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, len, | 1859 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, len, |
| 1819 | cluster_of_pages, mmap_page); | 1860 | cluster_of_pages, mmap_page); |
| 1820 | if (ret) { | 1861 | if (ret && ret != -EAGAIN) { |
| 1821 | mlog_errno(ret); | 1862 | mlog_errno(ret); |
| 1822 | goto out_quota; | 1863 | goto out_quota; |
| 1823 | } | 1864 | } |
| 1824 | 1865 | ||
| 1866 | /* | ||
| 1867 | * ocfs2_grab_pages_for_write() returns -EAGAIN if it could not lock | ||
| 1868 | * the target page. In this case, we exit with no error and no target | ||
| 1869 | * page. This will trigger the caller, page_mkwrite(), to re-try | ||
| 1870 | * the operation. | ||
| 1871 | */ | ||
| 1872 | if (ret == -EAGAIN) { | ||
| 1873 | BUG_ON(wc->w_target_page); | ||
| 1874 | ret = 0; | ||
| 1875 | goto out_quota; | ||
| 1876 | } | ||
| 1877 | |||
| 1825 | ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos, | 1878 | ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos, |
| 1826 | len); | 1879 | len); |
| 1827 | if (ret) { | 1880 | if (ret) { |
