From b2ac7b39a0b999b7e3d38b4164f9f2147a76a2e5 Mon Sep 17 00:00:00 2001
From: wangdi <wangdi>
Date: Mon, 23 Feb 2004 17:39:07 +0000
Subject: [PATCH] update smfs 1)Add kml in smfs, but still not finish it, will
 change later according to llog. 2)some minor fixs

---
 lustre/smfs/Makefile.am     |   6 +-
 lustre/smfs/cache.c         |  27 ++++
 lustre/smfs/dir.c           |  20 ++-
 lustre/smfs/file.c          |   1 +
 lustre/smfs/inode.c         |   2 +
 lustre/smfs/journal.c       | 249 ++++++++++++++++++++++++++++++++++++
 lustre/smfs/journal_ext3.c  |  96 ++++++++++++++
 lustre/smfs/kml.c           |  59 +++++++++
 lustre/smfs/kml_idl.h       |  52 ++++++++
 lustre/smfs/options.c       |  65 +++++-----
 lustre/smfs/reint.c         |  15 +++
 lustre/smfs/sm_fs.c         |   2 +-
 lustre/smfs/smfs_internal.h |  32 ++++-
 lustre/smfs/smfs_llog.c     |  27 ++++
 lustre/smfs/super.c         |  14 +-
 lustre/smfs/symlink.c       |   1 +
 lustre/smfs/sysctl.c        |   2 +-
 17 files changed, 629 insertions(+), 41 deletions(-)
 create mode 100644 lustre/smfs/journal.c
 create mode 100644 lustre/smfs/journal_ext3.c
 create mode 100644 lustre/smfs/kml.c
 create mode 100644 lustre/smfs/kml_idl.h
 create mode 100644 lustre/smfs/reint.c
 create mode 100644 lustre/smfs/smfs_llog.c

diff --git a/lustre/smfs/Makefile.am b/lustre/smfs/Makefile.am
index 96265dabe7..529d02915f 100644
--- a/lustre/smfs/Makefile.am
+++ b/lustre/smfs/Makefile.am
@@ -10,7 +10,7 @@ MODULE = smfs
 modulefs_DATA = smfs.o
 EXTRA_PROGRAMS = smfs
 
-smfs_SOURCES = super.c options.c inode.c cache.c dir.c  
-smfs_SOURCES += sysctl.c file.c symlink.c sm_fs.c
-
+smfs_SOURCES = super.c options.c inode.c cache.c dir.c sysctl.c file.c 
+smfs_SOURCES += symlink.c sm_fs.c kml.c reint.c journal.c journal_ext3.c
+smfs_SOURCES += smfs_llog.c
 include $(top_srcdir)/Rules
diff --git a/lustre/smfs/cache.c b/lustre/smfs/cache.c
index c4bfa27c5b..d94a0cb2a6 100644
--- a/lustre/smfs/cache.c
+++ b/lustre/smfs/cache.c
@@ -9,7 +9,9 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/lustre_idl.h>
 #include <portals/list.h>
+
 #include "smfs_internal.h" 
 struct sm_ops smfs_operations;
  
@@ -18,6 +20,8 @@ extern struct file_operations  smfs_file_fops;
 extern struct inode_operations smfs_sym_iops; 
 extern struct file_operations smfs_sym_fops;
 extern struct super_operations smfs_super_ops;
+extern struct journal_operations smfs_journal_ops;
+
 
 inline struct super_operations *cache_sops(struct sm_ops *smfs_ops)
 {
@@ -59,6 +63,11 @@ inline struct dentry_operations *cache_dops(struct sm_ops *smfs_ops)
 	return &smfs_ops->sm_dentry_ops;
 }
 
