Commit 5c36968343fcd013a3f7ae93f246c2e75596780b
1 parent
9fd367f0f3
Exists in
master
and in
7 other branches
NFS cleanup: speed up nfs_scan_commit using radix tree tags
Add a tag for requests that are waiting for a COMMIT Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Showing 3 changed files with 15 additions and 10 deletions Side-by-side Diff
fs/nfs/pagelist.c
... | ... | @@ -381,10 +381,10 @@ |
381 | 381 | /** |
382 | 382 | * nfs_scan_list - Scan a list for matching requests |
383 | 383 | * @nfsi: NFS inode |
384 | - * @head: One of the NFS inode request lists | |
385 | 384 | * @dst: Destination list |
386 | 385 | * @idx_start: lower bound of page->index to scan |
387 | 386 | * @npages: idx_start + npages sets the upper bound to scan. |
387 | + * @tag: tag to scan for | |
388 | 388 | * |
389 | 389 | * Moves elements from one of the inode request lists. |
390 | 390 | * If the number of requests is set to 0, the entire address_space |
391 | 391 | |
... | ... | @@ -392,9 +392,9 @@ |
392 | 392 | * The requests are *not* checked to ensure that they form a contiguous set. |
393 | 393 | * You must be holding the inode's req_lock when calling this function |
394 | 394 | */ |
395 | -int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, | |
395 | +int nfs_scan_list(struct nfs_inode *nfsi, | |
396 | 396 | struct list_head *dst, pgoff_t idx_start, |
397 | - unsigned int npages) | |
397 | + unsigned int npages, int tag) | |
398 | 398 | { |
399 | 399 | struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES]; |
400 | 400 | struct nfs_page *req; |
401 | 401 | |
... | ... | @@ -409,9 +409,9 @@ |
409 | 409 | idx_end = idx_start + npages - 1; |
410 | 410 | |
411 | 411 | for (;;) { |
412 | - found = radix_tree_gang_lookup(&nfsi->nfs_page_tree, | |
412 | + found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, | |
413 | 413 | (void **)&pgvec[0], idx_start, |
414 | - NFS_SCAN_MAXENTRIES); | |
414 | + NFS_SCAN_MAXENTRIES, tag); | |
415 | 415 | if (found <= 0) |
416 | 416 | break; |
417 | 417 | for (i = 0; i < found; i++) { |
418 | 418 | |
... | ... | @@ -419,10 +419,10 @@ |
419 | 419 | if (req->wb_index > idx_end) |
420 | 420 | goto out; |
421 | 421 | idx_start = req->wb_index + 1; |
422 | - if (req->wb_list_head != head) | |
423 | - continue; | |
424 | 422 | if (nfs_set_page_tag_locked(req)) { |
425 | 423 | nfs_list_remove_request(req); |
424 | + radix_tree_tag_clear(&nfsi->nfs_page_tree, | |
425 | + req->wb_index, tag); | |
426 | 426 | nfs_list_add_request(req, dst); |
427 | 427 | res++; |
428 | 428 | } |
fs/nfs/write.c
... | ... | @@ -462,6 +462,9 @@ |
462 | 462 | nfs_list_add_request(req, &nfsi->commit); |
463 | 463 | nfsi->ncommit++; |
464 | 464 | set_bit(PG_NEED_COMMIT, &(req)->wb_flags); |
465 | + radix_tree_tag_set(&nfsi->nfs_page_tree, | |
466 | + req->wb_index, | |
467 | + NFS_PAGE_TAG_COMMIT); | |
465 | 468 | spin_unlock(&nfsi->req_lock); |
466 | 469 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
467 | 470 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
... | ... | @@ -575,7 +578,8 @@ |
575 | 578 | int res = 0; |
576 | 579 | |
577 | 580 | if (nfsi->ncommit != 0) { |
578 | - res = nfs_scan_list(nfsi, &nfsi->commit, dst, idx_start, npages); | |
581 | + res = nfs_scan_list(nfsi, dst, idx_start, npages, | |
582 | + NFS_PAGE_TAG_COMMIT); | |
579 | 583 | nfsi->ncommit -= res; |
580 | 584 | if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit)) |
581 | 585 | printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n"); |
include/linux/nfs_page.h
... | ... | @@ -22,6 +22,7 @@ |
22 | 22 | * Valid flags for the radix tree |
23 | 23 | */ |
24 | 24 | #define NFS_PAGE_TAG_LOCKED 0 |
25 | +#define NFS_PAGE_TAG_COMMIT 1 | |
25 | 26 | |
26 | 27 | /* |
27 | 28 | * Valid flags for a dirty buffer |
... | ... | @@ -71,8 +72,8 @@ |
71 | 72 | extern void nfs_release_request(struct nfs_page *req); |
72 | 73 | |
73 | 74 | |
74 | -extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst, | |
75 | - pgoff_t idx_start, unsigned int npages); | |
75 | +extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst, | |
76 | + pgoff_t idx_start, unsigned int npages, int tag); | |
76 | 77 | extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc, |
77 | 78 | struct inode *inode, |
78 | 79 | int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int), |