Loading fs/nfs/pagelist.c +28 −1 Original line number Diff line number Diff line Loading @@ -111,6 +111,33 @@ void nfs_unlock_request(struct nfs_page *req) nfs_release_request(req); } /** * nfs_set_page_writeback_locked - Lock a request for writeback * @req: */ int nfs_set_page_writeback_locked(struct nfs_page *req) { struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode); if (!nfs_lock_request(req)) return 0; radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK); return 1; } /** * nfs_clear_page_writeback - Unlock request and wake up sleepers */ void nfs_clear_page_writeback(struct nfs_page *req) { struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode); spin_lock(&nfsi->req_lock); radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK); spin_unlock(&nfsi->req_lock); nfs_unlock_request(req); } /** * nfs_clear_request - Free up all resources allocated to the request * @req: Loading Loading @@ -301,7 +328,7 @@ nfs_scan_list(struct list_head *head, struct list_head *dst, if (req->wb_index > idx_end) break; if (!nfs_lock_request(req)) if (!nfs_set_page_writeback_locked(req)) continue; nfs_list_remove_request(req); nfs_list_add_request(req, dst); Loading fs/nfs/read.c +0 −3 Original line number Diff line number Diff line Loading @@ -173,7 +173,6 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, if (len < PAGE_CACHE_SIZE) memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); nfs_lock_request(new); nfs_list_add_request(new, &one_request); nfs_pagein_one(&one_request, inode); return 0; Loading @@ -185,7 +184,6 @@ static void nfs_readpage_release(struct nfs_page *req) nfs_clear_request(req); nfs_release_request(req); nfs_unlock_request(req); dprintk("NFS: read done (%s/%Ld %d@%Ld)\n", req->wb_context->dentry->d_inode->i_sb->s_id, Loading Loading @@ -553,7 +551,6 @@ readpage_async_filler(void *data, struct page *page) } if (len < PAGE_CACHE_SIZE) memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); nfs_lock_request(new); nfs_list_add_request(new, desc->head); return 0; } Loading fs/nfs/write.c +9 −10 Original line number Diff line number Diff line Loading @@ -503,13 +503,12 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int spin_lock(&nfsi->req_lock); next = idx_start; while (radix_tree_gang_lookup(&nfsi->nfs_page_tree, (void **)&req, next, 1)) { while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) { if (req->wb_index > idx_end) break; next = req->wb_index + 1; if (!NFS_WBACK_BUSY(req)) continue; BUG_ON(!NFS_WBACK_BUSY(req)); atomic_inc(&req->wb_count); spin_unlock(&nfsi->req_lock); Loading Loading @@ -821,7 +820,7 @@ static void nfs_writepage_release(struct nfs_page *req) #else nfs_inode_remove_request(req); #endif nfs_unlock_request(req); nfs_clear_page_writeback(req); } static inline int flush_task_priority(int how) Loading Loading @@ -952,7 +951,7 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how) nfs_writedata_free(data); } nfs_mark_request_dirty(req); nfs_unlock_request(req); nfs_clear_page_writeback(req); return -ENOMEM; } Loading Loading @@ -1002,7 +1001,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how) struct nfs_page *req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_mark_request_dirty(req); nfs_unlock_request(req); nfs_clear_page_writeback(req); } return -ENOMEM; } Loading @@ -1029,7 +1028,7 @@ nfs_flush_list(struct list_head *head, int wpages, int how) req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_mark_request_dirty(req); nfs_unlock_request(req); nfs_clear_page_writeback(req); } return error; } Loading Loading @@ -1121,7 +1120,7 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status) nfs_inode_remove_request(req); #endif next: nfs_unlock_request(req); nfs_clear_page_writeback(req); } } Loading Loading @@ -1278,7 +1277,7 @@ nfs_commit_list(struct list_head *head, int how) req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_mark_request_commit(req); nfs_unlock_request(req); nfs_clear_page_writeback(req); } return -ENOMEM; } Loading Loading @@ -1324,7 +1323,7 @@ nfs_commit_done(struct rpc_task *task) dprintk(" mismatch\n"); nfs_mark_request_dirty(req); next: nfs_unlock_request(req); nfs_clear_page_writeback(req); res++; } sub_page_state(nr_unstable,res); Loading include/linux/nfs_page.h +8 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,11 @@ #include <asm/atomic.h> /* * Valid flags for the radix tree */ #define NFS_PAGE_TAG_WRITEBACK 1 /* * Valid flags for a dirty buffer */ Loading Loading @@ -62,6 +67,9 @@ extern int nfs_coalesce_requests(struct list_head *, struct list_head *, unsigned int); extern int nfs_wait_on_request(struct nfs_page *); extern void nfs_unlock_request(struct nfs_page *req); extern int nfs_set_page_writeback_locked(struct nfs_page *req); extern void nfs_clear_page_writeback(struct nfs_page *req); /* * Lock the page of an asynchronous request without incrementing the wb_count Loading Loading @@ -96,10 +104,6 @@ nfs_list_remove_request(struct nfs_page *req) { if (list_empty(&req->wb_list)) return; if (!NFS_WBACK_BUSY(req)) { printk(KERN_ERR "NFS: unlocked request attempted removed from list!\n"); BUG(); } list_del_init(&req->wb_list); req->wb_list_head = NULL; } Loading Loading
fs/nfs/pagelist.c +28 −1 Original line number Diff line number Diff line Loading @@ -111,6 +111,33 @@ void nfs_unlock_request(struct nfs_page *req) nfs_release_request(req); } /** * nfs_set_page_writeback_locked - Lock a request for writeback * @req: */ int nfs_set_page_writeback_locked(struct nfs_page *req) { struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode); if (!nfs_lock_request(req)) return 0; radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK); return 1; } /** * nfs_clear_page_writeback - Unlock request and wake up sleepers */ void nfs_clear_page_writeback(struct nfs_page *req) { struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode); spin_lock(&nfsi->req_lock); radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK); spin_unlock(&nfsi->req_lock); nfs_unlock_request(req); } /** * nfs_clear_request - Free up all resources allocated to the request * @req: Loading Loading @@ -301,7 +328,7 @@ nfs_scan_list(struct list_head *head, struct list_head *dst, if (req->wb_index > idx_end) break; if (!nfs_lock_request(req)) if (!nfs_set_page_writeback_locked(req)) continue; nfs_list_remove_request(req); nfs_list_add_request(req, dst); Loading
fs/nfs/read.c +0 −3 Original line number Diff line number Diff line Loading @@ -173,7 +173,6 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, if (len < PAGE_CACHE_SIZE) memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); nfs_lock_request(new); nfs_list_add_request(new, &one_request); nfs_pagein_one(&one_request, inode); return 0; Loading @@ -185,7 +184,6 @@ static void nfs_readpage_release(struct nfs_page *req) nfs_clear_request(req); nfs_release_request(req); nfs_unlock_request(req); dprintk("NFS: read done (%s/%Ld %d@%Ld)\n", req->wb_context->dentry->d_inode->i_sb->s_id, Loading Loading @@ -553,7 +551,6 @@ readpage_async_filler(void *data, struct page *page) } if (len < PAGE_CACHE_SIZE) memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); nfs_lock_request(new); nfs_list_add_request(new, desc->head); return 0; } Loading
fs/nfs/write.c +9 −10 Original line number Diff line number Diff line Loading @@ -503,13 +503,12 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int spin_lock(&nfsi->req_lock); next = idx_start; while (radix_tree_gang_lookup(&nfsi->nfs_page_tree, (void **)&req, next, 1)) { while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) { if (req->wb_index > idx_end) break; next = req->wb_index + 1; if (!NFS_WBACK_BUSY(req)) continue; BUG_ON(!NFS_WBACK_BUSY(req)); atomic_inc(&req->wb_count); spin_unlock(&nfsi->req_lock); Loading Loading @@ -821,7 +820,7 @@ static void nfs_writepage_release(struct nfs_page *req) #else nfs_inode_remove_request(req); #endif nfs_unlock_request(req); nfs_clear_page_writeback(req); } static inline int flush_task_priority(int how) Loading Loading @@ -952,7 +951,7 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how) nfs_writedata_free(data); } nfs_mark_request_dirty(req); nfs_unlock_request(req); nfs_clear_page_writeback(req); return -ENOMEM; } Loading Loading @@ -1002,7 +1001,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how) struct nfs_page *req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_mark_request_dirty(req); nfs_unlock_request(req); nfs_clear_page_writeback(req); } return -ENOMEM; } Loading @@ -1029,7 +1028,7 @@ nfs_flush_list(struct list_head *head, int wpages, int how) req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_mark_request_dirty(req); nfs_unlock_request(req); nfs_clear_page_writeback(req); } return error; } Loading Loading @@ -1121,7 +1120,7 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status) nfs_inode_remove_request(req); #endif next: nfs_unlock_request(req); nfs_clear_page_writeback(req); } } Loading Loading @@ -1278,7 +1277,7 @@ nfs_commit_list(struct list_head *head, int how) req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_mark_request_commit(req); nfs_unlock_request(req); nfs_clear_page_writeback(req); } return -ENOMEM; } Loading Loading @@ -1324,7 +1323,7 @@ nfs_commit_done(struct rpc_task *task) dprintk(" mismatch\n"); nfs_mark_request_dirty(req); next: nfs_unlock_request(req); nfs_clear_page_writeback(req); res++; } sub_page_state(nr_unstable,res); Loading
include/linux/nfs_page.h +8 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,11 @@ #include <asm/atomic.h> /* * Valid flags for the radix tree */ #define NFS_PAGE_TAG_WRITEBACK 1 /* * Valid flags for a dirty buffer */ Loading Loading @@ -62,6 +67,9 @@ extern int nfs_coalesce_requests(struct list_head *, struct list_head *, unsigned int); extern int nfs_wait_on_request(struct nfs_page *); extern void nfs_unlock_request(struct nfs_page *req); extern int nfs_set_page_writeback_locked(struct nfs_page *req); extern void nfs_clear_page_writeback(struct nfs_page *req); /* * Lock the page of an asynchronous request without incrementing the wb_count Loading Loading @@ -96,10 +104,6 @@ nfs_list_remove_request(struct nfs_page *req) { if (list_empty(&req->wb_list)) return; if (!NFS_WBACK_BUSY(req)) { printk(KERN_ERR "NFS: unlocked request attempted removed from list!\n"); BUG(); } list_del_init(&req->wb_list); req->wb_list_head = NULL; } Loading