+inline struct journal_operations *journal_ops(struct sm_ops *smfs_ops)
+{
+	return &smfs_ops->sm_journal_ops;
+}
+
 void init_smfs_cache()
 {
 	memset(&smfs_operations, 0, sizeof(struct sm_ops)); 
@@ -359,3 +368,21 @@ void sm_set_sb_ops (struct super_block *cache_sb,
 	return;	
 }
 
+void setup_sm_journal_ops(char *cache_type)
+{
+	struct journal_operations *jops;
+
+	jops = journal_ops(&smfs_operations); 
+        
+	if (strlen(cache_type) == strlen("ext3") &&
+            memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
+#if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
+		memcpy(jops, &smfs_ext3_journal_ops, 
+		       sizeof(struct journal_operations)); 
+#else
+		memset(jops, 0, sizeof(journal_operations));
+#endif
+                CDEBUG(D_SUPER, "ops at %p\n", jops);
+        }
+}
+
diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c
index 58cf6e51ce..e7507a3be5 100644
--- a/lustre/smfs/dir.c
+++ b/lustre/smfs/dir.c
@@ -9,8 +9,11 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/unistd.h>
+#include <linux/lustre_idl.h> 
+#include <linux/smp_lock.h>
 
 #include "smfs_internal.h" 
+#include "kml_idl.h" 
 
 #define NAME_ALLOC_LEN(len)     ((len+16) & ~15)
                                                                                                                                                                                         
@@ -254,14 +257,22 @@ static int smfs_mkdir(struct inode * dir,
 	struct inode *inode = NULL;
 	struct dentry *cache_dentry;
 	struct dentry parent;
+	void   *handle;
 	int    rc = 0;
 
 	if (!cache_dir) 
 		RETURN(-ENOENT);
+
+	handle = smfs_trans_start(cache_dir, KML_OPCODE_MKDIR);
+	if (IS_ERR(handle) ) {
+                CERROR("smfs_do_mkdir: no space for transaction\n");
+        	RETURN(-ENOSPC);
+	}
 	
 	prepare_parent_dentry(&parent, cache_dir);
 	cache_dentry = d_alloc(&parent, &dentry->d_name);
-	
+
+	lock_kernel();	
 	if (cache_dir->i_op->mkdir)
 		rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode);
 
@@ -273,8 +284,15 @@ static int smfs_mkdir(struct inode * dir,
 		GOTO(exit, rc = -ENOENT);
  
 	d_instantiate(dentry, inode);	
+	/*Do KML post hook*/
+	if (smfs_do_kml(dir)) {
+		rc = post_kml_mkdir(dir, dentry);
+		GOTO(exit, rc);
+	}
 	duplicate_inode(cache_dir, dir);
 exit:
+	unlock_kernel();	
+	smfs_trans_commit(handle);
 	d_unalloc(cache_dentry);
 	RETURN(rc);		
 }
diff --git a/lustre/smfs/file.c b/lustre/smfs/file.c
index 62352351a5..aad7c327f7 100644
--- a/lustre/smfs/file.c
+++ b/lustre/smfs/file.c
@@ -11,6 +11,7 @@
 #include <linux/stat.h>
 #include <linux/unistd.h>
 #include <linux/pagemap.h>
+#include <linux/lustre_idl.h>
 #include "smfs_internal.h" 
         
 /* instantiate a file handle to the cache file */
diff --git a/lustre/smfs/inode.c b/lustre/smfs/inode.c
index e336451c24..8160d32e47 100644
--- a/lustre/smfs/inode.c
+++ b/lustre/smfs/inode.c
@@ -10,6 +10,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/lustre_idl.h>
 #include "smfs_internal.h" 
 
 void duplicate_inode(struct inode *cache_inode, struct inode *inode)
@@ -144,6 +145,7 @@ static void smfs_write_inode(struct inode *inode, int wait)
 	if (!cache_inode || !cache_sb)
 		return;
 		
+	duplicate_inode(inode, cache_inode); 
 	if (cache_sb->s_op->write_inode)
 		cache_sb->s_op->write_inode(cache_inode, wait);
 
diff --git a/lustre/smfs/journal.c b/lustre/smfs/journal.c
new file mode 100644
index 0000000000..715a61c6cc
--- /dev/null
+++ b/lustre/smfs/journal.c
@@ -0,0 +1,249 @@
+/*
+ *  smfs/inode.c
+ *
+ */
+
+#define DEBUG_SUBSYSTEM S_SM
+
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/lustre_idl.h>
+#include "kml_idl.h" 
+#include "smfs_internal.h" 
+extern struct sm_ops smfs_operations;
+
+#define size_round(x)  (((x)+3) & ~0x3)
+
+void *smfs_trans_start(struct inode *inode, int op)
+{
+
+	CDEBUG(D_INODE, "trans start %p\n", 
+	       smfs_operations.sm_journal_ops.tr_start);
+	if (smfs_operations.sm_journal_ops.tr_start) {
+		return smfs_operations.sm_journal_ops.tr_start(inode, op);	
+	}
+	return NULL;
+}
+
+void smfs_trans_commit(void *handle)
+{
+	if (smfs_operations.sm_journal_ops.tr_commit) {
+		smfs_operations.sm_journal_ops.tr_commit(handle);	
+	}
+	CDEBUG(D_SM, "trans commit %p\n", 
+	       smfs_operations.sm_journal_ops.tr_commit);
+}
+/*The following function are gotten from intermezzo
+ * smfs_path
+ * logit
+ * journal_log_prefix_with_groups_and_ids 
+ * journal_log_prefix 
+*/
+static char* smfs_path(struct dentry *dentry, struct dentry *root,
+                        char *buffer, int buflen)
+{
+        char * end = buffer+buflen;
+        char * retval;
+                                                                                                                                                                                                     
+        *--end = '\0';
+        buflen--;
+        if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
+                buflen -= 10;
+                end -= 10;
+                memcpy(end, " (deleted)", 10);
+        }
+                                                                                                                                                                                                     
+        /* Get '/' right */
+        retval = end-1;
+        *retval = '/';
+                                                                                                                                                                                                     
+        for (;;) {
+                struct dentry * parent;
+                int namelen;
+                                                                                                                                                                                                     
+                if (dentry == root)
+                        break;
+                parent = dentry->d_parent;
+                if (dentry == parent)
+                        break;
+                namelen = dentry->d_name.len;
+                buflen -= namelen + 1;
+                if (buflen < 0)
+                        break;
+                end -= namelen;
+                memcpy(end, dentry->d_name.name, namelen);
+                *--end = '/';
+                retval = end;
+                dentry = parent;
+        }
+        return retval;
+}
+                                                                                                                                                                                                     
+static inline char *logit(char *buf, const void *value, int size)
+{
+        char *ptr = (char *)value;
+                                                                                                                                                                                                     
+        memcpy(buf, ptr, size);
+        buf += size;
+        return buf;
+}
+static inline char *
+journal_log_prefix_with_groups_and_ids(char *buf, int opcode,
+                                       __u32 ngroups, gid_t *groups,
+                                       __u32 fsuid, __u32 fsgid)
+{
+        struct kml_prefix_hdr p;
+        u32 loggroups[NGROUPS_MAX];
+                                                                                                                                                                                                     
+        int i;
+                                                                                                                                                                                                     
+        p.version = KML_MAJOR_VERSION | KML_MINOR_VERSION;
+        p.pid = cpu_to_le32(current->pid);
+        p.auid = cpu_to_le32(current->uid);
+        p.fsuid = cpu_to_le32(fsuid);
+        p.fsgid = cpu_to_le32(fsgid);
+        p.ngroups = cpu_to_le32(ngroups);
+        p.opcode = cpu_to_le32(opcode);
+        for (i=0 ; i < ngroups ; i++)
+                loggroups[i] = cpu_to_le32((__u32) groups[i]);
+                                                                                                                                                                                                     
+        buf = logit(buf, &p, sizeof(struct kml_prefix_hdr));
+        buf = logit(buf, &loggroups, sizeof(__u32) * ngroups);
+        return buf;
+}
+                                                                                                                                                                                                     
+static inline char *
+journal_log_prefix(char *buf, int opcode)
+{
+        __u32 groups[NGROUPS_MAX];
+        int i;
+                                                                                                                                                                                                     
+        /* convert 16 bit gid's to 32 bit gid's */
+        for (i=0; i<current->ngroups; i++)
+                groups[i] = (__u32) current->groups[i];
+                                                                                                                                                                                                     
+        return journal_log_prefix_with_groups_and_ids(buf, opcode, 
+                                                      (__u32)current->ngroups,
+                                                      groups,
+                                                      (__u32)current->fsuid,
+                                                      (__u32)current->fsgid);
+}
+                                                                                                                                                                                                     
+static inline char *
+journal_log_prefix_with_groups(char *buf, int opcode, 
+                               __u32 ngroups, gid_t *groups)
+{
+        return journal_log_prefix_with_groups_and_ids(buf, opcode,
+                                                      ngroups, groups,
+                                                      (__u32)current->fsuid,
+                                                      (__u32)current->fsgid);
+}
+
+static inline char *log_dentry_version(char *buf, struct dentry *dentry)
+{
+        struct smfs_version version;
+                                                                                                                                                                                                     
+        smfs_getversion(&version, dentry->d_inode);
+                                                                                                                                                                                                     
+        version.sm_mtime = HTON__u64(version.sm_mtime);
+        version.sm_ctime = HTON__u64(version.sm_ctime);
+        version.sm_size = HTON__u64(version.sm_size);
+                                                                                                                                                                                                     
+        return logit(buf, &version, sizeof(version));
+}
+                                                                                                                                                                                                     
+static inline char *log_version(char *buf, struct smfs_version *pv)
+{
+        struct smfs_version version;
+                                                                                                                                                                                                     
+        memcpy(&version, pv, sizeof(version));
+                                                                                                                                                                                                     
+        version.sm_mtime = HTON__u64(version.sm_mtime);
+        version.sm_ctime = HTON__u64(version.sm_ctime);
+        version.sm_size = HTON__u64(version.sm_size);
+                                                                                                                                                                                                     
+        return logit(buf, &version, sizeof(version));
+}
+static inline char *journal_log_suffix(char *buf, char *log,
+                                       struct dentry *dentry)
+{
+        struct kml_suffix s;
+        struct kml_prefix_hdr *p = (struct kml_prefix_hdr *)log;
+                                                                                                                                                                                                     
+        s.prevrec = 0;
+                                                                                                                                                                                                     
+        /* record number needs to be filled in after reservation
+           s.recno = cpu_to_le32(rec->recno); */
+        s.time = cpu_to_le32(CURRENT_TIME);
+        s.len = p->len;
+        return logit(buf, &s, sizeof(s));
+}
+
+int smfs_kml_log(struct smfs_super_info *smfs_info,
+                 const char *buf, size_t size,
+                 const char *string1, int len1,
+                 const char *string2, int len2,
+                 const char *string3, int len3)
+{
+	int rc = 0;	
+	/*should pack the record and dispatch it
+	 *create llog handle write to the log*/
+	return rc;
+}
+
+int smfs_journal_mkdir(struct dentry *dentry,
+                       struct smfs_version *tgt_dir_ver,
+                       struct smfs_version *new_dir_ver, 
+		       int mode)
+{
+  	int opcode = KML_OPCODE_MKDIR;
+        char *buffer, *path, *logrecord, record[292];
+        struct dentry *root;
+        __u32 uid, gid, lmode, pathlen;
+	struct smfs_super_info *smfs_info; 	       
+        struct super_block* sb;
+        int error, size;
+ 
+	ENTRY;
+       
+	sb = dentry->d_inode->i_sb;
+	root = sb->s_root;
+	smfs_info = S2SMI(sb);
+	
+        uid = cpu_to_le32(dentry->d_inode->i_uid);
+        gid = cpu_to_le32(dentry->d_inode->i_gid);
+        lmode = cpu_to_le32(mode);
+                                                                                                                                                                                                     
+        SM_ALLOC(buffer, PAGE_SIZE);
+        path = smfs_path(dentry, root, buffer, PAGE_SIZE);
+        pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
+        size = sizeof(__u32) * current->ngroups +
+               sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
+               sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
+               sizeof(struct kml_suffix);
+                                                                                                                                                                                                     
+        if ( size > sizeof(record) )
+                CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
+                                                                                                                                                                                                     
+        logrecord = journal_log_prefix(record, opcode);
+                                                                                                                                                                                                     
+        logrecord = log_version(logrecord, tgt_dir_ver);
+        logrecord = log_dentry_version(logrecord, dentry->d_parent);
+        logrecord = log_version(logrecord, new_dir_ver);
+        logrecord = logit(logrecord, &lmode, sizeof(lmode));
+        logrecord = logit(logrecord, &uid, sizeof(uid));
+        logrecord = logit(logrecord, &gid, sizeof(gid));
+        logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
+        logrecord = journal_log_suffix(logrecord, record, dentry);
+                                                                                                                                                                                                     
+        error = smfs_kml_log(smfs_info, record, size,
+                         path, size_round(le32_to_cpu(pathlen)),
+                         NULL, 0, NULL, 0);
+	SM_FREE(buffer, PAGE_SIZE);
+	RETURN(error);
+}
diff --git a/lustre/smfs/journal_ext3.c b/lustre/smfs/journal_ext3.c
new file mode 100644
index 0000000000..c54effea43
--- /dev/null
+++ b/lustre/smfs/journal_ext3.c
@@ -0,0 +1,96 @@
+/*
+ *  smfs/journal_ext3.c
+ *
+ */
+
+#define DEBUG_SUBSYSTEM S_SM
+
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/lustre_idl.h>
+#if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/ext3_jbd.h>
+#endif
+                                                                                                                                                                                                     
+#include "smfs_internal.h" 
+#include "kml_idl.h" 
+                                                                                                                                                                                                     
+#if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
+
+#define MAX_PATH_BLOCKS(inode) (PATH_MAX >> EXT3_BLOCK_SIZE_BITS((inode)->i_sb))
+#define MAX_NAME_BLOCKS(inode) (NAME_MAX >> EXT3_BLOCK_SIZE_BITS((inode)->i_sb))
+
+static void *smfs_e3_trans_start(struct inode *inode, 
+				int op)
+{
+        
+	int trunc_blks, one_path_blks, extra_path_blks;
+        int extra_name_blks, lml_blks, jblocks;
+        __u32 avail_kmlblocks;
+	handle_t *handle;
+	
+	avail_kmlblocks = inode->i_sb->u.ext3_sb.s_es->s_free_blocks_count;
+                                                                                                                                                                                                     
+        if ( avail_kmlblocks < 3 ) {
+                return ERR_PTR(-ENOSPC);
+        }
+                                                                                                                                                                                                     
+        if ((op != KML_OPCODE_UNLINK && op != KML_OPCODE_RMDIR)
+             && avail_kmlblocks < 6 ) {
+                return ERR_PTR(-ENOSPC);
+        }
+        /* Need journal space for:
+             at least three writes to KML (two one block writes, one a path)
+             possibly a second name (unlink, rmdir)
+             possibly a second path (symlink, rename)
+             a one block write to the last rcvd file
+        */
+                                                                                                                                                                                                     
+        trunc_blks = EXT3_DATA_TRANS_BLOCKS + 1;
+        one_path_blks = 4*EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode) + 3;
+        lml_blks = 4*EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode) + 2;
+        extra_path_blks = EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode);
+        extra_name_blks = EXT3_DATA_TRANS_BLOCKS + MAX_NAME_BLOCKS(inode);
+                                                                                                                                                                                                     
+        /* additional blocks appear for "two pathname" operations
+           and operations involving the LML records
+        */
+
+	switch (op) {
+	case KML_OPCODE_MKDIR:
+		jblocks = one_path_blks + trunc_blks
+                          + EXT3_DATA_TRANS_BLOCKS + 4 + 2;
+		break;
+	default:
+		CDEBUG(D_INODE, "invalid operation %d for journal\n", op);
+		return NULL;
+	}
+
+	CDEBUG(D_INODE, "creating journal handle (%d blocks)\n", jblocks);
+        
+	lock_kernel();
+        handle = journal_start(EXT3_JOURNAL(inode), jblocks);
+        unlock_kernel();
+
+	return handle;
+}  
+
+static void smfs_e3_trans_commit(void *handle)
+{
+        lock_kernel();
+        journal_stop(handle);
+        unlock_kernel();
+}
+
+struct journal_operations smfs_ext3_journal_ops = {
+        .tr_start   = smfs_e3_trans_start, 
+        .tr_commit  = smfs_e3_trans_commit,
+};
+#endif
+
diff --git a/lustre/smfs/kml.c b/lustre/smfs/kml.c
new file mode 100644
index 0000000000..4151fdac74
--- /dev/null
+++ b/lustre/smfs/kml.c
@@ -0,0 +1,59 @@
+/*
+ *  smfs/kml.c
+ *
+ */
+
+#define DEBUG_SUBSYSTEM S_SM
+
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/lustre_idl.h>
+#include "smfs_internal.h" 
+#include "kml_idl.h"
+
+/*FIXME there should be more conditions in this check*/
+int smfs_do_kml(struct inode *dir)
+{
+	struct smfs_super_info	*smfs_info = S2SMI(dir->i_sb);	
+		
+	if (smfs_info->flags & SM_DO_KML) {
+		return 1;
+	}
+	return 0;
+}
+void smfs_getversion(struct smfs_version * smfs_version,
+                           struct inode * inode) 
+{
+	smfs_version->sm_mtime = (__u64)inode->i_mtime;
+        smfs_version->sm_ctime = (__u64)inode->i_ctime;
+        smfs_version->sm_size  = (__u64)inode->i_size;
+}
+
+int smfs_kml_init(struct super_block *sb)
+{
+	struct smfs_super_info	*smfs_info = S2SMI(sb);	
+	int    rc = 0;
+	smfs_info->flags |= SM_DO_KML;
+
+	rc = smfs_llog_setup(&smfs_info->kml_llog);			
+
+	RETURN(rc);
+}
+
+int post_kml_mkdir(struct inode *dir, struct dentry *dentry)
+{
+	struct smfs_version tgt_dir_ver, new_dir_ver;
+	int    error;
+
+	smfs_getversion(&tgt_dir_ver, dir); 	
+
+	smfs_getversion(&new_dir_ver, dentry->d_inode); 	
+	
+	error = smfs_journal_mkdir(dentry, &tgt_dir_ver,
+			           &new_dir_ver,
+                                   dentry->d_inode->i_mode);
+	return error;	                                                                                                                                                                                                     
+}
+
diff --git a/lustre/smfs/kml_idl.h b/lustre/smfs/kml_idl.h
new file mode 100644
index 0000000000..a470bb708a
--- /dev/null
+++ b/lustre/smfs/kml_idl.h
@@ -0,0 +1,52 @@
+/*
+ * smfs/kml_idl.h
+ */
+
+# define MYPATHLEN(buffer, path) ((buffer) + PAGE_SIZE - (path))
+/*Got these defines from intermezzo*/
+struct kml_log_fd {
+	rwlock_t         fd_lock;
+        loff_t           fd_offset;  /* offset where next record should go */
+        struct file      *fd_file;
+        int              fd_truncating;
+        unsigned int     fd_recno;   /* last recno written */
+        struct list_head fd_reservations;
+};
+
+#define KML_MAJOR_VERSION 0x00010000
+#define KML_MINOR_VERSION 0x00000002
+#define KML_OPCODE_NOOP          0
+#define KML_OPCODE_CREATE        1
+#define KML_OPCODE_MKDIR         2
+#define KML_OPCODE_UNLINK        3
+#define KML_OPCODE_RMDIR         4
+#define KML_OPCODE_CLOSE         5
+#define KML_OPCODE_SYMLINK       6
+#define KML_OPCODE_RENAME        7
+#define KML_OPCODE_SETATTR       8
+#define KML_OPCODE_LINK          9
+#define KML_OPCODE_OPEN          10
+#define KML_OPCODE_MKNOD         11
+#define KML_OPCODE_WRITE         12
+#define KML_OPCODE_RELEASE       13
+#define KML_OPCODE_TRUNC         14
+#define KML_OPCODE_SETEXTATTR    15
+#define KML_OPCODE_DELEXTATTR    16
+#define KML_OPCODE_KML_TRUNC     17
+#define KML_OPCODE_GET_FILEID    18
+#define KML_OPCODE_NUM           19
+                                                                                                                                                                                                     
+#ifdef __KERNEL__
+# define NTOH__u32(var) le32_to_cpu(var)
+# define NTOH__u64(var) le64_to_cpu(var)
+# define HTON__u32(var) cpu_to_le32(var)
+# define HTON__u64(var) cpu_to_le64(var)
+#else
+# include <glib.h>
+# define NTOH__u32(var) GUINT32_FROM_LE(var)
+# define NTOH__u64(var) GUINT64_FROM_LE(var)
+# define HTON__u32(var) GUINT32_TO_LE(var)
+# define HTON__u64(var) GUINT64_TO_LE(var)
+#endif
+                                                                                                                                                                                                     
+
diff --git a/lustre/smfs/options.c b/lustre/smfs/options.c
index 19dbe8c38d..8ff445eafe 100644
--- a/lustre/smfs/options.c
+++ b/lustre/smfs/options.c
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/lustre_idl.h>
 #include "smfs_internal.h" 
 
 
