From 40a5e452bea79d1c7c78af480354e16ef970ca63 Mon Sep 17 00:00:00 2001 From: Shehjar Tikoo Date: Fri, 11 Mar 2011 01:48:57 +0000 Subject: 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 Signed-off-by: Vijay Bellur BUG: 2504 () URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2504 --- xlators/nfs/lib/src/rpcsvc.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'xlators/nfs/lib/src/rpcsvc.c') diff --git a/xlators/nfs/lib/src/rpcsvc.c b/xlators/nfs/lib/src/rpcsvc.c index 987c24080..ea7533200 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; } -- cgit