From patchwork Wed Jan 4 21:06:39 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 134360 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from acsinet15.oracle.com (acsinet15.oracle.com [141.146.126.227]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "acsinet15.oracle.com", Issuer "VeriSign Class 3 International Server CA - G3" (verified OK)) by ozlabs.org (Postfix) with ESMTPS id 666B81007D7 for ; Thu, 5 Jan 2012 08:06:49 +1100 (EST) Received: from acsinet22.oracle.com (acsinet22.oracle.com [141.146.126.238]) by acsinet15.oracle.com (Switch-3.4.4/Switch-3.4.4) with ESMTP id q04L6hQ7029557 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 4 Jan 2012 21:06:44 GMT Received: from oss.oracle.com (oss.oracle.com [141.146.12.120]) by acsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id q04L6gwN006506 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 4 Jan 2012 21:06:43 GMT Received: from localhost ([127.0.0.1] helo=oss.oracle.com) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1RiY2k-0001gn-Rp; Wed, 04 Jan 2012 13:06:42 -0800 Received: from rcsinet12.oracle.com ([148.87.113.124]) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1RiY2j-0001gg-C7 for fedfs-utils-devel@oss.oracle.com; Wed, 04 Jan 2012 13:06:41 -0800 Received: from mail-gy0-f171.google.com (mail-gy0-f171.google.com [209.85.160.171]) by rcsinet12.oracle.com (Sentrion-MTA-4.2.0/Sentrion-MTA-4.2.0) with ESMTP id q04L6DpI008243 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Wed, 4 Jan 2012 21:06:40 GMT Received: by mail-gy0-f171.google.com with SMTP id 10so9357234ghy.2 for ; Wed, 04 Jan 2012 13:06:40 -0800 (PST) Received: by 10.101.208.1 with SMTP id k1mr9608870anq.12.1325711200696; Wed, 04 Jan 2012 13:06:40 -0800 (PST) Received: from degas.1015granger.net (adsl-99-26-161-222.dsl.sfldmi.sbcglobal.net. [99.26.161.222]) by mx.google.com with ESMTPS id d8sm106102109ang.2.2012.01.04.13.06.39 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 04 Jan 2012 13:06:40 -0800 (PST) From: Chuck Lever To: fedfs-utils-devel@oss.oracle.com Date: Wed, 04 Jan 2012 16:06:39 -0500 Message-ID: <20120104210638.8810.73629.stgit@degas.1015granger.net> In-Reply-To: <20120104204207.8810.10569.stgit@degas.1015granger.net> References: <20120104204207.8810.10569.stgit@degas.1015granger.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Flow-Control-Info: class=Default ip=209.85.160.171 ct-class=R6 ct-vol1=0 ct-vol2=0 ct-vol3=0 ct-risk=68 ct-spam1=0 ct-spam2=0 ct-bulk=0 rcpts=1 size=7700 Subject: [fedfs-utils] [PATCH 3/7] libjunction: Introduce new APIs for creating and deleting FedFS junctions X-BeenThere: fedfs-utils-devel@oss.oracle.com X-Mailman-Version: 2.1.9 Precedence: list Reply-To: fedfs-utils Developers List-Id: fedfs-utils Developers List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: fedfs-utils-devel-bounces@oss.oracle.com Errors-To: fedfs-utils-devel-bounces@oss.oracle.com X-Source-IP: acsinet22.oracle.com [141.146.126.238] X-CT-RefId: str=0001.0A090205.4F04BF64.0185:SCFSTAT1119972, ss=1, re=-6.300, fgs=0 X-Auth-Type: Internal IP Introduce fresh APIs that encapsulate the activities of managing the junction data and the junction object's mode bits. The common junction utility functions should no longer be invoked outside of libjunction. Instead, upper layers should invoke the type-specific APIs we're introducing in this patch. We're headed towards a world where callers like rpc.fedfsd will not care about the mode bit settings or what extended attributes are used to represent junctions. Note that fedfs_add_junction() behaves a little differently than the previous code. It updates the mode bits _after_ it has successfully created the mode xattr. This should prevent the kernel from generating an upcall on a junction that is partially formed. And, fedfs_add_junction() is more careful to clean up if something fails. This patch also addresses an open file descriptor leak in fedfs_save_mode(). Signed-off-by: Chuck Lever --- src/fedfsd/svc.c | 14 +----- src/include/junction.h | 7 +-- src/libjunction/junction.c | 108 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 93 insertions(+), 36 deletions(-) diff --git a/src/fedfsd/svc.c b/src/fedfsd/svc.c index 6d548c1..ece0702 100644 --- a/src/fedfsd/svc.c +++ b/src/fedfsd/svc.c @@ -531,13 +531,7 @@ fedfsd_svc_create_junction_1(SVCXPRT *xprt) goto out; } - result = fedfs_save_mode(pathname); - if (result != FEDFS_OK) { - xlog(D_GENERAL, "%s: fedfs_save_mode", __func__); - goto out; - } - - result = fedfs_store_fsn(pathname, fsn_uuid, host); + result = fedfs_add_junction(pathname, fsn_uuid, host); if (result != FEDFS_OK) { xlog(D_GENERAL, "%s: fedfs_store_fsn", __func__); goto out; @@ -635,11 +629,7 @@ fedfsd_svc_delete_junction_1(SVCXPRT *xprt) goto out; } - result = fedfs_restore_mode(pathname); - if (result != FEDFS_OK) - goto out; - - result = fedfs_remove_fsn(pathname); + result = fedfs_delete_junction(pathname); if (result!= FEDFS_OK) goto out; diff --git a/src/include/junction.h b/src/include/junction.h index edbab7b..de2f496 100644 --- a/src/include/junction.h +++ b/src/include/junction.h @@ -28,17 +28,14 @@ #include "nsdb.h" -FedFsStatus fedfs_remove_fsn(const char *pathname); -FedFsStatus fedfs_store_fsn(const char *pathname, const char *uuid, +FedFsStatus fedfs_delete_junction(const char *pathname); +FedFsStatus fedfs_add_junction(const char *pathname, const char *uuid, const nsdb_t host); FedFsStatus fedfs_get_fsn(const char *pathname, char **uuid, nsdb_t *host); FedFsStatus fedfs_is_prejunction(const char *pathname); FedFsStatus fedfs_is_junction(const char *pathname); -FedFsStatus fedfs_save_mode(const char *pathname); -FedFsStatus fedfs_restore_mode(const char *pathname); - FedFsStatus junction_flush_exports_cache(void); #endif /* !_FEDFS_JUNCTION_H_ */ diff --git a/src/libjunction/junction.c b/src/libjunction/junction.c index 10fc5f2..472f4ef 100644 --- a/src/libjunction/junction.c +++ b/src/libjunction/junction.c @@ -360,7 +360,7 @@ fedfs_remove_xattr(int fd, const char *pathname, const char *name) * * @note Access to trusted attributes requires CAP_SYS_ADMIN. */ -FedFsStatus +static FedFsStatus fedfs_remove_fsn(const char *pathname) { FedFsStatus retval; @@ -394,16 +394,13 @@ out: * @param host an initialized nsdb_t object * @return a FedFsStatus code */ -FedFsStatus +static FedFsStatus fedfs_store_fsn(const char *pathname, const char *fsn_uuid, const nsdb_t host) { FedFsStatus retval; char buf[20]; int fd, len; - if (fsn_uuid == NULL || host == NULL) - return FEDFS_ERR_INVAL; - retval = fedfs_open_path(pathname, &fd); if (retval != FEDFS_OK) return retval; @@ -411,32 +408,24 @@ fedfs_store_fsn(const char *pathname, const char *fsn_uuid, const nsdb_t host) retval = fedfs_set_xattr(fd, pathname, FEDFSD_XATTR_NAME_TYPE, FEDFSD_XATTR_NAME_TYPE, sizeof(FEDFSD_XATTR_NAME_TYPE)); if (retval != FEDFS_OK) - goto out_err; + goto out; retval = fedfs_set_xattr(fd, pathname, FEDFSD_XATTR_NAME_FSNUUID, fsn_uuid, strlen(fsn_uuid) + 1); if (retval != FEDFS_OK) - goto out_err; + goto out; retval = fedfs_set_xattr(fd, pathname, FEDFSD_XATTR_NAME_NSDB, nsdb_hostname(host), nsdb_hostname_len(host) + 1); if (retval != FEDFS_OK) - goto out_err; + goto out; len = snprintf(buf, sizeof(buf), "%u", nsdb_port(host)); retval = fedfs_set_xattr(fd, pathname, FEDFSD_XATTR_NAME_PORT, buf, len + 1); - if (retval != FEDFS_OK) - goto out_err; - - retval = fedfs_set_sticky_bit(fd, pathname); out: (void)close(fd); return retval; - -out_err: - (void)fedfs_remove_fsn(pathname); - goto out; } /** @@ -645,6 +634,7 @@ FedFsStatus fedfs_save_mode(const char *pathname) { FedFsStatus retval; + unsigned int mode; struct stat stb; char buf[16]; int fd; @@ -659,10 +649,26 @@ fedfs_save_mode(const char *pathname) return FEDFS_ERR_ACCESS; } - (void)snprintf(buf, sizeof(buf), "%o", ALLPERMS & stb.st_mode); - - return fedfs_set_xattr(fd, pathname, FEDFSD_XATTR_NAME_MODE, + mode = ALLPERMS & stb.st_mode; + (void)snprintf(buf, sizeof(buf), "%o", mode); + retval = fedfs_set_xattr(fd, pathname, FEDFSD_XATTR_NAME_MODE, buf, strlen(buf)); + if (retval != FEDFS_OK) + goto out; + + retval = fedfs_set_sticky_bit(fd, pathname); + if (retval != FEDFS_OK) { + (void)fedfs_remove_xattr(fd, pathname, + FEDFSD_XATTR_NAME_MODE); + goto out; + } + + xlog(D_CALL, "%s: saved mode %o to %s", __func__, mode, pathname); + retval = FEDFS_OK; + +out: + (void)close(fd); + return retval; } /** @@ -702,6 +708,7 @@ fedfs_restore_mode(const char *pathname) goto out; } + xlog(D_CALL, "%s: restored mode %o to %s", __func__, mode, pathname); retval = FEDFS_OK; out: @@ -709,3 +716,66 @@ out: (void)close(fd); return retval; } + +/** + * Add FedFS junction information to a pre-existing object + * + * @param pathname NUL-terminated C string containing pathname of a junction + * @param fsn_uuid NUL-terminated C string containing FSN UUID to store + * @param host an initialized nsdb_t object + * @return a FedFsStatus code + * + * An error occurs if the object referred to by "pathname" does not + * exist or contains existing FedFS junction data. + */ +FedFsStatus +fedfs_add_junction(const char *pathname, const char *fsn_uuid, const nsdb_t host) +{ + FedFsStatus retval; + + if (fsn_uuid == NULL || host == NULL) + return FEDFS_ERR_INVAL; + + retval = fedfs_is_prejunction(pathname); + if (retval != FEDFS_ERR_NOTJUNCT) + return retval; + + retval = fedfs_store_fsn(pathname, fsn_uuid, host); + if (retval != FEDFS_OK) + goto out_err; + + retval = fedfs_save_mode(pathname); + if (retval != FEDFS_OK) + goto out_err; + + return retval; + +out_err: + (void)fedfs_remove_fsn(pathname); + return retval; +} + +/** + * Remove FedFS junction information from an object + * + * @param pathname NUL-terminated C string containing pathname of a directory + * @return a FedFsStatus code + * + * An error occurs if the object referred to by "pathname" does not + * exist or does not contain FedFS junction data. + */ +FedFsStatus +fedfs_delete_junction(const char *pathname) +{ + FedFsStatus retval; + + retval = fedfs_is_junction(pathname); + if (retval != FEDFS_OK) + return retval; + + retval = fedfs_restore_mode(pathname); + if (retval != FEDFS_OK) + return retval; + + return fedfs_remove_fsn(pathname); +}