@@ -37,56 +38,60 @@ void cleanup_option(void)
 		option = list_entry(option_list.next, struct option, list);
 		list_del(&option->list);
 		SM_FREE(option->opt, strlen(option->opt) + 1);
-		SM_FREE(option->value, strlen(option->value) + 1);
+		if (option->value)
+			SM_FREE(option->value, strlen(option->value) + 1);
 		SM_FREE(option, sizeof(struct option));
 	}
 	SM_FREE(options, strlen(options) + 1);
 }
 int get_opt(struct option **option, char **pos)
 {
-	char  *name, *value, *left;
+	char  *name, *value, *left, *tmp;
 	struct option *tmp_opt;
-	int  length;
+	int  length = 0;
 
 	*pos = opt_left;
 
 	if (! *opt_left)
 		return -ENODATA;
-
-	left = strchr(opt_left, '=');
-
-	if (left == opt_left || !left) 
+	left = strchr(opt_left, ',');
+	if (left == opt_left) 
 		return -EINVAL;
+	if (!left){
+		left = opt_left + strlen(opt_left);	
+	}	
 
 	SM_ALLOC(tmp_opt, sizeof(struct option));   	
-		
-	length = left - opt_left + 1;
-	SM_ALLOC(name, length);
-	tmp_opt->opt = name;
-	memset(name, 0, length);
-	while (opt_left != left) *name++ = *opt_left++;
+	tmp_opt->opt = NULL;
+	tmp_opt->value = NULL;
 
-	opt_left ++; /*after '='*/
+	tmp = opt_left;
+	while(tmp != left && *tmp != '=') {
+		length++;
+		tmp++;
+	}	
+	SM_ALLOC(name, length + 1);
+	tmp_opt->opt = name;
+	memset(name, 0, length + 1);
+	while (opt_left != tmp) *name++ = *opt_left++;
 
-	left = strchr(opt_left, ',');
-	if (left == opt_left) {
-		SM_FREE(tmp_opt->opt, length);
-		SM_FREE(tmp_opt, sizeof(struct option));
-		opt_left = *pos;
-		return -EINVAL;
+	if (*tmp == '=') {
+		/*this option has value*/
+		opt_left ++; /*after '='*/
+		if (left == opt_left) {
+			SM_FREE(tmp_opt->opt, length);
+			SM_FREE(tmp_opt, sizeof(struct option));
+			opt_left = *pos;
+			return -EINVAL;
+		}
+		length = left - opt_left + 1;
+		SM_ALLOC(value, length);
+		tmp_opt->value = value;
+		memset(value, 0, length);
+		while (opt_left != left) *value++ = *opt_left++;
 	}
-	if (!left) 
-		left = opt_left + strlen(opt_left); 
-	length = left - opt_left + 1;
-	SM_ALLOC(value, length);
-	tmp_opt->value = value;
-	memset(value, 0, length);
-	while (opt_left != left) *value++ = *opt_left++;
-
 	list_add(&tmp_opt->list, &option_list);
-	
 	if (*opt_left == ',') opt_left ++; /*after ','*/	
-
 	*option = tmp_opt;
 	return 0;
 }
diff --git a/lustre/smfs/reint.c b/lustre/smfs/reint.c
new file mode 100644
index 0000000000..50420d72f3
--- /dev/null
+++ b/lustre/smfs/reint.c
@@ -0,0 +1,15 @@
+/*
+ *  smfs/kml.c
+ *
+ */
+
+#define DEBUG_SUBSYSTEM S_SM
+
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/lustre_idl.h> 
+#include "smfs_internal.h" 
+
diff --git a/lustre/smfs/sm_fs.c b/lustre/smfs/sm_fs.c
index d83c6f4a2a..d07facb353 100644
--- a/lustre/smfs/sm_fs.c
+++ b/lustre/smfs/sm_fs.c
@@ -14,7 +14,7 @@
 #include <linux/stat.h>
 #include <linux/unistd.h>
 #include <linux/miscdevice.h>
-                                                                                                                                                                                                     
+#include <linux/lustre_idl.h>                                                                                                                                                                                                     
 #include "smfs_internal.h" 
 
 int sm_stack = 0;
diff --git a/lustre/smfs/smfs_internal.h b/lustre/smfs/smfs_internal.h
index 2ab1e8f577..3142babc86 100644
--- a/lustre/smfs/smfs_internal.h
+++ b/lustre/smfs/smfs_internal.h
@@ -7,7 +7,9 @@ struct smfs_inode_info {
 
 struct smfs_super_info {
 	struct super_block *smsi_sb;
-        struct vfsmount *smsi_mnt;      /* mount the cache kere with kern_do_mount (like MDS) */
+        struct vfsmount *smsi_mnt;      /* mount the cache kern with kern_do_mount (like MDS) */
+	__u32 flags;			/* flags*/
+	struct llog_ctxt *kml_llog;	/*smfs kml llog*/ 
 	int ops_check;
 };
 
@@ -24,7 +26,15 @@ struct smfs_super_info {
 #define SYMLINK_OPS_CHECK 	0x20 
 #define DIR_OPS_CHECK 		0x40 
 
+#define SM_DO_KML		0x1
+ 
 #include "smfs_support.h"
+
+struct journal_operations {
+        void *(*tr_start)(struct inode *, int op);
+        void (*tr_commit)(void *handle);
+};
+
 struct sm_ops {
         /* operations on the file store */
         struct super_operations sm_sb_ops;
@@ -38,8 +48,9 @@ struct sm_ops {
         struct file_operations sm_sym_fops;
                                                                                                                                                                                                      
         struct dentry_operations sm_dentry_ops;
-};
+	struct journal_operations sm_journal_ops;
 
+};
 struct option {
 	char *opt;
 	char *value;
@@ -56,6 +67,7 @@ void sm_set_inode_ops(struct inode *cache_inode, struct inode *inode);
 void sm_set_sb_ops(struct super_block *cache_sb, struct super_block *sb);
 void init_smfs_cache(void);
 void cleanup_smfs_cache(void);
+void setup_sm_journal_ops(char * cache_type);
 /*super.c*/
 extern int init_smfs(void);
 extern int cleanup_smfs(void);
@@ -90,4 +102,20 @@ extern int smfs_getxattr(struct dentry *dentry, const char *name,
 extern ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
 extern int smfs_removexattr(struct dentry *dentry, const char *name);
 extern void smfs_update_file(struct file *file, struct file *cache_file);
+/*journal.c */
+extern void *smfs_trans_start(struct inode *inode, int op);
+extern void smfs_trans_commit(void *handle);
+extern int smfs_journal_mkdir(struct dentry *dentry,
+                       struct smfs_version *tgt_dir_ver,
+                       struct smfs_version *new_dir_ver, 
+		       int mode);
+/*journal_ext3.c*/
+extern struct journal_operations smfs_ext3_journal_ops;
+/*kml.c*/
+extern int smfs_kml_init(struct super_block *sb);
+extern int smfs_do_kml(struct inode *dir);
+extern void smfs_getversion(struct smfs_version * smfs_version, struct inode * inode); 
+extern int post_kml_mkdir(struct inode *dir, struct dentry *dentry);
+/*smfs_llog.c*/
+extern int smfs_llog_setup(struct llog_ctxt **ctxt);
 #endif /* __LINUX_SMFS_H */
diff --git a/lustre/smfs/smfs_llog.c b/lustre/smfs/smfs_llog.c
new file mode 100644
index 0000000000..a661e56df8
--- /dev/null
+++ b/lustre/smfs/smfs_llog.c
@@ -0,0 +1,27 @@
+/*
+ * llog.c
+ */
+#define DEBUG_SUBSYSTEM S_SM
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/lustre_idl.h> 
+
+#include "smfs_internal.h"
+
+int smfs_llog_setup(struct llog_ctxt **p_ctxt)
+{
+	int rc = 0;
+    
+        RETURN(rc);
+}	
+
+
+
+
+
+
diff --git a/lustre/smfs/super.c b/lustre/smfs/super.c
index be0e7452b2..bfa42471db 100644
--- a/lustre/smfs/super.c
+++ b/lustre/smfs/super.c
@@ -22,12 +22,13 @@
 #include <linux/slab.h>
 #include <linux/loop.h>
 #include <linux/errno.h>
+#include <linux/lustre_idl.h>
 #include "smfs_internal.h" 
 
 /* Find the options for the clone. These consist of a cache device
    and an index in the snaptable associated with that device. 
 */
-static char *smfs_options(char *options, char **devstr, char **namestr)
+static char *smfs_options(char *options, char **devstr, char **namestr, int *kml)
 {
 	struct option *opt_value = NULL;
 	char *pos;
@@ -39,6 +40,8 @@ static char *smfs_options(char *options, char **devstr, char **namestr)
 		} else if (!strcmp(opt_value->opt, "type")) {
 			if (namestr != NULL)
 				*namestr = opt_value->value;
+		} else if (!strcmp(opt_value->opt, "kml")) {
+			*kml = 1;	
 		} else {
 			break;
 		}
@@ -253,7 +256,7 @@ smfs_read_super(
 	char *devstr = NULL, *typestr = NULL;
 	char *cache_data;
 	ino_t root_ino;
-	int err = 0;
+	int err = 0, kml = 0;
 
 	ENTRY;
 
@@ -261,7 +264,7 @@ smfs_read_super(
 	
 	init_option(data);
 	/* read and validate options */
-	cache_data = smfs_options(data, &devstr, &typestr);
+	cache_data = smfs_options(data, &devstr, &typestr, &kml);
 	if (*cache_data) {
 		CERROR("invalid mount option %s\n", (char*)data);
 		GOTO(out_err, err=-EINVAL);
@@ -276,6 +279,11 @@ smfs_read_super(
 		CERROR("Can not mount %s as %s\n", devstr, typestr);
 		GOTO(out_err, 0);
 	}
+	
+	if (kml) smfs_kml_init(sb);	
+	
+	setup_sm_journal_ops(typestr);
+	
 	dget(S2CSB(sb)->s_root);
 	root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
 	root_inode = iget(sb, root_ino);
diff --git a/lustre/smfs/symlink.c b/lustre/smfs/symlink.c
index d424d938ac..b0b3714e4b 100644
--- a/lustre/smfs/symlink.c
+++ b/lustre/smfs/symlink.c
@@ -10,6 +10,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/lustre_idl.h>
 
 #include "smfs_internal.h" 
 
diff --git a/lustre/smfs/sysctl.c b/lustre/smfs/sysctl.c
index 6ec1f9b260..785b3dd930 100644
--- a/lustre/smfs/sysctl.c
+++ b/lustre/smfs/sysctl.c
@@ -14,7 +14,7 @@
 #include <linux/string.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
-
+#include <linux/lustre_idl.h>
 #include "smfs_internal.h" 
 
 
-- 
GitLab