[Ocfs2-devel] [PATCH 3/4] ocfs2: Add CDSL

Sunil Mushran sunil.mushran at oracle.com
Fri Feb 8 10:49:36 PST 2008


This is a forward port of the CDSL implementation in OCFS2 1.2.

Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
---
 fs/ocfs2/symlink.c |  244 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 244 insertions(+), 0 deletions(-)

diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index 9794649..0cc45d0 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -131,6 +131,246 @@ out:
 	return ret;
 }
 
+#ifdef OCFS2_CDSL
+
+struct ocfs2_symlink_ops {
+	const char *name;
+	const unsigned int len;
+	unsigned int (*subst_fn) (char *str, void *data);
+};
+
+/**
+ *** sym_hostname - Substitute system host name
+ *** @str: String for result
+ *** @len: Length of result buffer
+ ***
+ *** Returns: Length of hostname
+ ***/
+static unsigned int
+sym_hostname(char *str, void *data)
+{
+	  unsigned int l = strlen(system_utsname.nodename);
+
+	  if (str)
+		memcpy(str, system_utsname.nodename, l);
+
+	  return l;
+}
+
+/**
+ *** sym_machine - Substitute machine type
+ *** @str: String for result
+ *** @len: Length of result buffer
+ ***
+ *** Returns: Length of machine type
+ ***/
+
+static unsigned int
+sym_machine(char *str, void *data)
+{
+	unsigned int l = strlen(system_utsname.machine);
+
+	if (str)
+	       memcpy(str, system_utsname.machine, l);
+
+	return l;
+}
+
+/**
+ *** sym_os - Substitute OS name
+ *** @str: String for result
+ *** @len: Length of result buffer
+ ***
+ *** Returns: Length of OS name
+ ***/
+
+static unsigned int
+sym_os(char *str, void *data)
+{
+	unsigned int l = strlen(system_utsname.sysname);
+
+	if (str)
+	       memcpy(str, system_utsname.sysname, l);
+
+	return l;
+}
+
+/**
+ *** sym_nodenum - Substitute node number
+ *** @str: String for result
+ *** @len: Length of result buffer
+ ***
+ *** Returns: Length of  nodeNum
+ ***/
+
+static unsigned int
+sym_nodenum(char *str, void *data)
+{
+	unsigned int l;
+	char buf[10];
+	struct inode *inode = data;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+	l = sprintf(buf, "%lu", (unsigned long)osb->node_num);
+
+	if (str) {
+	      memcpy(str, buf, l);
+	      str[l] = '\0';
+	}
+
+	return l;
+}
+
+static unsigned int
+sym_system(char *str, void *data)
+{
+	unsigned int ml = strlen(system_utsname.machine);
+	unsigned int sl = strlen(system_utsname.sysname);
+	unsigned int l = ml + sl + 1;
+
+	if (str) {
+	       memcpy(str, system_utsname.machine, ml);
+	       str[ml] = '_';
+	       memcpy(str + ml + 1, system_utsname.sysname, sl);
+	       str[l] = '\0';
+	};
+
+	return l;
+}
+
+static unsigned int
+sym_uid(char *str, void *data)
+{
+	unsigned int l;
+	char buf[10];
+
+	l = sprintf(buf, "%lu", (unsigned long)current->fsuid);
+
+	if (str) {
+	      memcpy(str, buf, l);
+	      str[l] = '\0';
+	}
+
+	return l;
+}
+
+static unsigned int
+sym_gid(char *str, void *data)
+{
+	unsigned int l;
+	char buf[10];
+
+	l = sprintf(buf, "%lu", (unsigned long)current->fsgid);
+
+	if (str) {
+	      memcpy(str, buf, l);
+	      str[l] = '\0';
+	}
+
+	return l;
+}
+
+static struct ocfs2_symlink_ops symlink_ops[] = {
+	{"hostname}", 9, sym_hostname},
+	{"mach}", 5, sym_machine},
+	{"os}", 3, sym_os},
+	{"nodenum}", 8, sym_nodenum},
+	{"sys}", 4, sym_system},
+	{"uid}", 4, sym_uid},
+	{"gid}", 4, sym_gid},
+	{NULL, 0, NULL}
+};
+
+
+/**
+ *** ocfs2_link_expand - Expand a context sensitive symlink
+ *** @ops: The symlink substitution operations table
+ *** @out: Buffer to place result in
+ *** @in: Buffer to get symlink from
+ ***
+ *** Returns: 0 or error code
+ ***/
+
+static void ocfs2_link_expand(struct ocfs2_symlink_ops *ops, char *out, char *in, struct inode *inode)
+{
+	unsigned int i;
+
+	while (*in) {
+		*out++ = *in;
+		if (*in++ != '{')
+			continue;
+
+		for (i = 0; ops[i].name; i++) {
+			if (memcmp(in, ops[i].name, ops[i].len) == 0) {
+				out--;
+				out += ops[i].subst_fn(out, inode);
+				in += ops[i].len;
+			}
+		}
+	}
+
+	*out = 0;
+}
+
+
+/**
+ *** ocfs2_link_size - Return expanded size required to store a symlink
+ *** @str: The symlink
+ *** @ops: The symlink substitution operations table
+ ***
+ *** Returns: The size of the expanded symlink.
+ ***/
+
+
+static unsigned int ocfs2_link_size(struct ocfs2_symlink_ops *ops, char *str, struct inode *inode)
+{
+	unsigned int len = 0;
+	unsigned int i;
+
+	while (*str) {
+		len++;
+		if (*str++ != '{')
+			continue;
+
+		for (i = 0; ops[i].name; i++) {
+			if (memcmp(str, ops[i].name, ops[i].len) == 0) {
+				len--;
+				len += ops[i].subst_fn(NULL, inode);
+				str += ops[i].len;
+				break;
+			}
+		}
+	}
+
+	return len + 1;
+}
+
+static inline int ocfs2_cdsl_follow_link(struct nameidata *nd,
+					 char *old_link,
+					 struct inode *inode)
+{
+	int status;
+	char *new_link;
+	unsigned int len;
+
+	len = ocfs2_link_size(symlink_ops, old_link, inode);
+	new_link = kmalloc(len, GFP_KERNEL);
+	if (new_link == NULL) {
+		status = -ENOMEM;
+		mlog_errno(status);
+		goto bail;
+	}
+
+	ocfs2_link_expand(symlink_ops, new_link, old_link, inode);
+
+	status = vfs_follow_link(nd, new_link);
+
+	kfree(new_link);
+bail:
+	return status;
+}
+#endif
+
 static void *ocfs2_follow_link(struct dentry *dentry,
 			       struct nameidata *nd)
 {
@@ -150,7 +390,11 @@ static void *ocfs2_follow_link(struct dentry *dentry,
 		goto bail;
 	}
 
+#ifdef OCFS2_CDSL
+	status = ocfs2_cdsl_follow_link(nd, link, inode);
+#else
 	status = vfs_follow_link(nd, link);
+#endif
 
 bail:
 	if (page) {
-- 
1.5.2.5




More information about the Ocfs2-devel mailing list