diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c
index b27ed1c..f7914f5 100644
--- a/fs/orangefs/devorangefs-req.c
+++ b/fs/orangefs/devorangefs-req.c
@@ -58,9 +58,9 @@ static struct orangefs_kernel_op_s
*orangefs_devreq_remove_op(__u64 tag)
  next,
  &htable_ops_in_progress[index],
  list) {
- if (op->tag == tag && !op_state_purged(op)) {
+ if (op->tag == tag && !op_state_purged(op) &&
+    !op_state_given_up(op)) {
  list_del_init(&op->list);
- get_op(op); /* increase ref count. */
  spin_unlock(&htable_ops_in_progress_lock);
  return op;
  }
@@ -133,7 +133,7 @@ restart:
  __s32 fsid;
  /* This lock is held past the end of the loop when we break. */
  spin_lock(&op->lock);
- if (unlikely(op_state_purged(op))) {
+ if (unlikely(op_state_purged(op) || op_state_given_up(op))) {
  spin_unlock(&op->lock);
  continue;
  }
@@ -199,13 +199,12 @@ restart:
  */
  if (op_state_in_progress(cur_op) || op_state_serviced(cur_op)) {
  gossip_err("orangefs: ERROR: Current op already queued.\n");
- list_del(&cur_op->list);
+ list_del_init(&cur_op->list);
  spin_unlock(&cur_op->lock);
  spin_unlock(&orangefs_request_list_lock);
  return -EAGAIN;
  }
  list_del_init(&cur_op->list);
- get_op(op);
  spin_unlock(&orangefs_request_list_lock);

  spin_unlock(&cur_op->lock);
@@ -230,7 +229,7 @@ restart:
  if (unlikely(op_state_given_up(cur_op))) {
  spin_unlock(&cur_op->lock);
  spin_unlock(&htable_ops_in_progress_lock);
- op_release(cur_op);
+ complete(&cur_op->waitq);
  goto restart;
  }

@@ -242,7 +241,6 @@ restart:
  orangefs_devreq_add_op(cur_op);
  spin_unlock(&cur_op->lock);
  spin_unlock(&htable_ops_in_progress_lock);
- op_release(cur_op);

  /* The client only asks to read one size buffer. */
  return MAX_DEV_REQ_UPSIZE;
@@ -258,10 +256,12 @@ error:
  if (likely(!op_state_given_up(cur_op))) {
  set_op_state_waiting(cur_op);
  list_add(&cur_op->list, &orangefs_request_list);
+ spin_unlock(&cur_op->lock);
+ } else {
+ spin_unlock(&cur_op->lock);
+ complete(&cur_op->waitq);
  }
- spin_unlock(&cur_op->lock);
  spin_unlock(&orangefs_request_list_lock);
- op_release(cur_op);
  return -EFAULT;
 }

@@ -333,8 +333,7 @@ static ssize_t orangefs_devreq_write_iter(struct
kiocb *iocb,
  n = copy_from_iter(&op->downcall, downcall_size, iter);
  if (n != downcall_size) {
  gossip_err("%s: failed to copy downcall.\n", __func__);
- ret = -EFAULT;
- goto Broken;
+ goto Efault;
  }

  if (op->downcall.status)
@@ -354,8 +353,7 @@ static ssize_t orangefs_devreq_write_iter(struct
kiocb *iocb,
    downcall_size,
    op->downcall.trailer_size,
    total);
- ret = -EFAULT;
- goto Broken;
+ goto Efault;
  }

  /* Only READDIR operations should have trailers. */
@@ -364,8 +362,7 @@ static ssize_t orangefs_devreq_write_iter(struct
kiocb *iocb,
  gossip_err("%s: %x operation with trailer.",
    __func__,
    op->downcall.type);
- ret = -EFAULT;
- goto Broken;
+ goto Efault;
  }

  /* READDIR operations should always have trailers. */
@@ -374,8 +371,7 @@ static ssize_t orangefs_devreq_write_iter(struct
kiocb *iocb,
  gossip_err("%s: %x operation with no trailer.",
    __func__,
    op->downcall.type);
- ret = -EFAULT;
- goto Broken;
+ goto Efault;
  }

  if (op->downcall.type != ORANGEFS_VFS_OP_READDIR)
@@ -386,8 +382,7 @@ static ssize_t orangefs_devreq_write_iter(struct
kiocb *iocb,
  if (op->downcall.trailer_buf == NULL) {
  gossip_err("%s: failed trailer vmalloc.\n",
    __func__);
- ret = -ENOMEM;
- goto Broken;
+ goto Enomem;
  }
  memset(op->downcall.trailer_buf, 0, op->downcall.trailer_size);
  n = copy_from_iter(op->downcall.trailer_buf,
@@ -396,8 +391,7 @@ static ssize_t orangefs_devreq_write_iter(struct
kiocb *iocb,
  if (n != op->downcall.trailer_size) {
  gossip_err("%s: failed to copy trailer.\n", __func__);
  vfree(op->downcall.trailer_buf);
- ret = -EFAULT;
- goto Broken;
+ goto Efault;
  }

 wakeup:
@@ -406,38 +400,27 @@ wakeup:
  * that this op is done
  */
  spin_lock(&op->lock);
- if (unlikely(op_state_given_up(op))) {
+ if (unlikely(op_is_cancel(op))) {
  spin_unlock(&op->lock);
- goto out;
- }
- set_op_state_serviced(op);
- spin_unlock(&op->lock);
-
- /*
- * If this operation is an I/O operation we need to wait
- * for all data to be copied before we can return to avoid
- * buffer corruption and races that can pull the buffers
- * out from under us.
- *
- * Essentially we're synchronizing with other parts of the
- * vfs implicitly by not allowing the user space
- * application reading/writing this device to return until
- * the buffers are done being used.
- */
-out:
- if (unlikely(op_is_cancel(op)))
  put_cancel(op);
- op_release(op);
- return ret;
-
-Broken:
- spin_lock(&op->lock);
- if (!op_state_given_up(op)) {
- op->downcall.status = ret;
+ } else if (unlikely(op_state_given_up(op))) {
+ spin_unlock(&op->lock);
+ complete(&op->waitq);
+ } else {
  set_op_state_serviced(op);
+ spin_unlock(&op->lock);
  }
- spin_unlock(&op->lock);
- goto out;
+ return ret;
+
+Efault:
+ op->downcall.status = -(ORANGEFS_ERROR_BIT | 9);
+ ret = -EFAULT;
+ goto wakeup;
+
+Enomem:
+ op->downcall.status = -(ORANGEFS_ERROR_BIT | 8);
+ ret = -ENOMEM;
+ goto wakeup;
 }

 /* Returns whether any FS are still pending remounted */
diff --git a/fs/orangefs/orangefs-cache.c b/fs/orangefs/orangefs-cache.c
index 817092a..900a2e3 100644
--- a/fs/orangefs/orangefs-cache.c
+++ b/fs/orangefs/orangefs-cache.c
@@ -120,8 +120,6 @@ struct orangefs_kernel_op_s *op_alloc(__s32 type)
  spin_lock_init(&new_op->lock);
  init_completion(&new_op->waitq);

- atomic_set(&new_op->ref_count, 1);
-
  new_op->upcall.type = ORANGEFS_VFS_OP_INVALID;
  new_op->downcall.type = ORANGEFS_VFS_OP_INVALID;
  new_op->downcall.status = -1;
@@ -149,7 +147,7 @@ struct orangefs_kernel_op_s *op_alloc(__s32 type)
  return new_op;
 }

-void __op_release(struct orangefs_kernel_op_s *orangefs_op)
+void op_release(struct orangefs_kernel_op_s *orangefs_op)
 {
  if (orangefs_op) {
  gossip_debug(GOSSIP_CACHE_DEBUG,
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 1f8310c..e387d3c 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -205,8 +205,6 @@ struct orangefs_kernel_op_s {
  struct completion waitq;
  spinlock_t lock;

- atomic_t ref_count;
-
  /* VFS aio fields */

  int attempts;
@@ -230,23 +228,7 @@ static inline void set_op_state_serviced(struct
orangefs_kernel_op_s *op)
 #define op_state_given_up(op)    ((op)->op_state & OP_VFS_STATE_GIVEN_UP)
 #define op_is_cancel(op)         ((op)->downcall.type ==
ORANGEFS_VFS_OP_CANCEL)

-static inline void get_op(struct orangefs_kernel_op_s *op)
-{
- atomic_inc(&op->ref_count);
- gossip_debug(GOSSIP_DEV_DEBUG,
- "(get) Alloced OP (%p:%llu)\n", op, llu(op->tag));
-}
-
-void __op_release(struct orangefs_kernel_op_s *op);
-
-static inline void op_release(struct orangefs_kernel_op_s *op)
-{
- if (atomic_dec_and_test(&op->ref_count)) {
- gossip_debug(GOSSIP_DEV_DEBUG,
- "(put) Releasing OP (%p:%llu)\n", op, llu((op)->tag));
- __op_release(op);
- }
-}
+void op_release(struct orangefs_kernel_op_s *op);

 extern void orangefs_bufmap_put(int);
 static inline void put_cancel(struct orangefs_kernel_op_s *op)
@@ -259,7 +241,7 @@ static inline void set_op_state_purged(struct
orangefs_kernel_op_s *op)
 {
  spin_lock(&op->lock);
  if (unlikely(op_is_cancel(op))) {
- list_del(&op->list);
+ list_del_init(&op->list);
  spin_unlock(&op->lock);
  put_cancel(op);
  } else {
diff --git a/fs/orangefs/waitqueue.c b/fs/orangefs/waitqueue.c
index 2528d58..0ea2741 100644
--- a/fs/orangefs/waitqueue.c
+++ b/fs/orangefs/waitqueue.c
@@ -65,7 +65,7 @@ int service_operation(struct orangefs_kernel_op_s *op,
  op->upcall.pid = current->pid;

 retry_servicing:
- op->downcall.status = 0;
+ op->downcall.status = OP_VFS_STATE_UNKNOWN;
  gossip_debug(GOSSIP_WAIT_DEBUG,
      "%s: %s op:%p: process:%s: pid:%d:\n",
      __func__,
@@ -103,8 +103,9 @@ retry_servicing:
  wake_up_interruptible(&orangefs_request_list_waitq);
  if (!__is_daemon_in_service()) {
  gossip_debug(GOSSIP_WAIT_DEBUG,
-     "%s:client core is NOT in service.\n",
-     __func__);
+     "%s:client core is NOT in service, %p.\n",
+     __func__,
+     op);
  timeout = op_timeout_secs * HZ;
  }
  spin_unlock(&orangefs_request_list_lock);
@@ -208,15 +209,20 @@ static void
orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s
  * Called with op->lock held.
  */
  op->op_state |= OP_VFS_STATE_GIVEN_UP;
-
- if (op_state_waiting(op)) {
+ /* from that point on it can't be moved by anybody else */
+ if (list_empty(&op->list)) {
+ /* caught copying to/from daemon */
+ BUG_ON(op_state_serviced(op));
+ spin_unlock(&op->lock);
+ wait_for_completion(&op->waitq);
+ } else if (op_state_waiting(op)) {
  /*
  * upcall hasn't been read; remove op from upcall request
  * list.
  */
  spin_unlock(&op->lock);
  spin_lock(&orangefs_request_list_lock);
- list_del(&op->list);
+ list_del_init(&op->list);
  spin_unlock(&orangefs_request_list_lock);
  gossip_debug(GOSSIP_WAIT_DEBUG,
