diff options
author | Shehjar Tikoo <shehjart@gluster.com> | 2011-03-11 01:48:57 +0000 |
---|---|---|
committer | Vijay Bellur <vijay@dev.gluster.com> | 2011-03-12 05:10:21 -0800 |
commit | 40a5e452bea79d1c7c78af480354e16ef970ca63 (patch) | |
tree | a60383dc48a5917b6219c6400654bddbd6811638 /xlators/nfs/lib/src/rpcsvc.c | |
parent | 57d4551c05cdc17d2a9d687aca66802ce7af53f0 (diff) |
nfs-rpc: Fix order of freeing request and connection objects
..to prevent segfaults due to double frees and dereferencing of freed
up memory.
Signed-off-by: Shehjar Tikoo <shehjart@gluster.com>
Signed-off-by: Vijay Bellur <vijay@dev.gluster.com>
BUG: 2504 ()
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2504
Diffstat (limited to 'xlators/nfs/lib/src/rpcsvc.c')
-rw-r--r-- | xlators/nfs/lib/src/rpcsvc.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/xlators/nfs/lib/src/rpcsvc.c b/xlators/nfs/lib/src/rpcsvc.c index 987c24080fd..ea75332008e 100644 --- a/xlators/nfs/lib/src/rpcsvc.c +++ b/xlators/nfs/lib/src/rpcsvc.c @@ -1665,6 +1665,8 @@ nfs_rpcsvc_submit_generic (rpcsvc_request_t *req, struct iovec msgvec, struct iobuf *replyiob = NULL; struct iovec recordhdr = {0, }; rpcsvc_conn_t *conn = NULL; + int rpc_status = 0; + int rpc_error = 0; if ((!req) || (!req->conn)) return -1; @@ -1705,11 +1707,19 @@ disconnect_exit: * no actor was called, we will be losing the ref held for the RPC * layer. */ - if ((nfs_rpcsvc_request_accepted (req)) && - (nfs_rpcsvc_request_accepted_success (req))) - nfs_rpcsvc_conn_unref (conn); + /* If the request succeeded and was handed to the actor, then unref the + * conn. + */ + + rpc_status = req->rpc_stat; + rpc_error = req->rpc_err; + /* Must mem_put req back to rxpool before the possibility of destroying + * conn in conn_unref, where the rxpool itself is destroyed. + */ mem_put (conn->rxpool, req); + if ((rpc_status == MSG_ACCEPTED) && (rpc_error == SUCCESS)) + nfs_rpcsvc_conn_unref (conn); return ret; } @@ -1783,7 +1793,7 @@ nfs_rpcsvc_submit_vectors (rpcsvc_request_t *req) struct iobuf *replyiob = NULL; struct iovec recordhdr = {0, }; rpcsvc_txbuf_t *rpctxb = NULL; - void *rxpool = NULL; + rpcsvc_conn_t *conn = NULL; if ((!req) || (!req->conn)) return -1; @@ -1819,13 +1829,16 @@ disconnect_exit: * response to the ref that is performed on the conn when a request is * handed to the RPC program. */ - rxpool = req->conn->rxpool; + conn = req->conn; + /* Must mem_put req back to rxpool before the possibility of destroying + * conn in conn_unref, where the rxpool itself is destroyed. + */ + mem_put (conn->rxpool, req); - nfs_rpcsvc_conn_unref (req->conn); + nfs_rpcsvc_conn_unref (conn); if (ret == -1) iobuf_unref (replyiob); - mem_put (rxpool, req); return ret; } |