forked from luck/tmp_suning_uos_patched
NFS: Fix race in nfs_set_page_dirty
Protect nfs_set_page_dirty() against races with nfs_inode_add_request. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
612c9384fd
commit
2b82f190c8
|
@ -388,6 +388,8 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
|
|||
}
|
||||
SetPagePrivate(req->wb_page);
|
||||
set_page_private(req->wb_page, (unsigned long)req);
|
||||
if (PageDirty(req->wb_page))
|
||||
set_bit(PG_NEED_FLUSH, &req->wb_flags);
|
||||
nfsi->npages++;
|
||||
atomic_inc(&req->wb_count);
|
||||
return 0;
|
||||
|
@ -407,6 +409,8 @@ static void nfs_inode_remove_request(struct nfs_page *req)
|
|||
set_page_private(req->wb_page, 0);
|
||||
ClearPagePrivate(req->wb_page);
|
||||
radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
|
||||
if (test_and_clear_bit(PG_NEED_FLUSH, &req->wb_flags))
|
||||
__set_page_dirty_nobuffers(req->wb_page);
|
||||
nfsi->npages--;
|
||||
if (!nfsi->npages) {
|
||||
spin_unlock(&nfsi->req_lock);
|
||||
|
@ -1527,15 +1531,22 @@ int nfs_wb_page(struct inode *inode, struct page* page)
|
|||
|
||||
int nfs_set_page_dirty(struct page *page)
|
||||
{
|
||||
spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
|
||||
struct nfs_page *req;
|
||||
int ret;
|
||||
|
||||
req = nfs_page_find_request(page);
|
||||
spin_lock(req_lock);
|
||||
req = nfs_page_find_request_locked(page);
|
||||
if (req != NULL) {
|
||||
/* Mark any existing write requests for flushing */
|
||||
set_bit(PG_NEED_FLUSH, &req->wb_flags);
|
||||
ret = !test_and_set_bit(PG_NEED_FLUSH, &req->wb_flags);
|
||||
spin_unlock(req_lock);
|
||||
nfs_release_request(req);
|
||||
return ret;
|
||||
}
|
||||
return __set_page_dirty_nobuffers(page);
|
||||
ret = __set_page_dirty_nobuffers(page);
|
||||
spin_unlock(req_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user