Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
net/9p: handle correctly interrupted 9P requests
net/9p: return error when p9_client_stat fails
net/9p: set correct stat size when sending Twstat messages

+66 -65
-1
include/net/9p/client.h
··· 98 struct p9_req_t { 99 int status; 100 int t_err; 101 - u16 flush_tag; 102 wait_queue_head_t *wq; 103 struct p9_fcall *tc; 104 struct p9_fcall *rc;
··· 98 struct p9_req_t { 99 int status; 100 int t_err; 101 wait_queue_head_t *wq; 102 struct p9_fcall *tc; 103 struct p9_fcall *rc;
+55 -59
net/9p/client.c
··· 203 p9pdu_reset(req->tc); 204 p9pdu_reset(req->rc); 205 206 - req->flush_tag = 0; 207 req->tc->tag = tag-1; 208 req->status = REQ_STATUS_ALLOC; 209 ··· 323 */ 324 void p9_client_cb(struct p9_client *c, struct p9_req_t *req) 325 { 326 - struct p9_req_t *other_req; 327 - unsigned long flags; 328 - 329 P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); 330 - 331 - if (req->status == REQ_STATUS_ERROR) 332 - wake_up(req->wq); 333 - 334 - if (req->flush_tag) { /* flush receive path */ 335 - P9_DPRINTK(P9_DEBUG_9P, "<<< RFLUSH %d\n", req->tc->tag); 336 - spin_lock_irqsave(&c->lock, flags); 337 - other_req = p9_tag_lookup(c, req->flush_tag); 338 - if (other_req->status != REQ_STATUS_FLSH) /* stale flush */ 339 - spin_unlock_irqrestore(&c->lock, flags); 340 - else { 341 - other_req->status = REQ_STATUS_FLSHD; 342 - spin_unlock_irqrestore(&c->lock, flags); 343 - wake_up(other_req->wq); 344 - } 345 - p9_free_req(c, req); 346 - } else { /* normal receive path */ 347 - P9_DPRINTK(P9_DEBUG_MUX, "normal: tag %d\n", req->tc->tag); 348 - spin_lock_irqsave(&c->lock, flags); 349 - if (req->status != REQ_STATUS_FLSHD) 350 - req->status = REQ_STATUS_RCVD; 351 - spin_unlock_irqrestore(&c->lock, flags); 352 - wake_up(req->wq); 353 - P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); 354 - } 355 } 356 EXPORT_SYMBOL(p9_client_cb); 357 ··· 459 if (IS_ERR(req)) 460 return PTR_ERR(req); 461 462 - req->flush_tag = oldtag; 463 464 - /* we don't free anything here because RPC isn't complete */ 465 return 0; 466 } 467 ··· 488 struct p9_req_t *req; 489 unsigned long flags; 490 int sigpending; 491 - int flushed = 0; 492 493 P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); 494 ··· 524 goto reterr; 525 } 526 527 - /* if it was a flush we just transmitted, return our tag */ 528 - if (type == P9_TFLUSH) 529 - return req; 530 - again: 531 P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); 532 err = wait_event_interruptible(*req->wq, 533 req->status >= REQ_STATUS_RCVD); 534 - P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n", 535 - req->wq, tag, err, flushed); 536 537 if (req->status == REQ_STATUS_ERROR) { 538 P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); 539 err = req->t_err; 540 - } else if (err == -ERESTARTSYS && flushed) { 541 - P9_DPRINTK(P9_DEBUG_MUX, "flushed - going again\n"); 542 - goto again; 543 - } else if (req->status == REQ_STATUS_FLSHD) { 544 - P9_DPRINTK(P9_DEBUG_MUX, "flushed - erestartsys\n"); 545 - err = -ERESTARTSYS; 546 } 547 548 - if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) { 549 P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); 550 - spin_lock_irqsave(&c->lock, flags); 551 - if (req->status == REQ_STATUS_SENT) 552 - req->status = REQ_STATUS_FLSH; 553 - spin_unlock_irqrestore(&c->lock, flags); 554 sigpending = 1; 555 - flushed = 1; 556 clear_thread_flag(TIF_SIGPENDING); 557 558 - if (c->trans_mod->cancel(c, req)) { 559 - err = p9_client_flush(c, req); 560 - if (err == 0) 561 - goto again; 562 - } 563 } 564 565 if (sigpending) { ··· 1208 ret->name, ret->uid, ret->gid, ret->muid, ret->extension, 1209 ret->n_uid, ret->n_gid, ret->n_muid); 1210 1211 free_and_error: 1212 p9_free_req(clnt, req); 1213 error: 1214 - return ret; 1215 } 1216 EXPORT_SYMBOL(p9_client_stat); 1217 1218 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) 1219 { ··· 1252 struct p9_req_t *req; 1253 struct p9_client *clnt; 1254 1255 P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); 1256 P9_DPRINTK(P9_DEBUG_9P, 1257 " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" ··· 1266 wst->atime, wst->mtime, (unsigned long long)wst->length, 1267 wst->name, wst->uid, wst->gid, wst->muid, wst->extension, 1268 wst->n_uid, wst->n_gid, wst->n_muid); 1269 - err = 0; 1270 - clnt = fid->clnt; 1271 1272 - req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, 0, wst); 1273 if (IS_ERR(req)) { 1274 err = PTR_ERR(req); 1275 goto error;
··· 203 p9pdu_reset(req->tc); 204 p9pdu_reset(req->rc); 205 206 req->tc->tag = tag-1; 207 req->status = REQ_STATUS_ALLOC; 208 ··· 324 */ 325 void p9_client_cb(struct p9_client *c, struct p9_req_t *req) 326 { 327 P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); 328 + wake_up(req->wq); 329 + P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); 330 } 331 EXPORT_SYMBOL(p9_client_cb); 332 ··· 486 if (IS_ERR(req)) 487 return PTR_ERR(req); 488 489 490 + /* if we haven't received a response for oldreq, 491 + remove it from the list. */ 492 + spin_lock(&c->lock); 493 + if (oldreq->status == REQ_STATUS_FLSH) 494 + list_del(&oldreq->req_list); 495 + spin_unlock(&c->lock); 496 + 497 + p9_free_req(c, req); 498 return 0; 499 } 500 ··· 509 struct p9_req_t *req; 510 unsigned long flags; 511 int sigpending; 512 513 P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); 514 ··· 546 goto reterr; 547 } 548 549 P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); 550 err = wait_event_interruptible(*req->wq, 551 req->status >= REQ_STATUS_RCVD); 552 + P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n", 553 + req->wq, tag, err); 554 555 if (req->status == REQ_STATUS_ERROR) { 556 P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); 557 err = req->t_err; 558 } 559 560 + if ((err == -ERESTARTSYS) && (c->status == Connected)) { 561 P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); 562 sigpending = 1; 563 clear_thread_flag(TIF_SIGPENDING); 564 565 + if (c->trans_mod->cancel(c, req)) 566 + p9_client_flush(c, req); 567 + 568 + /* if we received the response anyway, don't signal error */ 569 + if (req->status == REQ_STATUS_RCVD) 570 + err = 0; 571 } 572 573 if (sigpending) { ··· 1244 ret->name, ret->uid, ret->gid, ret->muid, ret->extension, 1245 ret->n_uid, ret->n_gid, ret->n_muid); 1246 1247 + p9_free_req(clnt, req); 1248 + return ret; 1249 + 1250 free_and_error: 1251 p9_free_req(clnt, req); 1252 error: 1253 + kfree(ret); 1254 + return ERR_PTR(err); 1255 } 1256 EXPORT_SYMBOL(p9_client_stat); 1257 + 1258 + static int p9_client_statsize(struct p9_wstat *wst, int optional) 1259 + { 1260 + int ret; 1261 + 1262 + /* size[2] type[2] dev[4] qid[13] */ 1263 + /* mode[4] atime[4] mtime[4] length[8]*/ 1264 + /* name[s] uid[s] gid[s] muid[s] */ 1265 + ret = 2+2+4+13+4+4+4+8+2+2+2+2; 1266 + 1267 + if (wst->name) 1268 + ret += strlen(wst->name); 1269 + if (wst->uid) 1270 + ret += strlen(wst->uid); 1271 + if (wst->gid) 1272 + ret += strlen(wst->gid); 1273 + if (wst->muid) 1274 + ret += strlen(wst->muid); 1275 + 1276 + if (optional) { 1277 + ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ 1278 + if (wst->extension) 1279 + ret += strlen(wst->extension); 1280 + } 1281 + 1282 + return ret; 1283 + } 1284 1285 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) 1286 { ··· 1257 struct p9_req_t *req; 1258 struct p9_client *clnt; 1259 1260 + err = 0; 1261 + clnt = fid->clnt; 1262 + wst->size = p9_client_statsize(wst, clnt->dotu); 1263 P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); 1264 P9_DPRINTK(P9_DEBUG_9P, 1265 " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" ··· 1268 wst->atime, wst->mtime, (unsigned long long)wst->length, 1269 wst->name, wst->uid, wst->gid, wst->muid, wst->extension, 1270 wst->n_uid, wst->n_gid, wst->n_muid); 1271 1272 + req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst); 1273 if (IS_ERR(req)) { 1274 err = PTR_ERR(req); 1275 goto error;
+9 -5
net/9p/trans_fd.c
··· 213 spin_unlock_irqrestore(&m->client->lock, flags); 214 215 list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { 216 - list_del(&req->req_list); 217 P9_DPRINTK(P9_DEBUG_ERROR, "call back req %p\n", req); 218 p9_client_cb(m->client, req); 219 } 220 } ··· 336 "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); 337 338 m->req = p9_tag_lookup(m->client, tag); 339 - if (!m->req) { 340 P9_DPRINTK(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", 341 tag); 342 err = -EIO; ··· 362 if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ 363 P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n"); 364 spin_lock(&m->client->lock); 365 list_del(&m->req->req_list); 366 spin_unlock(&m->client->lock); 367 p9_client_cb(m->client, m->req); 368 - 369 m->rbuf = NULL; 370 m->rpos = 0; 371 m->rsize = 0; ··· 456 req = list_entry(m->unsent_req_list.next, struct p9_req_t, 457 req_list); 458 req->status = REQ_STATUS_SENT; 459 list_move_tail(&req->req_list, &m->req_list); 460 461 m->wbuf = req->tc->sdata; ··· 686 P9_DPRINTK(P9_DEBUG_TRANS, "client %p req %p\n", client, req); 687 688 spin_lock(&client->lock); 689 - list_del(&req->req_list); 690 691 if (req->status == REQ_STATUS_UNSENT) { 692 req->status = REQ_STATUS_FLSHD; 693 ret = 0; 694 - } 695 696 spin_unlock(&client->lock); 697
··· 213 spin_unlock_irqrestore(&m->client->lock, flags); 214 215 list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { 216 P9_DPRINTK(P9_DEBUG_ERROR, "call back req %p\n", req); 217 + list_del(&req->req_list); 218 p9_client_cb(m->client, req); 219 } 220 } ··· 336 "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); 337 338 m->req = p9_tag_lookup(m->client, tag); 339 + if (!m->req || (m->req->status != REQ_STATUS_SENT && 340 + m->req->status != REQ_STATUS_FLSH)) { 341 P9_DPRINTK(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", 342 tag); 343 err = -EIO; ··· 361 if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ 362 P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n"); 363 spin_lock(&m->client->lock); 364 + if (m->req->status != REQ_STATUS_ERROR) 365 + m->req->status = REQ_STATUS_RCVD; 366 list_del(&m->req->req_list); 367 spin_unlock(&m->client->lock); 368 p9_client_cb(m->client, m->req); 369 m->rbuf = NULL; 370 m->rpos = 0; 371 m->rsize = 0; ··· 454 req = list_entry(m->unsent_req_list.next, struct p9_req_t, 455 req_list); 456 req->status = REQ_STATUS_SENT; 457 + P9_DPRINTK(P9_DEBUG_TRANS, "move req %p\n", req); 458 list_move_tail(&req->req_list, &m->req_list); 459 460 m->wbuf = req->tc->sdata; ··· 683 P9_DPRINTK(P9_DEBUG_TRANS, "client %p req %p\n", client, req); 684 685 spin_lock(&client->lock); 686 687 if (req->status == REQ_STATUS_UNSENT) { 688 + list_del(&req->req_list); 689 req->status = REQ_STATUS_FLSHD; 690 ret = 0; 691 + } else if (req->status == REQ_STATUS_SENT) 692 + req->status = REQ_STATUS_FLSH; 693 694 spin_unlock(&client->lock); 695
+1
net/9p/trans_rdma.c
··· 295 goto err_out; 296 297 req->rc = c->rc; 298 p9_client_cb(client, req); 299 300 return;
··· 295 goto err_out; 296 297 req->rc = c->rc; 298 + req->status = REQ_STATUS_RCVD; 299 p9_client_cb(client, req); 300 301 return;
+1
net/9p/trans_virtio.c
··· 134 P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); 135 P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); 136 req = p9_tag_lookup(chan->client, rc->tag); 137 p9_client_cb(chan->client, req); 138 } 139 }
··· 134 P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); 135 P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); 136 req = p9_tag_lookup(chan->client, rc->tag); 137 + req->status = REQ_STATUS_RCVD; 138 p9_client_cb(chan->client, req); 139 } 140 }