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>
diff --git a/fs/orangefs/orangefs-sysfs.c b/fs/orangefs/orangefs-sysfs.c
index 3d36038..83f4053 100644
--- a/fs/orangefs/orangefs-sysfs.c
+++ b/fs/orangefs/orangefs-sysfs.c
@@ -773,10 +773,8 @@
 		op_alloc_type = ORANGEFS_VFS_OP_PERF_COUNT;
 
 	new_op = op_alloc(op_alloc_type);
-	if (!new_op) {
-		rc = -ENOMEM;
-		goto out;
-	}
+	if (!new_op)
+		return -ENOMEM;
 
 	/* Can't do a service_operation if the client is not running... */
 	rc = is_daemon_in_service();
@@ -931,11 +929,7 @@
 		}
 	}
 
-	/*
-	 * if we got ENOMEM, then op_alloc probably failed...
-	 */
-	if (rc != -ENOMEM)
-		op_release(new_op);
+	op_release(new_op);
 
 	return rc;
 
@@ -1039,10 +1033,8 @@
 		     kobj_id);
 
 	new_op = op_alloc(ORANGEFS_VFS_OP_PARAM);
-	if (!new_op) {
-		rc = -ENOMEM;
-		goto out;
-	}
+	if (!new_op)
+		return -EINVAL; /* sic */
 
 	/* Can't do a service_operation if the client is not running... */
 	rc = is_daemon_in_service();
@@ -1269,15 +1261,9 @@
 	}
 
 out:
-	/*
-	 * if we got ENOMEM, then op_alloc probably failed...
-	 */
-	if (rc == -ENOMEM)
-		rc = 0;
-	else
-		op_release(new_op);
+	op_release(new_op);
 
-	if (rc == 0)
+	if (rc == -ENOMEM || rc == 0)
 		rc = -EINVAL;
 
 	return rc;