X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fptlrpc%2Fclient.c;h=23a3b9f35e7ce4cde3d76e924b6563fba4e3d9b0;hb=05b1e40d05c81c59504f5b7b5813d296be02f289;hp=45573956f69b198a86c35ae16ea7435e2648ff88;hpb=3293f5b9676e5336d92950f7210823c54c36c784;p=fs%2Flustre-release.git diff --git a/lustre/ptlrpc/client.c b/lustre/ptlrpc/client.c index 4557395..23a3b9f 100644 --- a/lustre/ptlrpc/client.c +++ b/lustre/ptlrpc/client.c @@ -22,137 +22,96 @@ #define EXPORT_SYMTAB -#include -#include -#include - #define DEBUG_SUBSYSTEM S_RPC -#include -#include #include -int ptlrpc_enqueue(struct ptlrpc_client *peer, struct ptlrpc_request *req) + +void ptlrpc_init_client(struct connmgr_obd *mgr, int req_portal, + int rep_portal, struct ptlrpc_client *cl) { - struct ptlrpc_request *srv_req; - - if (!peer->cli_obd) { - EXIT; - return -1; - } - - OBD_ALLOC(srv_req, sizeof(*srv_req)); - if (!srv_req) { - EXIT; - return -ENOMEM; - } - - CDEBUG(0, "peer obd minor %d, incoming req %p, srv_req %p\n", - peer->cli_obd->obd_minor, req, srv_req); - - memset(srv_req, 0, sizeof(*req)); - - /* move the request buffer */ - srv_req->rq_reqbuf = req->rq_reqbuf; - srv_req->rq_reqlen = req->rq_reqlen; - srv_req->rq_obd = peer->cli_obd; - - /* remember where it came from */ - srv_req->rq_reply_handle = req; - - list_add(&srv_req->rq_list, &peer->cli_obd->obd_req_list); - wake_up(&peer->cli_obd->obd_req_waitq); - return 0; + memset(cl, 0, sizeof(*cl)); + cl->cli_ha_mgr = mgr; + if (mgr) + connmgr_cli_manage(mgr, cl); + cl->cli_obd = NULL; + cl->cli_request_portal = req_portal; + cl->cli_reply_portal = rep_portal; + INIT_LIST_HEAD(&cl->cli_sending_head); + INIT_LIST_HEAD(&cl->cli_sent_head); + sema_init(&cl->cli_rpc_sem, 32); } -int ptlrpc_connect_client(int dev, char *uuid, int req_portal, int rep_portal, - req_pack_t req_pack, rep_unpack_t rep_unpack, - struct ptlrpc_client *cl) +struct ptlrpc_connection *ptlrpc_uuid_to_connection(char *uuid) { - int err; + struct ptlrpc_connection *c; + struct lustre_peer peer; + int err; - memset(cl, 0, sizeof(*cl)); - spin_lock_init(&cl->cli_lock); - cl->cli_xid = 1; - cl->cli_obd = NULL; - cl->cli_request_portal = req_portal; - cl->cli_reply_portal = rep_portal; - cl->cli_rep_unpack = rep_unpack; - cl->cli_req_pack = req_pack; - - /* non networked client */ - if (dev >= 0 && dev < MAX_OBD_DEVICES) { - struct obd_device *obd = &obd_dev[dev]; - - if ((!obd->obd_flags & OBD_ATTACHED) || - (!obd->obd_flags & OBD_SET_UP)) { - CERROR("target device %d not att or setup\n", dev); - return -EINVAL; - } - if (strcmp(obd->obd_type->typ_name, "ost") && - strcmp(obd->obd_type->typ_name, "mds")) { - return -EINVAL; - } - - cl->cli_obd = &obd_dev[dev]; - return 0; - } - - /* networked */ - err = kportal_uuid_to_peer(uuid, &cl->cli_server); - if (err != 0) { - CERROR("cannot find peer %s!", uuid); - } - - return err; + err = kportal_uuid_to_peer(uuid, &peer); + if (err != 0) { + CERROR("cannot find peer %s!\n", uuid); + return NULL; + } + + c = ptlrpc_get_connection(&peer); + if (c) + c->c_epoch++; + + return c; } -struct ptlrpc_bulk_desc *ptlrpc_prep_bulk(struct lustre_peer *peer) +struct ptlrpc_bulk_desc *ptlrpc_prep_bulk(struct ptlrpc_connection *conn) { struct ptlrpc_bulk_desc *bulk; OBD_ALLOC(bulk, sizeof(*bulk)); if (bulk != NULL) { - memset(bulk, 0, sizeof(*bulk)); - memcpy(&bulk->b_peer, peer, sizeof(*peer)); + bulk->b_connection = ptlrpc_connection_addref(conn); init_waitqueue_head(&bulk->b_waitq); } return bulk; } -struct ptlrpc_request *ptlrpc_prep_req(struct ptlrpc_client *cl, - int opcode, int namelen, char *name, - int tgtlen, char *tgt) +struct ptlrpc_request *ptlrpc_prep_req(struct ptlrpc_client *cl, + struct ptlrpc_connection *conn, + int opcode, int count, int *lengths, + char **bufs) { - struct ptlrpc_request *request; - int rc; - ENTRY; - - OBD_ALLOC(request, sizeof(*request)); - if (!request) { - CERROR("request allocation out of memory\n"); - return NULL; - } - - memset(request, 0, sizeof(*request)); - - spin_lock(&cl->cli_lock); - request->rq_xid = cl->cli_xid++; - spin_unlock(&cl->cli_lock); - - rc = cl->cli_req_pack(name, namelen, tgt, tgtlen, - &request->rq_reqhdr, &request->rq_req, - &request->rq_reqlen, &request->rq_reqbuf); - if (rc) { - CERROR("cannot pack request %d\n", rc); - return NULL; - } - request->rq_reqhdr->opc = opcode; - request->rq_reqhdr->xid = request->rq_xid; - - EXIT; - return request; + struct ptlrpc_request *request; + int rc; + ENTRY; + + OBD_ALLOC(request, sizeof(*request)); + if (!request) { + CERROR("request allocation out of memory\n"); + RETURN(NULL); + } + + rc = lustre_pack_msg(count, lengths, bufs, + &request->rq_reqlen, &request->rq_reqmsg); + if (rc) { + CERROR("cannot pack request %d\n", rc); + RETURN(NULL); + } + + request->rq_time = CURRENT_TIME; + request->rq_type = PTL_RPC_REQUEST; + request->rq_connection = ptlrpc_connection_addref(conn); + + request->rq_reqmsg->conn = (__u64)(unsigned long)conn->c_remote_conn; + request->rq_reqmsg->token = conn->c_remote_token; + request->rq_reqmsg->opc = HTON__u32(opcode); + request->rq_reqmsg->type = HTON__u32(request->rq_type); + + spin_lock(&conn->c_lock); + request->rq_reqmsg->xid = HTON__u32(++conn->c_xid_out); + spin_unlock(&conn->c_lock); + + request->rq_client = cl; + + RETURN(request); } void ptlrpc_free_req(struct ptlrpc_request *request) @@ -160,27 +119,40 @@ void ptlrpc_free_req(struct ptlrpc_request *request) if (request == NULL) return; - if (request->rq_repbuf != NULL) - OBD_FREE(request->rq_repbuf, request->rq_replen); - OBD_FREE(request, sizeof(*request)); + if (request->rq_repmsg != NULL) + OBD_FREE(request->rq_repmsg, request->rq_replen); + + ptlrpc_put_connection(request->rq_connection); + + OBD_FREE(request, sizeof(*request)); } static int ptlrpc_check_reply(struct ptlrpc_request *req) { - if (req->rq_repbuf != NULL) { + int rc = 0; + + schedule_timeout(3 * HZ); /* 3 second timeout */ + if (req->rq_repmsg != NULL) { req->rq_flags = PTL_RPC_REPLY; - EXIT; - return 1; + GOTO(out, rc = 1); + } + + if (CURRENT_TIME - req->rq_time >= 3) { + CERROR("-- REQ TIMEOUT --\n"); + if (req->rq_client && req->rq_client->cli_ha_mgr) + connmgr_cli_fail(req->rq_client); + return 0; } if (sigismember(&(current->pending.signal), SIGKILL) || - sigismember(&(current->pending.signal), SIGINT)) { + sigismember(&(current->pending.signal), SIGTERM) || + sigismember(&(current->pending.signal), SIGINT)) { req->rq_flags = PTL_RPC_INTR; - EXIT; - return 1; + GOTO(out, rc = 1); } - return 0; + out: + return rc; } int ptlrpc_check_status(struct ptlrpc_request *req, int err) @@ -189,100 +161,93 @@ int ptlrpc_check_status(struct ptlrpc_request *req, int err) if (err != 0) { CERROR("err is %d\n", err); - EXIT; - return err; + RETURN(err); } if (req == NULL) { CERROR("req == NULL\n"); - EXIT; - return -ENOMEM; + RETURN(-ENOMEM); } - if (req->rq_rephdr == NULL) { - CERROR("req->rq_rephdr == NULL\n"); - EXIT; - return -ENOMEM; + if (req->rq_repmsg == NULL) { + CERROR("req->rq_repmsg == NULL\n"); + RETURN(-ENOMEM); } - if (req->rq_rephdr->status != 0) { - CERROR("req->rq_rephdr->status is %d\n", - req->rq_rephdr->status); - EXIT; + if (req->rq_repmsg->status != 0) { + CERROR("req->rq_repmsg->status is %d\n", + req->rq_repmsg->status); /* XXX: translate this error from net to host */ - return req->rq_rephdr->status; + RETURN(req->rq_repmsg->status); } - EXIT; - return 0; + RETURN(0); +} + +static void ptlrpc_cleanup_request_buf(struct ptlrpc_request *request) +{ + OBD_FREE(request->rq_reqmsg, request->rq_reqlen); + request->rq_reqmsg = NULL; + request->rq_reqlen = 0; } /* Abort this request and cleanup any resources associated with it. */ -int ptlrpc_abort(struct ptlrpc_request *request) +static int ptlrpc_abort(struct ptlrpc_request *request) { - /* First remove the MD for the reply; in theory, this means + /* First remove the ME for the reply; in theory, this means * that we can tear down the buffer safely. */ PtlMEUnlink(request->rq_reply_me_h); - PtlMDUnlink(request->rq_reply_md_h); - OBD_FREE(request->rq_repbuf, request->rq_replen); - request->rq_repbuf = NULL; + OBD_FREE(request->rq_reply_md.start, request->rq_replen); + request->rq_repmsg = NULL; request->rq_replen = 0; - return 0; } -int ptlrpc_queue_wait(struct ptlrpc_client *cl, struct ptlrpc_request *req) - +int ptlrpc_queue_wait(struct ptlrpc_request *req) { - int rc; + int rc = 0; ENTRY; - init_waitqueue_head(&req->rq_wait_for_rep); - - if (cl->cli_obd) { - /* Local delivery */ - ENTRY; - rc = ptlrpc_enqueue(cl, req); - } else { - /* Remote delivery via portals. */ - req->rq_req_portal = cl->cli_request_portal; - req->rq_reply_portal = cl->cli_reply_portal; - rc = ptl_send_rpc(req, &cl->cli_server); - } - if (rc) { - CERROR("error %d, opcode %d\n", rc, req->rq_reqhdr->opc); - return -rc; - } + init_waitqueue_head(&req->rq_wait_for_rep); + + rc = ptl_send_rpc(req); + if (rc) { + CERROR("error %d, opcode %d\n", rc, req->rq_reqmsg->opc); + ptlrpc_cleanup_request_buf(req); + up(&req->rq_client->cli_rpc_sem); + RETURN(-rc); + } CDEBUG(D_OTHER, "-- sleeping\n"); wait_event_interruptible(req->rq_wait_for_rep, ptlrpc_check_reply(req)); CDEBUG(D_OTHER, "-- done\n"); - - if (req->rq_flags == PTL_RPC_INTR) { + ptlrpc_cleanup_request_buf(req); + up(&req->rq_client->cli_rpc_sem); + if (req->rq_flags == PTL_RPC_INTR) { /* Clean up the dangling reply buffers */ ptlrpc_abort(req); - EXIT; - return -EINTR; + GOTO(out, rc = -EINTR); } - if (req->rq_flags != PTL_RPC_REPLY) { + if (req->rq_flags != PTL_RPC_REPLY) { CERROR("Unknown reason for wakeup\n"); - EXIT; - return -EINTR; + /* XXX Phil - I end up here when I kill obdctl */ + ptlrpc_abort(req); + GOTO(out, rc = -EINTR); } - rc = cl->cli_rep_unpack(req->rq_repbuf, req->rq_replen, - &req->rq_rephdr, &req->rq_rep); - if (rc) { - CERROR("unpack_rep failed: %d\n", rc); - return rc; - } - CDEBUG(D_NET, "got rep %d\n", req->rq_rephdr->xid); + rc = lustre_unpack_msg(req->rq_repmsg, req->rq_replen); + if (rc) { + CERROR("unpack_rep failed: %d\n", rc); + GOTO(out, rc); + } + CDEBUG(D_NET, "got rep %d\n", req->rq_repmsg->xid); - if ( req->rq_rephdr->status == 0 ) - CDEBUG(D_NET, "--> buf %p len %d status %d\n", req->rq_repbuf, - req->rq_replen, req->rq_rephdr->status); + if (req->rq_repmsg->status == 0) + CDEBUG(D_NET, "--> buf %p len %d status %d\n", req->rq_repmsg, + req->rq_replen, req->rq_repmsg->status); - EXIT; - return 0; + EXIT; + out: + return rc; }