Patchwork [7/8] libjunction: Save directory mode in junction XML

login
register
mail settings
Submitter Chuck Lever
Date Oct. 11, 2012, 7:09 p.m.
Message ID <20121011190939.31447.93783.stgit@seurat.1015granger.net>
Download mbox | patch
Permalink /patch/190978/
State Accepted
Headers show

Comments

Chuck Lever - Oct. 11, 2012, 7:09 p.m.
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 <chuck.lever@oracle.com>
---

 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(-)

Patch

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);
 }