diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-01-22 19:47:47 -0500 |
---|---|---|
committer | Mike Marshall <hubcap@omnibond.com> | 2016-01-23 13:03:12 -0500 |
commit | ed42fe059389daa35a2aa10ec832e9f8d0a9e59e (patch) | |
tree | 778e6ebb516e7a6301305b077e31ee40d9fe96c2 /fs/orangefs/waitqueue.c | |
parent | fee25ce12504ff071254fd213055c3f1d3004622 (diff) | |
download | lwn-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.c | 24 |
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); |