Today, when we convert a directory into a junction, we save the directory's mode bits in an extended attribute, and then set them to a known weird value, which the kernel can detect.
As an experiment, save the directory mode in the junction XML as well. If this works out, we can avoid using a separate extended attribute for the saved mode. Signed-off-by: Chuck Lever <[email protected]> --- src/libjunction/fedfs.c | 38 ++++++++++++++++++++++++++++++++ src/libjunction/junction-internal.h | 10 +++++++++ src/libjunction/junction.c | 41 ++++++++++++++++++++++++++++++----- src/libjunction/nfs.c | 38 ++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 6 deletions(-) diff --git a/src/libjunction/fedfs.c b/src/libjunction/fedfs.c index 5acd58e..a39925b 100644 --- a/src/libjunction/fedfs.c +++ b/src/libjunction/fedfs.c @@ -28,6 +28,7 @@ * * <?xml version="1.0" encoding="UTF-8"?> * <junction> + * <savedmode bits="1777" /> * <fileset> * <name fsnuuid="d2b09895-98ff-415e-ac73-565fad7b429b" * nsdbname="nsdb.example.net" @@ -175,6 +176,38 @@ fedfs_fileset_xml(const char *pathname, xmlNodePtr root, } /** + * Construct a "savedmode" element + * + * @param pathname NUL-terminated C string containing pathname of a junction + * @param root root element of XML document tree + * @return a FedFsStatus code + */ +static FedFsStatus +fedfs_savedmode_xml(const char *pathname, xmlNodePtr root) +{ + xmlNodePtr savedmode; + FedFsStatus retval; + mode_t mode; + char buf[8]; + + retval = junction_get_mode(pathname, &mode); + if (retval != FEDFS_OK) + return retval; + + savedmode = xmlNewTextChild(root, NULL, JUNCTION_XML_SAVEDMODE_TAG, NULL); + if (savedmode == NULL) { + xlog(D_GENERAL, "%s: Failed to add savedmode element for %s\n", + __func__, pathname); + return FEDFS_ERR_SVRFAULT; + } + + (void)snprintf(buf, sizeof(buf), "%o", ALLPERMS & mode); + xmlSetProp(savedmode, JUNCTION_XML_MODEBITS_ATTR, (const xmlChar *)buf); + + return FEDFS_OK; +} + +/** * Construct FedFS junction XML document * * @param pathname NUL-terminated C string containing pathname of a junction @@ -189,6 +222,7 @@ fedfs_build_xml(const char *pathname, xmlDocPtr doc, const char *fsn_uuid, const char *nsdb_name, unsigned short nsdb_port) { + FedFsStatus retval; xmlNodePtr root; root = xmlNewNode(NULL, JUNCTION_XML_ROOT_TAG); @@ -199,6 +233,10 @@ fedfs_build_xml(const char *pathname, xmlDocPtr doc, } (void)xmlDocSetRootElement(doc, root); + retval = fedfs_savedmode_xml(pathname, root); + if (retval != FEDFS_OK) + return retval; + return fedfs_fileset_xml(pathname, root, fsn_uuid, nsdb_name, nsdb_port); } diff --git a/src/libjunction/junction-internal.h b/src/libjunction/junction-internal.h index e80edf0..8279ad1 100644 --- a/src/libjunction/junction-internal.h +++ b/src/libjunction/junction-internal.h @@ -58,6 +58,15 @@ */ #define JUNCTION_XML_FILESET_TAG (const xmlChar *)"fileset" +/** + * Tag name of savedmode element of a junction XML document + */ +#define JUNCTION_XML_SAVEDMODE_TAG (const xmlChar *)"savedmode" + +/** + * Name of mode bits attribute on a savedmode element + */ +#define JUNCTION_XML_MODEBITS_ATTR (const xmlChar *)"bits" /** ** Junction helper functions @@ -77,6 +86,7 @@ FedFsStatus junction_set_xattr(int fd, const char *path, const char *name, const void *contents, const size_t contentlen); FedFsStatus junction_remove_xattr(int fd, const char *pathname, const char *name); +FedFsStatus junction_get_mode(const char *pathname, mode_t *mode); FedFsStatus junction_save_mode(const char *pathname); FedFsStatus junction_restore_mode(const char *pathname); diff --git a/src/libjunction/junction.c b/src/libjunction/junction.c index cd53744..9d9a266 100644 --- a/src/libjunction/junction.c +++ b/src/libjunction/junction.c @@ -374,18 +374,17 @@ junction_remove_xattr(int fd, const char *pathname, const char *name) } /** - * Save the object's mode in an xattr. Saved mode is human-readable. + * Retrieve object's mode bits. * * @param pathname NUL-terminated C string containing pathname of a directory + * @param mode OUT: mode bits * @return a FedFsStatus code */ FedFsStatus -junction_save_mode(const char *pathname) +junction_get_mode(const char *pathname, mode_t *mode) { FedFsStatus retval; - unsigned int mode; struct stat stb; - char buf[16]; int fd; retval = junction_open_path(pathname, &fd); @@ -398,8 +397,38 @@ junction_save_mode(const char *pathname) return FEDFS_ERR_ACCESS; } - mode = ALLPERMS & stb.st_mode; - (void)snprintf(buf, sizeof(buf), "%o", mode); + (void)close(fd); + + xlog(D_CALL, "%s: pathname %s has mode %o", + __func__, pathname, stb.st_mode); + *mode = stb.st_mode; + return FEDFS_OK; + +} + +/** + * Save the object's mode in an xattr. Saved mode is human-readable. + * + * @param pathname NUL-terminated C string containing pathname of a directory + * @return a FedFsStatus code + */ +FedFsStatus +junction_save_mode(const char *pathname) +{ + FedFsStatus retval; + mode_t mode; + char buf[8]; + int fd; + + retval = junction_get_mode(pathname, &mode); + if (retval != FEDFS_OK) + return retval; + (void)snprintf(buf, sizeof(buf), "%o", ALLPERMS & mode); + + retval = junction_open_path(pathname, &fd); + if (retval != FEDFS_OK) + return retval; + retval = junction_set_xattr(fd, pathname, JUNCTION_XATTR_NAME_MODE, buf, strlen(buf)); if (retval != FEDFS_OK) diff --git a/src/libjunction/nfs.c b/src/libjunction/nfs.c index 67c434c..b141392 100644 --- a/src/libjunction/nfs.c +++ b/src/libjunction/nfs.c @@ -29,6 +29,7 @@ * * <?xml version="1.0" encoding="UTF-8"?> * <junction> + * <savedmode bits="1777" /> * <fileset> * <location> * <host name="fileserver.example.net" port="2049" /> @@ -708,6 +709,38 @@ nfs_fileset_xml(const char *pathname, xmlNodePtr root, } /** + * Construct a "savedmode" element + * + * @param pathname NUL-terminated C string containing pathname of a junction + * @param root root element of XML document tree + * @return a FedFsStatus code + */ +static FedFsStatus +nfs_savedmode_xml(const char *pathname, xmlNodePtr root) +{ + xmlNodePtr savedmode; + FedFsStatus retval; + mode_t mode; + char buf[8]; + + retval = junction_get_mode(pathname, &mode); + if (retval != FEDFS_OK) + return retval; + + savedmode = xmlNewTextChild(root, NULL, JUNCTION_XML_SAVEDMODE_TAG, NULL); + if (savedmode == NULL) { + xlog(D_GENERAL, "%s: Failed to add savedmode element for %s\n", + __func__, pathname); + return FEDFS_ERR_SVRFAULT; + } + + (void)snprintf(buf, sizeof(buf), "%o", ALLPERMS & mode); + xmlSetProp(savedmode, JUNCTION_XML_MODEBITS_ATTR, (const xmlChar *)buf); + + return FEDFS_OK; +} + +/** * Construct NFS junction XML document from list of NFS locations * * @param pathname NUL-terminated C string containing pathname of a junction @@ -719,6 +752,7 @@ static FedFsStatus nfs_junction_xml(const char *pathname, xmlDocPtr doc, struct nfs_fsloc *fslocs) { + FedFsStatus retval; xmlNodePtr root; root = xmlNewNode(NULL, JUNCTION_XML_ROOT_TAG); @@ -729,6 +763,10 @@ nfs_junction_xml(const char *pathname, xmlDocPtr doc, } (void)xmlDocSetRootElement(doc, root); + retval = nfs_savedmode_xml(pathname, root); + if (retval != FEDFS_OK) + return retval; + return nfs_fileset_xml(pathname, root, fslocs); } _______________________________________________ fedfs-utils-devel mailing list [email protected] https://oss.oracle.com/mailman/listinfo/fedfs-utils-devel
