···303303304304static void nfs_invalidate_page(struct page *page, unsigned long offset)305305{306306- /* FIXME: we really should cancel any unstarted writes on this page */306306+ struct inode *inode = page->mapping->host;307307+308308+ /* Cancel any unstarted writes on this page */309309+ if (offset == 0)310310+ nfs_sync_inode_wait(inode, page->index, 1, FLUSH_INVALIDATE);307311}308312309313static int nfs_release_page(struct page *page, gfp_t gfp)
+28-19
fs/nfs/pagelist.c
···325325326326/**327327 * nfs_scan_list - Scan a list for matching requests328328+ * @nfsi: NFS inode328329 * @head: One of the NFS inode request lists329330 * @dst: Destination list330331 * @idx_start: lower bound of page->index to scan···337336 * The requests are *not* checked to ensure that they form a contiguous set.338337 * You must be holding the inode's req_lock when calling this function339338 */340340-int341341-nfs_scan_list(struct list_head *head, struct list_head *dst,342342- unsigned long idx_start, unsigned int npages)339339+int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,340340+ struct list_head *dst, unsigned long idx_start,341341+ unsigned int npages)343342{344344- struct list_head *pos, *tmp;345345- struct nfs_page *req;346346- unsigned long idx_end;347347- int res;343343+ struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];344344+ struct nfs_page *req;345345+ unsigned long idx_end;346346+ int found, i;347347+ int res;348348349349 res = 0;350350 if (npages == 0)···353351 else354352 idx_end = idx_start + npages - 1;355353356356- list_for_each_safe(pos, tmp, head) {357357-358358- req = nfs_list_entry(pos);359359-360360- if (req->wb_index < idx_start)361361- continue;362362- if (req->wb_index > idx_end)354354+ for (;;) {355355+ found = radix_tree_gang_lookup(&nfsi->nfs_page_tree,356356+ (void **)&pgvec[0], idx_start,357357+ NFS_SCAN_MAXENTRIES);358358+ if (found <= 0)363359 break;360360+ for (i = 0; i < found; i++) {361361+ req = pgvec[i];362362+ if (req->wb_index > idx_end)363363+ goto out;364364+ idx_start = req->wb_index + 1;365365+ if (req->wb_list_head != head)366366+ continue;367367+ if (nfs_set_page_writeback_locked(req)) {368368+ nfs_list_remove_request(req);369369+ nfs_list_add_request(req, dst);370370+ res++;371371+ }372372+ }364373365365- if (!nfs_set_page_writeback_locked(req))366366- continue;367367- nfs_list_remove_request(req);368368- nfs_list_add_request(req, dst);369369- res++;370374 }375375+out:371376 return res;372377}373378
+24-3
fs/nfs/write.c
···579579 return ret;580580}581581582582+static void nfs_cancel_requests(struct list_head *head)583583+{584584+ struct nfs_page *req;585585+ while(!list_empty(head)) {586586+ req = nfs_list_entry(head->next);587587+ nfs_list_remove_request(req);588588+ nfs_inode_remove_request(req);589589+ nfs_clear_page_writeback(req);590590+ }591591+}592592+582593/*583594 * nfs_scan_dirty - Scan an inode for dirty requests584595 * @inode: NFS inode to scan···634623 int res = 0;635624636625 if (nfsi->ncommit != 0) {637637- res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages);626626+ res = nfs_scan_list(nfsi, &nfsi->commit, dst, idx_start, npages);638627 nfsi->ncommit -= res;639628 if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))640629 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");···15021491 pages = nfs_scan_dirty(inode, &head, idx_start, npages);15031492 if (pages != 0) {15041493 spin_unlock(&nfsi->req_lock);15051505- ret = nfs_flush_list(inode, &head, pages, how);14941494+ if (how & FLUSH_INVALIDATE)14951495+ nfs_cancel_requests(&head);14961496+ else14971497+ ret = nfs_flush_list(inode, &head, pages, how);15061498 spin_lock(&nfsi->req_lock);15071499 continue;15081500 }15091501 if (nocommit)15101502 break;15111511- pages = nfs_scan_commit(inode, &head, 0, 0);15031503+ pages = nfs_scan_commit(inode, &head, idx_start, npages);15121504 if (pages == 0)15131505 break;15061506+ if (how & FLUSH_INVALIDATE) {15071507+ spin_unlock(&nfsi->req_lock);15081508+ nfs_cancel_requests(&head);15091509+ spin_lock(&nfsi->req_lock);15101510+ continue;15111511+ }15121512+ pages += nfs_scan_commit(inode, &head, 0, 0);15141513 spin_unlock(&nfsi->req_lock);15151514 ret = nfs_commit_list(inode, &head, how);15161515 spin_lock(&nfsi->req_lock);