aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pagelist.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/pagelist.c')
-rw-r--r--fs/nfs/pagelist.c86
1 files changed, 56 insertions, 30 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 356a33bb38a6..d53857b148e2 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -177,36 +177,6 @@ nfs_release_request(struct nfs_page *req)
177 nfs_page_free(req); 177 nfs_page_free(req);
178} 178}
179 179
180/**
181 * nfs_list_add_request - Insert a request into a sorted list
182 * @req: request
183 * @head: head of list into which to insert the request.
184 *
185 * Note that the wb_list is sorted by page index in order to facilitate
186 * coalescing of requests.
187 * We use an insertion sort that is optimized for the case of appended
188 * writes.
189 */
190void
191nfs_list_add_request(struct nfs_page *req, struct list_head *head)
192{
193 struct list_head *pos;
194
195#ifdef NFS_PARANOIA
196 if (!list_empty(&req->wb_list)) {
197 printk(KERN_ERR "NFS: Add to list failed!\n");
198 BUG();
199 }
200#endif
201 list_for_each_prev(pos, head) {
202 struct nfs_page *p = nfs_list_entry(pos);
203 if (p->wb_index < req->wb_index)
204 break;
205 }
206 list_add(&req->wb_list, pos);
207 req->wb_list_head = head;
208}
209
210static int nfs_wait_bit_interruptible(void *word) 180static int nfs_wait_bit_interruptible(void *word)
211{ 181{
212 int ret = 0; 182 int ret = 0;
@@ -291,6 +261,62 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
291 return npages; 261 return npages;
292} 262}
293 263
264#define NFS_SCAN_MAXENTRIES 16
265/**
266 * nfs_scan_lock_dirty - Scan the radix tree for dirty requests
267 * @nfsi: NFS inode
268 * @dst: Destination list
269 * @idx_start: lower bound of page->index to scan
270 * @npages: idx_start + npages sets the upper bound to scan.
271 *
272 * Moves elements from one of the inode request lists.
273 * If the number of requests is set to 0, the entire address_space
274 * starting at index idx_start, is scanned.
275 * The requests are *not* checked to ensure that they form a contiguous set.
276 * You must be holding the inode's req_lock when calling this function
277 */
278int
279nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,
280 unsigned long idx_start, unsigned int npages)
281{
282 struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
283 struct nfs_page *req;
284 unsigned long idx_end;
285 int found, i;
286 int res;
287
288 res = 0;
289 if (npages == 0)
290 idx_end = ~0;
291 else
292 idx_end = idx_start + npages - 1;
293
294 for (;;) {
295 found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
296 (void **)&pgvec[0], idx_start, NFS_SCAN_MAXENTRIES,
297 NFS_PAGE_TAG_DIRTY);
298 if (found <= 0)
299 break;
300 for (i = 0; i < found; i++) {
301 req = pgvec[i];
302 if (req->wb_index > idx_end)
303 goto out;
304
305 idx_start = req->wb_index + 1;
306
307 if (nfs_set_page_writeback_locked(req)) {
308 radix_tree_tag_clear(&nfsi->nfs_page_tree,
309 req->wb_index, NFS_PAGE_TAG_DIRTY);
310 nfs_list_remove_request(req);
311 nfs_list_add_request(req, dst);
312 res++;
313 }
314 }
315 }
316out:
317 return res;
318}
319
294/** 320/**
295 * nfs_scan_list - Scan a list for matching requests 321 * nfs_scan_list - Scan a list for matching requests
296 * @head: One of the NFS inode request lists 322 * @head: One of the NFS inode request lists