···135135 int flags = sync ? FLUSH_WAIT : 0;136136 int ret;137137138138- ret = nfs_commit_inode(inode, 0, 0, flags);138138+ ret = nfs_commit_inode(inode, flags);139139 if (ret < 0)140140 return ret;141141 return 0;
+56-30
fs/nfs/pagelist.c
···177177 nfs_page_free(req);178178}179179180180-/**181181- * nfs_list_add_request - Insert a request into a sorted list182182- * @req: request183183- * @head: head of list into which to insert the request.184184- *185185- * Note that the wb_list is sorted by page index in order to facilitate186186- * coalescing of requests.187187- * We use an insertion sort that is optimized for the case of appended188188- * writes.189189- */190190-void191191-nfs_list_add_request(struct nfs_page *req, struct list_head *head)192192-{193193- struct list_head *pos;194194-195195-#ifdef NFS_PARANOIA196196- if (!list_empty(&req->wb_list)) {197197- printk(KERN_ERR "NFS: Add to list failed!\n");198198- BUG();199199- }200200-#endif201201- list_for_each_prev(pos, head) {202202- struct nfs_page *p = nfs_list_entry(pos);203203- if (p->wb_index < req->wb_index)204204- break;205205- }206206- list_add(&req->wb_list, pos);207207- req->wb_list_head = head;208208-}209209-210180static int nfs_wait_bit_interruptible(void *word)211181{212182 int ret = 0;···259289 break;260290 }261291 return npages;292292+}293293+294294+#define NFS_SCAN_MAXENTRIES 16295295+/**296296+ * nfs_scan_lock_dirty - Scan the radix tree for dirty requests297297+ * @nfsi: NFS inode298298+ * @dst: Destination list299299+ * @idx_start: lower bound of page->index to scan300300+ * @npages: idx_start + npages sets the upper bound to scan.301301+ *302302+ * Moves elements from one of the inode request lists.303303+ * If the number of requests is set to 0, the entire address_space304304+ * starting at index idx_start, is scanned.305305+ * The requests are *not* checked to ensure that they form a contiguous set.306306+ * You must be holding the inode's req_lock when calling this function307307+ */308308+int309309+nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,310310+ unsigned long idx_start, unsigned int npages)311311+{312312+ struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];313313+ struct nfs_page *req;314314+ unsigned long idx_end;315315+ int found, i;316316+ int res;317317+318318+ res = 0;319319+ if (npages == 0)320320+ idx_end = ~0;321321+ else322322+ idx_end = idx_start + npages - 1;323323+324324+ for (;;) {325325+ found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,326326+ (void **)&pgvec[0], idx_start, NFS_SCAN_MAXENTRIES,327327+ NFS_PAGE_TAG_DIRTY);328328+ if (found <= 0)329329+ break;330330+ for (i = 0; i < found; i++) {331331+ req = pgvec[i];332332+ if (req->wb_index > idx_end)333333+ goto out;334334+335335+ idx_start = req->wb_index + 1;336336+337337+ if (nfs_set_page_writeback_locked(req)) {338338+ radix_tree_tag_clear(&nfsi->nfs_page_tree,339339+ req->wb_index, NFS_PAGE_TAG_DIRTY);340340+ nfs_list_remove_request(req);341341+ nfs_list_add_request(req, dst);342342+ res++;343343+ }344344+ }345345+ }346346+out:347347+ return res;262348}263349264350/**
+32-39
fs/nfs/write.c
···352352 if (err < 0)353353 goto out;354354 }355355- err = nfs_commit_inode(inode, 0, 0, wb_priority(wbc));355355+ err = nfs_commit_inode(inode, wb_priority(wbc));356356 if (err > 0) {357357 wbc->nr_to_write -= err;358358 err = 0;···446446 struct nfs_inode *nfsi = NFS_I(inode);447447448448 spin_lock(&nfsi->req_lock);449449+ radix_tree_tag_set(&nfsi->nfs_page_tree,450450+ req->wb_index, NFS_PAGE_TAG_DIRTY);449451 nfs_list_add_request(req, &nfsi->dirty);450452 nfsi->ndirty++;451453 spin_unlock(&nfsi->req_lock);···539537nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)540538{541539 struct nfs_inode *nfsi = NFS_I(inode);542542- int res;543543- res = nfs_scan_list(&nfsi->dirty, dst, idx_start, npages);544544- nfsi->ndirty -= res;545545- sub_page_state(nr_dirty,res);546546- if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))547547- printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");540540+ int res = 0;541541+542542+ if (nfsi->ndirty != 0) {543543+ res = nfs_scan_lock_dirty(nfsi, dst, idx_start, npages);544544+ nfsi->ndirty -= res;545545+ sub_page_state(nr_dirty,res);546546+ if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))547547+ printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");548548+ }548549 return res;549550}550551···566561nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)567562{568563 struct nfs_inode *nfsi = NFS_I(inode);569569- int res;570570- res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages);571571- nfsi->ncommit -= res;572572- if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))573573- printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");564564+ int res = 0;565565+566566+ if (nfsi->ncommit != 0) {567567+ res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages);568568+ nfsi->ncommit -= res;569569+ if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))570570+ printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");571571+ }574572 return res;575573}576574#endif···12171209 struct nfs_write_data *data, int how)12181210{12191211 struct rpc_task *task = &data->task;12201220- struct nfs_page *first, *last;12121212+ struct nfs_page *first;12211213 struct inode *inode;12221222- loff_t start, end, len;1223121412241215 /* Set up the RPC argument and reply structs12251216 * NB: take care not to mess about with data->commit et al. */1226121712271218 list_splice_init(head, &data->pages);12281219 first = nfs_list_entry(data->pages.next);12291229- last = nfs_list_entry(data->pages.prev);12301220 inode = first->wb_context->dentry->d_inode;12311231-12321232- /*12331233- * Determine the offset range of requests in the COMMIT call.12341234- * We rely on the fact that data->pages is an ordered list...12351235- */12361236- start = req_offset(first);12371237- end = req_offset(last) + last->wb_bytes;12381238- len = end - start;12391239- /* If 'len' is not a 32-bit quantity, pass '0' in the COMMIT call */12401240- if (end >= i_size_read(inode) || len < 0 || len > (~((u32)0) >> 1))12411241- len = 0;1242122112431222 data->inode = inode;12441223 data->cred = first->wb_context->cred;1245122412461225 data->args.fh = NFS_FH(data->inode);12471247- data->args.offset = start;12481248- data->args.count = len;12491249- data->res.count = len;12261226+ /* Note: we always request a commit of the entire inode */12271227+ data->args.offset = 0;12281228+ data->args.count = 0;12291229+ data->res.count = 0;12501230 data->res.fattr = &data->fattr;12511231 data->res.verf = &data->verf;12521232···13531357}1354135813551359#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)13561356-int nfs_commit_inode(struct inode *inode, unsigned long idx_start,13571357- unsigned int npages, int how)13601360+int nfs_commit_inode(struct inode *inode, int how)13581361{13591362 struct nfs_inode *nfsi = NFS_I(inode);13601363 LIST_HEAD(head);···13611366 error = 0;1362136713631368 spin_lock(&nfsi->req_lock);13641364- res = nfs_scan_commit(inode, &head, idx_start, npages);13691369+ res = nfs_scan_commit(inode, &head, 0, 0);13701370+ spin_unlock(&nfsi->req_lock);13651371 if (res) {13661366- res += nfs_scan_commit(inode, &head, 0, 0);13671367- spin_unlock(&nfsi->req_lock);13681372 error = nfs_commit_list(&head, how);13691369- } else13701370- spin_unlock(&nfsi->req_lock);13711371- if (error < 0)13721372- return error;13731373+ if (error < 0)13741374+ return error;13751375+ }13731376 return res;13741377}13751378#endif···13891396 error = nfs_flush_inode(inode, idx_start, npages, how);13901397#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)13911398 if (error == 0)13921392- error = nfs_commit_inode(inode, idx_start, npages, how);13991399+ error = nfs_commit_inode(inode, how);13931400#endif13941401 } while (error > 0);13951402 return error;
+2-2
include/linux/nfs_fs.h
···395395 */396396extern int nfs_sync_inode(struct inode *, unsigned long, unsigned int, int);397397#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)398398-extern int nfs_commit_inode(struct inode *, unsigned long, unsigned int, int);398398+extern int nfs_commit_inode(struct inode *, int);399399#else400400static inline int401401-nfs_commit_inode(struct inode *inode, unsigned long idx_start, unsigned int npages, int how)401401+nfs_commit_inode(struct inode *inode, int how)402402{403403 return 0;404404}
+16-2
include/linux/nfs_page.h
···2222/*2323 * Valid flags for the radix tree2424 */2525+#define NFS_PAGE_TAG_DIRTY 02526#define NFS_PAGE_TAG_WRITEBACK 126272728/*···3231#define PG_NEED_COMMIT 13332#define PG_NEED_RESCHED 234333434+struct nfs_inode;3535struct nfs_page {3636 struct list_head wb_list, /* Defines state of page: */3737 *wb_list_head; /* read/write/commit */···6159extern void nfs_release_request(struct nfs_page *req);626063616464-extern void nfs_list_add_request(struct nfs_page *, struct list_head *);6565-6262+extern int nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,6363+ unsigned long idx_start, unsigned int npages);6664extern int nfs_scan_list(struct list_head *, struct list_head *,6765 unsigned long, unsigned int);6866extern int nfs_coalesce_requests(struct list_head *, struct list_head *,···9492 return 0;9593 atomic_inc(&req->wb_count);9694 return 1;9595+}9696+9797+/**9898+ * nfs_list_add_request - Insert a request into a list9999+ * @req: request100100+ * @head: head of list into which to insert the request.101101+ */102102+static inline void103103+nfs_list_add_request(struct nfs_page *req, struct list_head *head)104104+{105105+ list_add_tail(&req->wb_list, head);106106+ req->wb_list_head = head;97107}9810899109