aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-11-13 16:23:44 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-12-06 10:46:26 -0500
commit8aca67f0ae2d8811165c22326825a645cc8e1b48 (patch)
tree19e82f4bc7b4f865a9dcf4744e7c224ea517ba10 /include
parente6b3c4db6fbcd0d33720696f37790d6b8be12313 (diff)
SUNRPC: Fix a potential race in rpc_wake_up_task()
Use RCU to ensure that we can safely call rpc_finish_wakeup after we've called __rpc_do_wake_up_task. If not, there is a theoretical race, in which the rpc_task finishes executing, and gets freed first. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'include')
-rw-r--r--include/linux/nfs_fs.h7
-rw-r--r--include/linux/sunrpc/sched.h2
2 files changed, 4 insertions, 5 deletions
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 625ffea98561..02f38189d180 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -428,11 +428,6 @@ extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned
428extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *); 428extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
429extern void nfs_writedata_release(void *); 429extern void nfs_writedata_release(void *);
430 430
431#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
432struct nfs_write_data *nfs_commit_alloc(void);
433void nfs_commit_free(struct nfs_write_data *p);
434#endif
435
436/* 431/*
437 * Try to write back everything synchronously (but check the 432 * Try to write back everything synchronously (but check the
438 * return value!) 433 * return value!)
@@ -440,6 +435,8 @@ void nfs_commit_free(struct nfs_write_data *p);
440extern int nfs_sync_inode_wait(struct inode *, unsigned long, unsigned int, int); 435extern int nfs_sync_inode_wait(struct inode *, unsigned long, unsigned int, int);
441#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 436#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
442extern int nfs_commit_inode(struct inode *, int); 437extern int nfs_commit_inode(struct inode *, int);
438extern struct nfs_write_data *nfs_commit_alloc(void);
439extern void nfs_commit_free(struct nfs_write_data *wdata);
443extern void nfs_commit_release(void *wdata); 440extern void nfs_commit_release(void *wdata);
444#else 441#else
445static inline int 442static inline int
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 9fdb8c9d09f2..14fc813ddd0c 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -11,6 +11,7 @@
11 11
12#include <linux/timer.h> 12#include <linux/timer.h>
13#include <linux/sunrpc/types.h> 13#include <linux/sunrpc/types.h>
14#include <linux/rcupdate.h>
14#include <linux/spinlock.h> 15#include <linux/spinlock.h>
15#include <linux/wait.h> 16#include <linux/wait.h>
16#include <linux/workqueue.h> 17#include <linux/workqueue.h>
@@ -85,6 +86,7 @@ struct rpc_task {
85 union { 86 union {
86 struct work_struct tk_work; /* Async task work queue */ 87 struct work_struct tk_work; /* Async task work queue */
87 struct rpc_wait tk_wait; /* RPC wait */ 88 struct rpc_wait tk_wait; /* RPC wait */
89 struct rcu_head tk_rcu; /* for task deletion */
88 } u; 90 } u;
89 91
90 unsigned short tk_timeouts; /* maj timeouts */ 92 unsigned short tk_timeouts; /* maj timeouts */