Merge tag 'sound-6.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[linux-block.git] / net / 9p / client.c
index 0638b12055ba4153edb516e62d9668a43d0a7ede..622ec6a586eea993b0adcdd91655f37c3937998f 100644 (file)
@@ -297,6 +297,11 @@ p9_tag_alloc(struct p9_client *c, int8_t type, uint t_size, uint r_size,
        p9pdu_reset(&req->rc);
        req->t_err = 0;
        req->status = REQ_STATUS_ALLOC;
+       /* refcount needs to be set to 0 before inserting into the idr
+        * so p9_tag_lookup does not accept a request that is not fully
+        * initialized. refcount_set to 2 below will mark request ready.
+        */
+       refcount_set(&req->refcount, 0);
        init_waitqueue_head(&req->wq);
        INIT_LIST_HEAD(&req->req_list);
 
@@ -438,7 +443,7 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)
         * the status change is visible to another thread
         */
        smp_wmb();
-       req->status = status;
+       WRITE_ONCE(req->status, status);
 
        wake_up(&req->wq);
        p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag);
@@ -514,10 +519,9 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
        int ecode;
 
        err = p9_parse_header(&req->rc, NULL, &type, NULL, 0);
-       if (req->rc.size >= c->msize) {
-               p9_debug(P9_DEBUG_ERROR,
-                        "requested packet size too big: %d\n",
-                        req->rc.size);
+       if (req->rc.size > req->rc.capacity && !req->rc.zc) {
+               pr_err("requested packet size too big: %d does not fit %zu (type=%d)\n",
+                      req->rc.size, req->rc.capacity, req->rc.id);
                return -EIO;
        }
        /* dump the response from server
@@ -600,7 +604,7 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
        /* if we haven't received a response for oldreq,
         * remove it from the list
         */
-       if (oldreq->status == REQ_STATUS_SENT) {
+       if (READ_ONCE(oldreq->status) == REQ_STATUS_SENT) {
                if (c->trans_mod->cancelled)
                        c->trans_mod->cancelled(c, oldreq);
        }
@@ -680,6 +684,9 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
        if (IS_ERR(req))
                return req;
 
+       req->tc.zc = false;
+       req->rc.zc = false;
+
        if (signal_pending(current)) {
                sigpending = 1;
                clear_thread_flag(TIF_SIGPENDING);
@@ -697,7 +704,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
        }
 again:
        /* Wait for the response */
-       err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD);
+       err = wait_event_killable(req->wq,
+                                 READ_ONCE(req->status) >= REQ_STATUS_RCVD);
 
        /* Make sure our req is coherent with regard to updates in other
         * threads - echoes to wmb() in the callback
@@ -711,7 +719,7 @@ again:
                goto again;
        }
 
-       if (req->status == REQ_STATUS_ERROR) {
+       if (READ_ONCE(req->status) == REQ_STATUS_ERROR) {
                p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
                err = req->t_err;
        }
@@ -724,7 +732,7 @@ again:
                        p9_client_flush(c, req);
 
                /* if we received the response anyway, don't signal error */
-               if (req->status == REQ_STATUS_RCVD)
+               if (READ_ONCE(req->status) == REQ_STATUS_RCVD)
                        err = 0;
        }
 recalc_sigpending:
@@ -778,6 +786,9 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
        if (IS_ERR(req))
                return req;
 
+       req->tc.zc = true;
+       req->rc.zc = true;
+
        if (signal_pending(current)) {
                sigpending = 1;
                clear_thread_flag(TIF_SIGPENDING);
@@ -793,7 +804,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
                if (err != -ERESTARTSYS)
                        goto recalc_sigpending;
        }
-       if (req->status == REQ_STATUS_ERROR) {
+       if (READ_ONCE(req->status) == REQ_STATUS_ERROR) {
                p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
                err = req->t_err;
        }
@@ -806,7 +817,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
                        p9_client_flush(c, req);
 
                /* if we received the response anyway, don't signal error */
-               if (req->status == REQ_STATUS_RCVD)
+               if (READ_ONCE(req->status) == REQ_STATUS_RCVD)
                        err = 0;
        }
 recalc_sigpending: