summaryrefslogtreecommitdiff
path: root/fs/orangefs/waitqueue.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-01-22 19:47:47 -0500
committerMike Marshall <hubcap@omnibond.com>2016-01-23 13:03:12 -0500
commited42fe059389daa35a2aa10ec832e9f8d0a9e59e (patch)
tree778e6ebb516e7a6301305b077e31ee40d9fe96c2 /fs/orangefs/waitqueue.c
parentfee25ce12504ff071254fd213055c3f1d3004622 (diff)
downloadlwn-ed42fe059389daa35a2aa10ec832e9f8d0a9e59e.tar.gz
lwn-ed42fe059389daa35a2aa10ec832e9f8d0a9e59e.zip
orangefs: hopefully saner op refcounting and locking
* create with refcount 1 * make op_release() decrement and free if zero (i.e. old put_op() has become that). * mark when submitter has given up waiting; from that point nobody else can move between the lists, change state, etc. * have daemon read/write_iter grab a reference when picking op and *always* give it up in the end * don't put into hash until we know it's been successfully passed to daemon * move op->lock _lower_ than htab_in_progress_lock (and make sure to take it in purge_inprogress_ops()) Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Mike Marshall <hubcap@omnibond.com>
Diffstat (limited to 'fs/orangefs/waitqueue.c')
-rw-r--r--fs/orangefs/waitqueue.c24
1 files changed, 4 insertions, 20 deletions
diff --git a/fs/orangefs/waitqueue.c b/fs/orangefs/waitqueue.c
index a257891dd3ea..2e9468f57981 100644
--- a/fs/orangefs/waitqueue.c
+++ b/fs/orangefs/waitqueue.c
@@ -279,25 +279,6 @@ retry_servicing:
return ret;
}
-static inline void remove_op_from_request_list(struct orangefs_kernel_op_s *op)
-{
- struct list_head *tmp = NULL;
- struct list_head *tmp_safe = NULL;
- struct orangefs_kernel_op_s *tmp_op = NULL;
-
- spin_lock(&orangefs_request_list_lock);
- list_for_each_safe(tmp, tmp_safe, &orangefs_request_list) {
- tmp_op = list_entry(tmp,
- struct orangefs_kernel_op_s,
- list);
- if (tmp_op && (tmp_op == op)) {
- list_del(&tmp_op->list);
- break;
- }
- }
- spin_unlock(&orangefs_request_list_lock);
-}
-
static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s *op)
{
/*
@@ -334,6 +315,7 @@ static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s
}
spin_lock(&op->lock);
+ op->op_state |= OP_VFS_STATE_GIVEN_UP;
if (op_state_waiting(op)) {
/*
@@ -341,7 +323,9 @@ static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s
* list.
*/
spin_unlock(&op->lock);
- remove_op_from_request_list(op);
+ spin_lock(&orangefs_request_list_lock);
+ list_del(&op->list);
+ spin_unlock(&orangefs_request_list_lock);
gossip_debug(GOSSIP_WAIT_DEBUG,
"Interrupted: Removed op %p from request_list\n",
op);