rxrpc: Allow the kernel to mark a call as being non-interruptible
[linux-2.6-block.git] / fs / afs / rxrpc.c
index 3ed2c99c58abe4325661a6a3cbf12bbab2b2cdcf..87763379952d3853b58cd663e7a8f9baf0ababcb 100644 (file)
@@ -21,7 +21,6 @@
 struct workqueue_struct *afs_async_calls;
 
 static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
-static long afs_wait_for_call_to_complete(struct afs_call *, struct afs_addr_cursor *);
 static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
 static void afs_delete_async_call(struct work_struct *);
 static void afs_process_async_call(struct work_struct *);
@@ -361,10 +360,10 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg)
 }
 
 /*
- * initiate a call
+ * Initiate a call and synchronously queue up the parameters for dispatch.  Any
+ * error is stored into the call struct, which the caller must check for.
  */
-long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
-                  gfp_t gfp, bool async)
+void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
 {
        struct sockaddr_rxrpc *srx = &ac->alist->addrs[ac->index];
        struct rxrpc_call *rxcall;
@@ -382,7 +381,6 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
               call, call->type->name, key_serial(call->key),
               atomic_read(&call->net->nr_outstanding_calls));
 
-       call->async = async;
        call->addr_ix = ac->index;
        call->alist = afs_get_addrlist(ac->alist);
 
@@ -415,10 +413,11 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
        rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key,
                                         (unsigned long)call,
                                         tx_total_len, gfp,
-                                        (async ?
+                                        (call->async ?
                                          afs_wake_up_async_call :
                                          afs_wake_up_call_waiter),
                                         call->upgrade,
+                                        true,
                                         call->debug_id);
        if (IS_ERR(rxcall)) {
                ret = PTR_ERR(rxcall);
@@ -428,6 +427,10 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
 
        call->rxcall = rxcall;
 
+       if (call->max_lifespan)
+               rxrpc_kernel_set_max_life(call->net->socket, rxcall,
+                                         call->max_lifespan);
+
        /* send the request */
        iov[0].iov_base = call->request;
        iov[0].iov_len  = call->request_size;
@@ -453,13 +456,11 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
 
        /* Note that at this point, we may have received the reply or an abort
         * - and an asynchronous call may already have completed.
+        *
+        * afs_wait_for_call_to_complete(call, ac)
+        * must be called to synchronously clean up.
         */
-       if (call->async) {
-               afs_put_call(call);
-               return -EINPROGRESS;
-       }
-
-       return afs_wait_for_call_to_complete(call, ac);
+       return;
 
 error_do_abort:
        if (ret != -ECONNABORTED) {
@@ -495,9 +496,7 @@ error_kill_call:
 
        ac->error = ret;
        call->state = AFS_CALL_COMPLETE;
-       afs_put_call(call);
        _leave(" = %d", ret);
-       return ret;
 }
 
 /*
@@ -604,10 +603,10 @@ call_complete:
 }
 
 /*
- * wait synchronously for a call to complete
+ * Wait synchronously for a call to complete and clean up the call struct.
  */
-static long afs_wait_for_call_to_complete(struct afs_call *call,
-                                         struct afs_addr_cursor *ac)
+long afs_wait_for_call_to_complete(struct afs_call *call,
+                                  struct afs_addr_cursor *ac)
 {
        signed long rtt2, timeout;
        long ret;
@@ -620,6 +619,10 @@ static long afs_wait_for_call_to_complete(struct afs_call *call,
 
        _enter("");
 
+       ret = call->error;
+       if (ret < 0)
+               goto out;
+
        rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall);
        rtt2 = nsecs_to_jiffies64(rtt) * 2;
        if (rtt2 < 2)
@@ -703,6 +706,7 @@ static long afs_wait_for_call_to_complete(struct afs_call *call,
                break;
        }
 
+out:
        _debug("call complete");
        afs_put_call(call);
        _leave(" = %p", (void *)ret);