diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-07 11:36:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-07 11:36:45 -0500 |
commit | 4c9014f2ca7e5ecf8806e838be0f07aa1810c985 (patch) | |
tree | dd33fdebedf1ce6497737113e183f2a5d8bbca63 /net/sunrpc/sched.c | |
parent | 5ce2955e04a80da7287dc12f32da7f870039bf8f (diff) | |
parent | ecf0eb9edbb607d74f74b73c14af8b43f3729528 (diff) |
Merge tag 'nfs-for-3.8-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust:
- Fix a permissions problem when opening NFSv4 files that only have the
exec bit set.
- Fix a couple of typos in pNFS (inverted logic), and the mount parsing
(missing pointer dereference).
- Work around a series of deadlock issues due to workqueues using
struct work_struct pointer address comparisons in the re-entrancy
tests. Ensure that we don't free struct work_struct prematurely if
our work function involves waiting for completion of other work items
(e.g. by calling rpc_shutdown_client).
- Revert the part of commit 168e4b3 that is causing unnecessary
warnings to be issued in the nfsd callback code.
* tag 'nfs-for-3.8-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
nfs: avoid dereferencing null pointer in initiate_bulk_draining
SUNRPC: Partial revert of commit 168e4b39d1afb79a7e3ea6c3bb246b4c82c6bdb9
NFS: Ensure that we free the rpc_task after read and write cleanups are done
SUNRPC: Ensure that we free the rpc_task after cleanups are done
nfs: fix null checking in nfs_get_option_str()
pnfs: Increase the refcount when LAYOUTGET fails the first time
NFS: Fix access to suid/sgid executables
Diffstat (limited to 'net/sunrpc/sched.c')
-rw-r--r-- | net/sunrpc/sched.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index d17a704aaf5f..b4133bd13915 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -934,16 +934,35 @@ struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data) | |||
934 | return task; | 934 | return task; |
935 | } | 935 | } |
936 | 936 | ||
937 | /* | ||
938 | * rpc_free_task - release rpc task and perform cleanups | ||
939 | * | ||
940 | * Note that we free up the rpc_task _after_ rpc_release_calldata() | ||
941 | * in order to work around a workqueue dependency issue. | ||
942 | * | ||
943 | * Tejun Heo states: | ||
944 | * "Workqueue currently considers two work items to be the same if they're | ||
945 | * on the same address and won't execute them concurrently - ie. it | ||
946 | * makes a work item which is queued again while being executed wait | ||
947 | * for the previous execution to complete. | ||
948 | * | ||
949 | * If a work function frees the work item, and then waits for an event | ||
950 | * which should be performed by another work item and *that* work item | ||
951 | * recycles the freed work item, it can create a false dependency loop. | ||
952 | * There really is no reliable way to detect this short of verifying | ||
953 | * every memory free." | ||
954 | * | ||
955 | */ | ||
937 | static void rpc_free_task(struct rpc_task *task) | 956 | static void rpc_free_task(struct rpc_task *task) |
938 | { | 957 | { |
939 | const struct rpc_call_ops *tk_ops = task->tk_ops; | 958 | unsigned short tk_flags = task->tk_flags; |
940 | void *calldata = task->tk_calldata; | 959 | |
960 | rpc_release_calldata(task->tk_ops, task->tk_calldata); | ||
941 | 961 | ||
942 | if (task->tk_flags & RPC_TASK_DYNAMIC) { | 962 | if (tk_flags & RPC_TASK_DYNAMIC) { |
943 | dprintk("RPC: %5u freeing task\n", task->tk_pid); | 963 | dprintk("RPC: %5u freeing task\n", task->tk_pid); |
944 | mempool_free(task, rpc_task_mempool); | 964 | mempool_free(task, rpc_task_mempool); |
945 | } | 965 | } |
946 | rpc_release_calldata(tk_ops, calldata); | ||
947 | } | 966 | } |
948 | 967 | ||
949 | static void rpc_async_release(struct work_struct *work) | 968 | static void rpc_async_release(struct work_struct *work) |