diff options
| author | Shehjar Tikoo <shehjart@gluster.com> | 2010-11-08 06:25:16 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2010-11-09 02:11:55 -0800 | 
| commit | 0f9ec3dec9d51ac5a8f692896d0724b3e87e9ae2 (patch) | |
| tree | 9efaf5e5148a03158701699adec0a02bb84e6978 | |
| parent | 13c4f8d0f9114a9f8324d0dec8bd926c04a5dfc5 (diff) | |
nfsrpc: Decouple TCP connections from programs
..so that multiple programs can be served from the same connection
or multiple ports can be bound to the same port number.
Signed-off-by: Shehjar Tikoo <shehjart@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 1743 (XenServer is not compatible with GlusterNFS)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1743
| -rw-r--r-- | xlators/nfs/lib/src/rpc-socket.c | 11 | ||||
| -rw-r--r-- | xlators/nfs/lib/src/rpcsvc.c | 150 | ||||
| -rw-r--r-- | xlators/nfs/lib/src/rpcsvc.h | 12 | 
3 files changed, 110 insertions, 63 deletions
diff --git a/xlators/nfs/lib/src/rpc-socket.c b/xlators/nfs/lib/src/rpc-socket.c index 9d6aca33b38..6c399d90416 100644 --- a/xlators/nfs/lib/src/rpc-socket.c +++ b/xlators/nfs/lib/src/rpc-socket.c @@ -123,12 +123,11 @@ nfs_rpcsvc_socket_listen (int addrfam, char *listenhost, uint16_t listenport)          ret = bind (sock, (struct sockaddr *)&sockaddr, sockaddr_len);          if (ret == -1) { -                gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "binding socket failed:" -                        " %s", strerror (errno)); -                if (errno == EADDRINUSE) -                        gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "Port is already" -                                " in use"); -                goto close_err; +                if (errno != EADDRINUSE) { +                        gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "binding socket " +                                "failed: %s", strerror (errno)); +                        goto close_err; +                }          }          ret = listen (sock, 10); diff --git a/xlators/nfs/lib/src/rpcsvc.c b/xlators/nfs/lib/src/rpcsvc.c index 112bf632613..081b4d6fe66 100644 --- a/xlators/nfs/lib/src/rpcsvc.c +++ b/xlators/nfs/lib/src/rpcsvc.c @@ -173,6 +173,7 @@ nfs_rpcsvc_init (glusterfs_ctx_t *ctx, dict_t *options)          pthread_mutex_init (&svc->rpclock, NULL);          INIT_LIST_HEAD (&svc->stages);          INIT_LIST_HEAD (&svc->authschemes); +        INIT_LIST_HEAD (&svc->allprograms);          ret = nfs_rpcsvc_init_options (svc, options);          if (ret == -1) { @@ -654,7 +655,7 @@ out:  /* Initialize the core of a connection */  rpcsvc_conn_t * -nfs_rpcsvc_conn_init (rpcsvc_t *svc, rpcsvc_program_t *prog, int sockfd) +nfs_rpcsvc_conn_init (rpcsvc_t *svc, int sockfd)  {          rpcsvc_conn_t  *conn = NULL;          int             ret = -1; @@ -667,7 +668,6 @@ nfs_rpcsvc_conn_init (rpcsvc_t *svc, rpcsvc_program_t *prog, int sockfd)          }          conn->sockfd = sockfd; -        conn->program = (void *)prog;          INIT_LIST_HEAD (&conn->txbufs);          poolcount = RPCSVC_POOLCOUNT_MULT * svc->memfactor;          gf_log (GF_RPCSVC, GF_LOG_TRACE, "tx pool: %d", poolcount); @@ -855,7 +855,7 @@ nfs_rpcsvc_conn_listen_init (rpcsvc_t *svc, rpcsvc_program_t *newprog)          if (sock == -1)                  goto err; -        conn = nfs_rpcsvc_conn_init (svc, newprog, sock); +        conn = nfs_rpcsvc_conn_init (svc, sock);          if (!conn)                  goto sock_close_err; @@ -997,8 +997,7 @@ err:  /* Inits a rpcsvc_conn_t after accepting the connection.   */  rpcsvc_conn_t * -nfs_rpcsvc_conn_accept_init (rpcsvc_t *svc, int listenfd, -                             rpcsvc_program_t *destprog) +nfs_rpcsvc_conn_accept_init (rpcsvc_t *svc, int listenfd)  {          rpcsvc_conn_t   *newconn = NULL;          int             sock = -1; @@ -1008,7 +1007,7 @@ nfs_rpcsvc_conn_accept_init (rpcsvc_t *svc, int listenfd,          if (sock == -1)                  goto err; -        newconn = nfs_rpcsvc_conn_init (svc, destprog, sock); +        newconn = nfs_rpcsvc_conn_init (svc, sock);          if (!newconn) {                  gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to init conn object");                  ret = -1; @@ -1253,62 +1252,105 @@ nfs_rpcsvc_record_update_frag (rpcsvc_record_state_t *rs, ssize_t dataread)  } +  /* This needs to change to returning errors, since   * we need to return RPC specific error messages when some   * of the pointers below are NULL.   */ -rpcsvc_actor_t * -nfs_rpcsvc_program_actor (rpcsvc_conn_t *conn, rpcsvc_request_t *req) +int +__nfs_rpcsvc_program_actor (rpcsvc_request_t *req, rpcsvc_program_t **prg)  {          rpcsvc_program_t        *program = NULL; -        int                     err = SYSTEM_ERR; +        int                     ret = PROG_UNAVAIL;          rpcsvc_actor_t          *actor = NULL; +        struct list_head        *prglist = NULL; -        if ((!conn) || (!req)) -                goto err; +        if (!req) +                return ret; -        program = (rpcsvc_program_t *)conn->program; -        if (!program) -                goto err; +        prglist = &((nfs_rpcsvc_request_service (req))->allprograms); +        if (list_empty (prglist)) +                return ret; -        if (req->prognum != program->prognum) { -                gf_log (GF_RPCSVC, GF_LOG_DEBUG, "RPC program not available"); -                err = PROG_UNAVAIL; -                goto err; -        } +        list_for_each_entry (program, prglist, proglist) { +                ret = PROG_UNAVAIL; +                if (req->prognum != program->prognum) +                        continue; -        if (!program->actors) { -                gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC System error"); -                err = SYSTEM_ERR; -                goto err; -        } +                if (!program->actors) { +                        ret = SYSTEM_ERR; +                        goto err; +                } -        if (req->progver != program->progver) { -                gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC program version not" -                        " available"); -                err = PROG_MISMATCH; -                goto err; +                ret = PROG_MISMATCH; +                if (req->progver != program->progver) +                        continue; + +                ret = PROC_UNAVAIL; +                if ((req->procnum < 0) || (req->procnum >= program->numactors)) +                        goto err; + +                actor = &program->actors[req->procnum]; +                if (!actor->actor) { +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC Program procedure" +                                " not defined"); +                        actor = NULL; +                        goto err; +                } else { +                        ret = SUCCESS; +                        break; +                }          } -        if ((req->procnum < 0) || (req->procnum >= program->numactors)) { -                gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC Program procedure not" -                        " available"); -                err = PROC_UNAVAIL; -                goto err; +        *prg = program; +err: +        switch (ret) { + +        case PROG_UNAVAIL: +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC program not available"); +                break; + +        case PROG_MISMATCH: +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC program version " +                        "not available"); +                break; + +        case PROC_UNAVAIL: +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC Program procedure" +                        " not available"); +                break; + +        case SUCCESS: +                gf_log (GF_RPCSVC, GF_LOG_TRACE, "RPC Program found"); +                break; + +        default: +                gf_log (GF_RPCSVC, GF_LOG_DEBUG, "System error"); +                break;          } -        actor = &program->actors[req->procnum]; -        if (!actor->actor) { -                gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC Program procedure not" -                        " available"); -                err = PROC_UNAVAIL; -                actor = NULL; +        req->rpc_err = ret; + +        return ret; +} + +/* This needs to change to returning errors, since + * we need to return RPC specific error messages when some + * of the pointers below are NULL. + */ +rpcsvc_actor_t * +nfs_rpcsvc_program_actor (rpcsvc_request_t *req) +{ +        int                     err = SYSTEM_ERR; +        rpcsvc_actor_t          *actor = NULL; + +        if (!req)                  goto err; -        } +        actor = &req->program->actors[req->procnum];          err = SUCCESS;          gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Actor found: %s - %s", -                program->progname, actor->procname); +                req->program->progname, actor->procname);  err:          if (req)                  req->rpc_err = err; @@ -1831,6 +1873,7 @@ nfs_rpcsvc_request_create (rpcsvc_conn_t *conn)          struct iovec            progmsg;        /* RPC Program payload */          rpcsvc_request_t        *req = NULL;          int                     ret = -1; +        rpcsvc_program_t        *program = NULL;          if (!conn)                  return NULL; @@ -1873,6 +1916,11 @@ nfs_rpcsvc_request_create (rpcsvc_conn_t *conn)                  goto err;          } +        ret = __nfs_rpcsvc_program_actor (req, &program); +        if (ret != SUCCESS) +                goto err; + +        req->program = program;          ret = nfs_rpcsvc_authenticate (req);          if (ret == RPCSVC_AUTH_REJECT) {                  /* No need to set auth_err, that is the responsibility of @@ -1918,7 +1966,7 @@ nfs_rpcsvc_handle_rpc_call (rpcsvc_conn_t *conn)          if (!nfs_rpcsvc_request_accepted (req))                  goto err_reply; -        actor = nfs_rpcsvc_program_actor (conn, req); +        actor = nfs_rpcsvc_program_actor (req);          if (!actor)                  goto err_reply; @@ -2015,7 +2063,7 @@ nfs_rpcsvc_handle_vectored_prep_rpc_call (rpcsvc_conn_t *conn)          if (!nfs_rpcsvc_request_accepted (req))                  goto err_reply; -        actor = nfs_rpcsvc_program_actor (conn, req); +        actor = nfs_rpcsvc_program_actor (req);          if (!actor)                  goto err_reply; @@ -2157,7 +2205,7 @@ nfs_rpcsvc_handle_vectored_rpc_call (rpcsvc_conn_t *conn)          if (!req)                  goto err; -        actor = nfs_rpcsvc_program_actor (conn, req); +        actor = nfs_rpcsvc_program_actor (req);          if (!actor)                  goto err_reply; @@ -2224,7 +2272,7 @@ nfs_rpcsvc_record_vectored_call_actor (rpcsvc_conn_t *conn)          if (!req)                  goto err; -        actor = nfs_rpcsvc_program_actor (conn, req); +        actor = nfs_rpcsvc_program_actor (req);          if (!actor)                  goto err_reply; @@ -2600,16 +2648,14 @@ nfs_rpcsvc_conn_listening_handler (int fd, int idx, void *data, int poll_in,          rpcsvc_stage_t          *selectedstage = NULL;          int                     ret = -1;          rpcsvc_conn_t           *conn = NULL; -        rpcsvc_program_t        *prog = NULL;          rpcsvc_t                *svc = NULL;          if (!poll_in)                  return 0;          conn = (rpcsvc_conn_t *)data; -        prog = (rpcsvc_program_t *)conn->program;          svc = nfs_rpcsvc_conn_rpcsvc (conn); -        newconn = nfs_rpcsvc_conn_accept_init (svc, fd, prog); +        newconn = nfs_rpcsvc_conn_accept_init (svc, fd);          if (!newconn) {                  gf_log (GF_RPCSVC, GF_LOG_ERROR, "failed to accept connection");                  goto err; @@ -2630,9 +2676,7 @@ nfs_rpcsvc_conn_listening_handler (int fd, int idx, void *data, int poll_in,                          " with new connection");                  goto close_err;          } -        gf_log (GF_RPCSVC, GF_LOG_DEBUG, "New Connection: Program %s, Num: %d," -                " Ver: %d, Port: %d", prog->progname, prog->prognum, -                prog->progver, prog->progport); +        gf_log (GF_RPCSVC, GF_LOG_DEBUG, "New Connection");          ret = 0;  close_err:          if (ret == -1) @@ -2732,6 +2776,8 @@ nfs_rpcsvc_program_register (rpcsvc_t *svc, rpcsvc_program_t program)                  goto free_prog;          memcpy (newprog, &program, sizeof (program)); +        INIT_LIST_HEAD (&newprog->proglist); +        list_add_tail (&newprog->proglist, &svc->allprograms);          selectedstage = nfs_rpcsvc_select_stage (svc);          ret = nfs_rpcsvc_stage_program_register (selectedstage, newprog); diff --git a/xlators/nfs/lib/src/rpcsvc.h b/xlators/nfs/lib/src/rpcsvc.h index 5a669cf83df..300111de5e0 100644 --- a/xlators/nfs/lib/src/rpcsvc.h +++ b/xlators/nfs/lib/src/rpcsvc.h @@ -244,9 +244,6 @@ typedef struct rpc_conn_state {          pthread_mutex_t         connlock;          int                     connstate; -        /* The program that is listening for requests on this connection. */ -        rpcsvc_program_t        *program; -          /* List of buffers awaiting transmission */          /* Accesses to txbufs between multiple threads calling           * rpcsvc_submit is synced through connlock. Prefer spinlock over @@ -365,10 +362,12 @@ struct rpcsvc_request {           */          void                    *private; +        /* To save a ref to the program for which this request is. */ +        rpcsvc_program_t        *program;  }; -#define nfs_rpcsvc_request_program(req) ((rpcsvc_program_t *)((req)->conn->program)) -#define nfs_rpcsvc_request_program_private(req) (((rpcsvc_program_t *)((req)->conn->program))->private) +#define nfs_rpcsvc_request_program(req) ((rpcsvc_program_t *)((req)->program)) +#define nfs_rpcsvc_request_program_private(req) ((req)->program->private)  #define nfs_rpcsvc_request_conn(req)        (req)->conn  #define nfs_rpcsvc_program_xlator(prg)      ((prg)->actorxl)  #define nfs_rpcsvc_request_actorxl(rq)      (nfs_rpcsvc_request_program(rq))->actorxl @@ -453,6 +452,7 @@ typedef struct rpc_svc_actor_desc {   * Never changed ever by any thread so no need for a lock.   */  struct rpc_svc_program { +        struct list_head        proglist;          char                    progname[RPCSVC_NAME_MAX];          int                     prognum;          int                     progver; @@ -522,6 +522,8 @@ typedef struct rpc_svc_state {          glusterfs_ctx_t         *ctx;          gf_boolean_t            register_portmap; + +        struct list_head        allprograms;  } rpcsvc_t;  | 
