From patchwork Mon Jul 16 18:36:32 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 1201501 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id DC594E0038 for ; Mon, 16 Jul 2012 18:36:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752118Ab2GPSgf (ORCPT ); Mon, 16 Jul 2012 14:36:35 -0400 Received: from mail-gh0-f174.google.com ([209.85.160.174]:46313 "EHLO mail-gh0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751736Ab2GPSgf (ORCPT ); Mon, 16 Jul 2012 14:36:35 -0400 Received: by ghrr11 with SMTP id r11so5328860ghr.19 for ; Mon, 16 Jul 2012 11:36:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:subject:to:date:message-id:user-agent:mime-version :content-type:content-transfer-encoding; bh=ivtSqEd98LyC9TlnoVe2XRh3tWVJ2fONaVX5xfTIomw=; b=kIeOOdWp0Sk0tGW8DWVV7aeB76nxLREuKQv9+PP31NsUn3YUB5qt3bRbu9lnNKCoMZ S6nvU329m7h22BqUpVM66+T+pyePOOkyHflpmM3Ze4/ktLT9XK8m4OBLH9eAKXWOCxBE vAjHiKFDSOpgOyoxd5xlQZJ3+harMBryY4TsDEfm1JSBwCUkZ4uzkXdvgIk6DqmilpR7 SWzBj2dcC9zkeuite1ZbJpGWMBzmNYx5Dy1ciIPU7et8xPhaGdud3TI6bMGsbSbQpfjB OBr89PGOq6IozqyBZM54X54je2+MIqfLNR77Ws74mrNF7eyAFmIE+XnWTbs2DGi5R2ZM 2cvw== Received: by 10.50.219.194 with SMTP id pq2mr5958331igc.25.1342463794087; Mon, 16 Jul 2012 11:36:34 -0700 (PDT) Received: from degas.1015granger.net ([99.26.161.222]) by mx.google.com with ESMTPS id ay5sm9407125igb.15.2012.07.16.11.36.33 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 16 Jul 2012 11:36:33 -0700 (PDT) From: Chuck Lever Subject: [PATCH] rpc.gssd: close upcall pipe on POLLHUP To: linux-nfs@vger.kernel.org Date: Mon, 16 Jul 2012 14:36:32 -0400 Message-ID: <20120716183526.2399.37839.stgit@degas.1015granger.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org When a POLLHUP event is received on a pipe file descriptor, that means the other side has closed its end of the pipe. If the receiver does not close its end of the pipe, the pipe is left in an open-but-unlinked state. For a "gssd" upcall pipe, the kernel may close its end, removing the directory entry for it, and then later create a fresh pipe named "gssd" in the same directory. In this case, rpc.gssd continues to listen on the open-but-unlinked previous "gssd" pipe. Thus upcalls on the new "gssd" pipe are left unanswered. In addition, poll(2) continues to return POLLHUP on the old pipe. Since there is no logic to close the pipe in rpc.gssd, poll(2) always returns immediately, and rpc.gssd goes into a tight loop. Typically, the kernel closes upcall pipes and destroys their parent directory at the same time. When an RPC client's directory vanishes, rpc.gssd sees the change via dnotify and eventually invokes destroy_client() which closes the user-space end of the pipes. However, if the kernel wants to switch authentication flavors (say from AUTH_KRB5 to AUTH_UNIX) on an RPC client without destroying it, the upcall pipes go away, but the RPC client's directory remains. rpc.gssd invokes update_client_list(), but that logic never closes upcall pipes if the client directory is still in place. After a POLLHUP on a pipe, close it when rpc.gssd reconstructs its list of upcall clients. Signed-off-by: Chuck Lever --- I know folks are probably on vacation this week, so this is only a request for comments. utils/gssd/gssd.h | 2 ++ utils/gssd/gssd_main_loop.c | 8 ++++++-- utils/gssd/gssd_proc.c | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h index e0a2b7b..ec81beb 100644 --- a/utils/gssd/gssd.h +++ b/utils/gssd/gssd.h @@ -82,8 +82,10 @@ struct clnt_info { char *protocol; int krb5_fd; int krb5_poll_index; + int krb5_close_me; int gssd_fd; int gssd_poll_index; + int gssd_close_me; struct sockaddr_storage addr; }; diff --git a/utils/gssd/gssd_main_loop.c b/utils/gssd/gssd_main_loop.c index 187954c..6480390 100644 --- a/utils/gssd/gssd_main_loop.c +++ b/utils/gssd/gssd_main_loop.c @@ -78,8 +78,10 @@ scan_poll_results(int ret) { i = clp->gssd_poll_index; if (i >= 0 && pollarray[i].revents) { - if (pollarray[i].revents & POLLHUP) + if (pollarray[i].revents & POLLHUP) { + clp->gssd_close_me = 1; dir_changed = 1; + } if (pollarray[i].revents & POLLIN) handle_gssd_upcall(clp); pollarray[clp->gssd_poll_index].revents = 0; @@ -89,8 +91,10 @@ scan_poll_results(int ret) } i = clp->krb5_poll_index; if (i >= 0 && pollarray[i].revents) { - if (pollarray[i].revents & POLLHUP) + if (pollarray[i].revents & POLLHUP) { + clp->krb5_close_me = 1; dir_changed = 1; + } if (pollarray[i].revents & POLLIN) handle_krb5_upcall(clp); pollarray[clp->krb5_poll_index].revents = 0; diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c index fed2886..5e33379 100644 --- a/utils/gssd/gssd_proc.c +++ b/utils/gssd/gssd_proc.c @@ -339,6 +339,25 @@ process_clnt_dir_files(struct clnt_info * clp) char gname[PATH_MAX]; char info_file_name[PATH_MAX]; + if (clp->gssd_close_me) { + printerr(2, "Closing 'gssd' pipe for %s\n", clp->dirname); + close(clp->gssd_fd); + memset(&pollarray[clp->gssd_poll_index], 0, + sizeof(struct pollfd)); + clp->gssd_fd = -1; + clp->gssd_poll_index = -1; + clp->gssd_close_me = 0; + } + if (clp->krb5_close_me) { + printerr(2, "Closing 'krb5' pipe for %s\n", clp->dirname); + close(clp->krb5_fd); + memset(&pollarray[clp->krb5_poll_index], 0, + sizeof(struct pollfd)); + clp->krb5_fd = -1; + clp->krb5_poll_index = -1; + clp->krb5_close_me = 0; + } + if (clp->gssd_fd == -1) { snprintf(gname, sizeof(gname), "%s/gssd", clp->dirname); clp->gssd_fd = open(gname, O_RDWR);