X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=fs%2Fnfs%2Fpagelist.c;h=e046c9b6a9dd201315b40e2e4532f414e906fdb4;hb=3f442547b76bf9fb70d7aecc41cf1980459253c9;hp=36e902a88ca1b92bd9e81cee86317fa18a427d63;hpb=ca78f6baca863afe2e6a244a0fe94b3a70211d46;p=linux-2.6-omap-h63xx.git diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 36e902a88ca..e046c9b6a9d 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -17,6 +17,7 @@ #include #include #include +#include #define NFS_PARANOIA 1 @@ -268,11 +269,10 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst, #define NFS_SCAN_MAXENTRIES 16 /** - * nfs_scan_lock_dirty - Scan the radix tree for dirty requests - * @nfsi: NFS inode + * nfs_scan_dirty - Scan the radix tree for dirty requests + * @mapping: pointer to address space + * @wbc: writeback_control structure * @dst: Destination list - * @idx_start: lower bound of page->index to scan - * @npages: idx_start + npages sets the upper bound to scan. * * Moves elements from one of the inode request lists. * If the number of requests is set to 0, the entire address_space @@ -280,46 +280,72 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst, * The requests are *not* checked to ensure that they form a contiguous set. * You must be holding the inode's req_lock when calling this function */ -int -nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst, - unsigned long idx_start, unsigned int npages) +long nfs_scan_dirty(struct address_space *mapping, + struct writeback_control *wbc, + struct list_head *dst) { + struct nfs_inode *nfsi = NFS_I(mapping->host); struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES]; struct nfs_page *req; - unsigned long idx_end; + pgoff_t idx_start, idx_end; + long count = wbc->nr_to_write; + long res = 0; int found, i; - int res; - res = 0; - if (npages == 0) - idx_end = ~0; - else - idx_end = idx_start + npages - 1; + if (nfsi->ndirty == 0 || count <= 0) + return 0; + if (wbc->range_cyclic) { + idx_start = 0; + idx_end = ULONG_MAX; + } else if (wbc->range_end == 0) { + idx_start = wbc->range_start >> PAGE_CACHE_SHIFT; + idx_end = ULONG_MAX; + } else { + idx_start = wbc->range_start >> PAGE_CACHE_SHIFT; + idx_end = wbc->range_end >> PAGE_CACHE_SHIFT; + } for (;;) { + unsigned int toscan = NFS_SCAN_MAXENTRIES; + + if (toscan > count) + toscan = count; found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, - (void **)&pgvec[0], idx_start, NFS_SCAN_MAXENTRIES, + (void **)&pgvec[0], idx_start, toscan, NFS_PAGE_TAG_DIRTY); + + /* Did we make progress? */ if (found <= 0) break; + for (i = 0; i < found; i++) { req = pgvec[i]; - if (req->wb_index > idx_end) + if (!wbc->range_cyclic && req->wb_index > idx_end) goto out; - idx_start = req->wb_index + 1; + /* Try to lock request and mark it for writeback */ + if (!nfs_set_page_writeback_locked(req)) + goto next; + radix_tree_tag_clear(&nfsi->nfs_page_tree, + req->wb_index, NFS_PAGE_TAG_DIRTY); + nfsi->ndirty--; + nfs_list_remove_request(req); + nfs_list_add_request(req, dst); + dec_zone_page_state(req->wb_page, NR_FILE_DIRTY); + res++; + if (res == LONG_MAX) + goto out; + count--; + if (count == 0) + goto out; - if (nfs_set_page_writeback_locked(req)) { - radix_tree_tag_clear(&nfsi->nfs_page_tree, - req->wb_index, NFS_PAGE_TAG_DIRTY); - nfs_list_remove_request(req); - nfs_list_add_request(req, dst); - dec_zone_page_state(req->wb_page, NR_FILE_DIRTY); - res++; - } +next: + idx_start = req->wb_index + 1; } } out: + wbc->nr_to_write = count; + WARN_ON ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty)); return res; } @@ -392,7 +418,6 @@ int __init nfs_init_nfspagecache(void) void nfs_destroy_nfspagecache(void) { - if (kmem_cache_destroy(nfs_page_cachep)) - printk(KERN_INFO "nfs_page: not all structures were freed\n"); + kmem_cache_destroy(nfs_page_cachep); }