diff options
Diffstat (limited to 'net/9p/client.c')
-rw-r--r-- | net/9p/client.c | 114 |
1 files changed, 55 insertions, 59 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 1eb580c38fbb..dd43a8289b0d 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -203,7 +203,6 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) | |||
203 | p9pdu_reset(req->tc); | 203 | p9pdu_reset(req->tc); |
204 | p9pdu_reset(req->rc); | 204 | p9pdu_reset(req->rc); |
205 | 205 | ||
206 | req->flush_tag = 0; | ||
207 | req->tc->tag = tag-1; | 206 | req->tc->tag = tag-1; |
208 | req->status = REQ_STATUS_ALLOC; | 207 | req->status = REQ_STATUS_ALLOC; |
209 | 208 | ||
@@ -324,35 +323,9 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r) | |||
324 | */ | 323 | */ |
325 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req) | 324 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req) |
326 | { | 325 | { |
327 | struct p9_req_t *other_req; | ||
328 | unsigned long flags; | ||
329 | |||
330 | P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); | 326 | P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); |
331 | 327 | wake_up(req->wq); | |
332 | if (req->status == REQ_STATUS_ERROR) | 328 | P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); |
333 | wake_up(req->wq); | ||
334 | |||
335 | if (req->flush_tag) { /* flush receive path */ | ||
336 | P9_DPRINTK(P9_DEBUG_9P, "<<< RFLUSH %d\n", req->tc->tag); | ||
337 | spin_lock_irqsave(&c->lock, flags); | ||
338 | other_req = p9_tag_lookup(c, req->flush_tag); | ||
339 | if (other_req->status != REQ_STATUS_FLSH) /* stale flush */ | ||
340 | spin_unlock_irqrestore(&c->lock, flags); | ||
341 | else { | ||
342 | other_req->status = REQ_STATUS_FLSHD; | ||
343 | spin_unlock_irqrestore(&c->lock, flags); | ||
344 | wake_up(other_req->wq); | ||
345 | } | ||
346 | p9_free_req(c, req); | ||
347 | } else { /* normal receive path */ | ||
348 | P9_DPRINTK(P9_DEBUG_MUX, "normal: tag %d\n", req->tc->tag); | ||
349 | spin_lock_irqsave(&c->lock, flags); | ||
350 | if (req->status != REQ_STATUS_FLSHD) | ||
351 | req->status = REQ_STATUS_RCVD; | ||
352 | spin_unlock_irqrestore(&c->lock, flags); | ||
353 | wake_up(req->wq); | ||
354 | P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); | ||
355 | } | ||
356 | } | 329 | } |
357 | EXPORT_SYMBOL(p9_client_cb); | 330 | EXPORT_SYMBOL(p9_client_cb); |
358 | 331 | ||
@@ -486,9 +459,15 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) | |||
486 | if (IS_ERR(req)) | 459 | if (IS_ERR(req)) |
487 | return PTR_ERR(req); | 460 | return PTR_ERR(req); |
488 | 461 | ||
489 | req->flush_tag = oldtag; | ||
490 | 462 | ||
491 | /* we don't free anything here because RPC isn't complete */ | 463 | /* if we haven't received a response for oldreq, |
464 | remove it from the list. */ | ||
465 | spin_lock(&c->lock); | ||
466 | if (oldreq->status == REQ_STATUS_FLSH) | ||
467 | list_del(&oldreq->req_list); | ||
468 | spin_unlock(&c->lock); | ||
469 | |||
470 | p9_free_req(c, req); | ||
492 | return 0; | 471 | return 0; |
493 | } | 472 | } |
494 | 473 | ||
@@ -509,7 +488,6 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
509 | struct p9_req_t *req; | 488 | struct p9_req_t *req; |
510 | unsigned long flags; | 489 | unsigned long flags; |
511 | int sigpending; | 490 | int sigpending; |
512 | int flushed = 0; | ||
513 | 491 | ||
514 | P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); | 492 | P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); |
515 | 493 | ||
@@ -546,42 +524,28 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
546 | goto reterr; | 524 | goto reterr; |
547 | } | 525 | } |
548 | 526 | ||
549 | /* if it was a flush we just transmitted, return our tag */ | ||
550 | if (type == P9_TFLUSH) | ||
551 | return req; | ||
552 | again: | ||
553 | P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); | 527 | P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); |
554 | err = wait_event_interruptible(*req->wq, | 528 | err = wait_event_interruptible(*req->wq, |
555 | req->status >= REQ_STATUS_RCVD); | 529 | req->status >= REQ_STATUS_RCVD); |
556 | P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n", | 530 | P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n", |
557 | req->wq, tag, err, flushed); | 531 | req->wq, tag, err); |
558 | 532 | ||
559 | if (req->status == REQ_STATUS_ERROR) { | 533 | if (req->status == REQ_STATUS_ERROR) { |
560 | P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); | 534 | P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); |
561 | err = req->t_err; | 535 | err = req->t_err; |
562 | } else if (err == -ERESTARTSYS && flushed) { | ||
563 | P9_DPRINTK(P9_DEBUG_MUX, "flushed - going again\n"); | ||
564 | goto again; | ||
565 | } else if (req->status == REQ_STATUS_FLSHD) { | ||
566 | P9_DPRINTK(P9_DEBUG_MUX, "flushed - erestartsys\n"); | ||
567 | err = -ERESTARTSYS; | ||
568 | } | 536 | } |
569 | 537 | ||
570 | if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) { | 538 | if ((err == -ERESTARTSYS) && (c->status == Connected)) { |
571 | P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); | 539 | P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); |
572 | spin_lock_irqsave(&c->lock, flags); | ||
573 | if (req->status == REQ_STATUS_SENT) | ||
574 | req->status = REQ_STATUS_FLSH; | ||
575 | spin_unlock_irqrestore(&c->lock, flags); | ||
576 | sigpending = 1; | 540 | sigpending = 1; |
577 | flushed = 1; | ||
578 | clear_thread_flag(TIF_SIGPENDING); | 541 | clear_thread_flag(TIF_SIGPENDING); |
579 | 542 | ||
580 | if (c->trans_mod->cancel(c, req)) { | 543 | if (c->trans_mod->cancel(c, req)) |
581 | err = p9_client_flush(c, req); | 544 | p9_client_flush(c, req); |
582 | if (err == 0) | 545 | |
583 | goto again; | 546 | /* if we received the response anyway, don't signal error */ |
584 | } | 547 | if (req->status == REQ_STATUS_RCVD) |
548 | err = 0; | ||
585 | } | 549 | } |
586 | 550 | ||
587 | if (sigpending) { | 551 | if (sigpending) { |
@@ -1244,19 +1208,53 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) | |||
1244 | ret->name, ret->uid, ret->gid, ret->muid, ret->extension, | 1208 | ret->name, ret->uid, ret->gid, ret->muid, ret->extension, |
1245 | ret->n_uid, ret->n_gid, ret->n_muid); | 1209 | ret->n_uid, ret->n_gid, ret->n_muid); |
1246 | 1210 | ||
1211 | p9_free_req(clnt, req); | ||
1212 | return ret; | ||
1213 | |||
1247 | free_and_error: | 1214 | free_and_error: |
1248 | p9_free_req(clnt, req); | 1215 | p9_free_req(clnt, req); |
1249 | error: | 1216 | error: |
1250 | return ret; | 1217 | kfree(ret); |
1218 | return ERR_PTR(err); | ||
1251 | } | 1219 | } |
1252 | EXPORT_SYMBOL(p9_client_stat); | 1220 | EXPORT_SYMBOL(p9_client_stat); |
1253 | 1221 | ||
1222 | static int p9_client_statsize(struct p9_wstat *wst, int optional) | ||
1223 | { | ||
1224 | int ret; | ||
1225 | |||
1226 | /* size[2] type[2] dev[4] qid[13] */ | ||
1227 | /* mode[4] atime[4] mtime[4] length[8]*/ | ||
1228 | /* name[s] uid[s] gid[s] muid[s] */ | ||
1229 | ret = 2+2+4+13+4+4+4+8+2+2+2+2; | ||
1230 | |||
1231 | if (wst->name) | ||
1232 | ret += strlen(wst->name); | ||
1233 | if (wst->uid) | ||
1234 | ret += strlen(wst->uid); | ||
1235 | if (wst->gid) | ||
1236 | ret += strlen(wst->gid); | ||
1237 | if (wst->muid) | ||
1238 | ret += strlen(wst->muid); | ||
1239 | |||
1240 | if (optional) { | ||
1241 | ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ | ||
1242 | if (wst->extension) | ||
1243 | ret += strlen(wst->extension); | ||
1244 | } | ||
1245 | |||
1246 | return ret; | ||
1247 | } | ||
1248 | |||
1254 | int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) | 1249 | int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) |
1255 | { | 1250 | { |
1256 | int err; | 1251 | int err; |
1257 | struct p9_req_t *req; | 1252 | struct p9_req_t *req; |
1258 | struct p9_client *clnt; | 1253 | struct p9_client *clnt; |
1259 | 1254 | ||
1255 | err = 0; | ||
1256 | clnt = fid->clnt; | ||
1257 | wst->size = p9_client_statsize(wst, clnt->dotu); | ||
1260 | P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); | 1258 | P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); |
1261 | P9_DPRINTK(P9_DEBUG_9P, | 1259 | P9_DPRINTK(P9_DEBUG_9P, |
1262 | " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" | 1260 | " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" |
@@ -1268,10 +1266,8 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) | |||
1268 | wst->atime, wst->mtime, (unsigned long long)wst->length, | 1266 | wst->atime, wst->mtime, (unsigned long long)wst->length, |
1269 | wst->name, wst->uid, wst->gid, wst->muid, wst->extension, | 1267 | wst->name, wst->uid, wst->gid, wst->muid, wst->extension, |
1270 | wst->n_uid, wst->n_gid, wst->n_muid); | 1268 | wst->n_uid, wst->n_gid, wst->n_muid); |
1271 | err = 0; | ||
1272 | clnt = fid->clnt; | ||
1273 | 1269 | ||
1274 | req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, 0, wst); | 1270 | req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst); |
1275 | if (IS_ERR(req)) { | 1271 | if (IS_ERR(req)) { |
1276 | err = PTR_ERR(req); | 1272 | err = PTR_ERR(req); |
1277 | goto error; | 1273 | goto error; |