@@ -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;
@@ -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_ */
@@ -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);
+}
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 <chuck.lever@oracle.com> --- src/fedfsd/svc.c | 14 +----- src/include/junction.h | 7 +-- src/libjunction/junction.c | 108 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 93 insertions(+), 36 deletions(-)