diff -ru V7EM/h/param.h V7JEM/h/param.h
--- V7EM/h/param.h	Tue Jan 29 18:15:02 2002
+++ V7JEM/h/param.h	Sun Mar  3 01:43:53 2002
@@ -2,6 +2,8 @@
  * tunable variables
  */
 
+#define JOURNALING
+
 #define	NBUF	29		/* size of buffer cache */
 #define	NINODE	200		/* number of in core inodes */
 #define	NFILE	175		/* number of in core file structures */
diff -ru V7EM/h/trans.h V7JEM/h/trans.h
--- V7EM/h/trans.h	Sun Mar  3 03:37:45 2002
+++ V7JEM/h/trans.h	Sun Mar  3 04:18:56 2002
@@ -0,0 +1,20 @@
+
+struct trans {
+	int t_gen;	/* generation no : for test */
+	int t_opcount;	/* op serial : for test */
+};
+
+#define TOP_USED	1
+#define TOP_SUPER	2
+#define TOP_FREE	3
+#define TOP_INODE	4
+#define TOP_ILIST	5
+#define TOP_FDATA	6
+
+
+/* u.u_tflag */
+#define TRANS_FILEDATA	1
+
+struct trans * trans_get();
+void trans_add(struct trans *tp,struct buf *bp,int op,int from,int to);
+void trans_put(struct trans *tp);
diff -ru V7EM/h/user.h V7JEM/h/user.h
--- V7EM/h/user.h	Mon Jan 28 07:02:49 2002
+++ V7JEM/h/user.h	Sun Mar  3 04:05:07 2002
@@ -94,6 +94,8 @@
 					 * extends from u + USIZE*64
 					 * backward not to reach here
 					 */
+	struct trans *u_tp;		/* transaction pointer */
+	int    u_tflag;			/* transaction option */
 };
 
 #define r_val1	u_rv.ur_val1
diff -ru V7EM/sys/Makefile V7JEM/sys/Makefile
--- V7EM/sys/Makefile	Tue Jan 29 19:04:01 2002
+++ V7JEM/sys/Makefile	Sun Mar  3 01:02:35 2002
@@ -2,7 +2,8 @@
 CFLAGS=-O -g -traditional -DFSEM
 
 SRCS= alloc.c bio.c fio.c iget.c nami.c pipe.c rdwri.c \
-setup.c subr.c c.c prf.c sys2.c sys3.c sys4.c mkdir.c rmdir.c pwd.c em.c 
+setup.c subr.c c.c prf.c sys2.c sys3.c sys4.c mkdir.c rmdir.c pwd.c em.c \
+trans.c
 
 OBJS=$(SRCS:.c=.o)
 
diff -ru V7EM/sys/alloc.c V7JEM/sys/alloc.c
--- V7EM/sys/alloc.c	Tue Jan 29 18:01:20 2002
+++ V7JEM/sys/alloc.c	Sun Mar  3 03:12:11 2002
@@ -9,6 +9,7 @@
 #include "../h/ino.h"
 #include "../h/dir.h"
 #include "../h/user.h"
+#include "../h/trans.h"
 typedef	struct fblk *FBLKP;
 
 /*
@@ -114,7 +115,12 @@
 			}
 		}
 		fp->s_nfree = 0;
+#ifdef JOURNALING
+		trans_add(u.u_tp,bp,TOP_FREE,0,sizeof(fp->s_free));
+		bdwrite(bp);
+#else
 		bwrite(bp);
+#endif
 		fp->s_flock = 0;
 		wakeup((caddr_t)&fp->s_flock);
 	}
diff -ru V7EM/sys/iget.c V7JEM/sys/iget.c
--- V7EM/sys/iget.c	Tue Jan 29 16:03:04 2002
+++ V7JEM/sys/iget.c	Sun Mar  3 02:41:48 2002
@@ -8,6 +8,7 @@
 #include "../h/filsys.h"
 #include "../h/conf.h"
 #include "../h/buf.h"
+#include "../h/trans.h"
 
 /*
  * Look up an inode by device,inumber.
@@ -217,6 +218,11 @@
 			CONV_TO_DISKORDER4(&(dp->di_ctime));
 		}
 		ip->i_flag &= ~(IUPD|IACC|ICHG);
+#ifdef JOURNALING
+		trans_add(u.u_tp, bp, TOP_INODE
+			, itoo(ip->i_number)*sizeof(struct dinode)
+			, (itoo(ip->i_number)+1)*sizeof(struct dinode));
+#endif
 		bdwrite(bp);
 	}
 }
diff -ru V7EM/sys/mkdir.c V7JEM/sys/mkdir.c
--- V7EM/sys/mkdir.c	Tue Jan 29 14:01:11 2002
+++ V7JEM/sys/mkdir.c	Sun Mar  3 04:23:42 2002
@@ -11,6 +11,7 @@
 #include "../h/file.h"
 #include "../h/conf.h"
 #include "../h/stat.h"
+#include "../h/trans.h"
 /*
 ** make directory
 */
@@ -42,17 +43,22 @@
 	__v7_chown(d, __v7_getuid(), __v7_getgid());
 	strcpy(dname, d);
 	strcat(dname, "/.");
+	u.u_tp = trans_get();
 	if((__v7_link(d, dname)) < 0) {
-		printf("mkdir: cannot link %s\n", dname);
 		__v7_unlink(d);
+		trans_put(u.u_tp); u.u_tp = NULL;
+		printf("mkdir: cannot link %s\n", dname);
 		return -u.u_error;
 	}
 	strcat(dname, ".");
 	if((__v7_link(pname, dname)) < 0) {
-		printf("mkdir: cannot link %s\n",dname);
 		dname[strlen(dname)] = '\0';
 		__v7_unlink(dname);
 		__v7_unlink(d);
+		trans_put(u.u_tp); u.u_tp = NULL;
+		printf("mkdir: cannot link %s\n",dname);
+		return -u.u_error;
 	}
+	trans_put(u.u_tp); u.u_tp = NULL;
 	return -u.u_error;
 }
diff -ru V7EM/sys/rdwri.c V7JEM/sys/rdwri.c
--- V7EM/sys/rdwri.c	Tue Jan 29 14:01:11 2002
+++ V7JEM/sys/rdwri.c	Sun Mar  3 04:11:01 2002
@@ -5,6 +5,7 @@
 #include "../h/user.h"
 #include "../h/buf.h"
 #include "../h/conf.h"
+#include "../h/trans.h"
 
 /*
  * Read the file corresponding to
@@ -120,8 +121,13 @@
 		iomove(bp->b_un.b_addr+on, n, B_WRITE);
 		if(u.u_error != 0)
 			brelse(bp);
-		else
+		else {
+#ifdef JOURNALING
+			if (u.u_tflag & TRANS_FILEDATA)
+				trans_add(u.u_tp, bp, TOP_FDATA, on , on + n);
+#endif
 			bdwrite(bp);
+		}
 		if(u.u_offset > ip->i_size &&
 		   (type==IFDIR || type==IFREG))
 			ip->i_size = u.u_offset;
diff -ru V7EM/sys/rmdir.c V7JEM/sys/rmdir.c
--- V7EM/sys/rmdir.c	Tue Jan 29 14:01:11 2002
+++ V7JEM/sys/rmdir.c	Sun Mar  3 04:18:16 2002
@@ -11,6 +11,7 @@
 #include "../h/file.h"
 #include "../h/conf.h"
 #include "../h/stat.h"
+#include "../h/trans.h"
 
 /*
  * Remove directory
@@ -28,6 +29,7 @@
 	char	*np, name[500];
 	struct	stat	st, cst;
 	struct	direct	dir;
+	int ret;
 
 	strcpy(name, d);
 	if((np = rindex(name, '/')) == NULL)
@@ -75,20 +77,30 @@
 		goto unl;
 	}
 	strcat(name, ".");
-	if((__v7_access(name, 0)) < 0)		/* name/.. non-existent */
+	if((__v7_access(name, 0)) < 0) {	/* name/.. non-existent */
+#ifdef JOURNALING
+		u.u_tp = trans_get();
+#endif
 		goto unl2;
+	}
 	if(__v7_access(name, 02)) {
 		name[strlen(name)-3] = '\0';
 		printf("rmdir: %s: no permission\n", name);
 		return -u.u_error;
 	}
+#ifdef JOURNALING
+	u.u_tp = trans_get();
+#endif
 unl:
 	__v7_unlink(name);	/* unlink name/.. */
 unl2:
 	name[strlen(name)-1] = '\0';
 	__v7_unlink(name);	/* unlink name/.  */
 	name[strlen(name)-2] = '\0';
-	if (__v7_unlink(name) < 0) {
+	ret = __v7_unlink(name);
+	trans_put(u.u_tp);
+	u.u_tp = NULL;
+	if (ret < 0) {
 		printf("rmdir: %s not removed\n", name);
 	}
 	return -u.u_error;
diff -ru V7EM/sys/subr.c V7JEM/sys/subr.c
--- V7EM/sys/subr.c	Tue Jan 29 17:53:45 2002
+++ V7JEM/sys/subr.c	Sun Mar  3 04:38:00 2002
@@ -5,6 +5,7 @@
 #include "../h/dir.h"
 #include "../h/user.h"
 #include "../h/buf.h"
+#include "../h/trans.h"
 
 /*
  * Bmap defines the structure of file system storage
@@ -42,9 +43,16 @@
 			if(rwflg==B_READ || (bp = alloc(dev))==NULL)
 				return((daddr_t)-1);
 			nb = bp->b_blkno;
+#ifdef JOURNALING
+			if (!(u.u_tflag & TRANS_FILEDATA))
+				trans_add(u.u_tp, bp, TOP_USED, 0, 0);
+#endif
 			bdwrite(bp);
 			ip->i_un.i_addr[i] = nb;
 			ip->i_flag |= IUPD|ICHG;
+#ifdef JOURNALING
+			iupdat(ip, &time, &time);
+#endif
 		}
 		if(i < NADDR-4)
 			rablock = ip->i_un.i_addr[i+1];
@@ -83,6 +91,9 @@
 		bdwrite(bp);
 		ip->i_un.i_addr[NADDR-j] = nb;
 		ip->i_flag |= IUPD|ICHG;
+#ifdef JOURNALING
+		iupdat(ip, &time, &time);
+#endif
 	}
 
 	/*
@@ -105,9 +116,16 @@
 				return((daddr_t)-1);
 			}
 			nb = nbp->b_blkno;
+#ifdef JOURNALING
+			if (j==3 && !(u.u_tflag & TRANS_FILEDATA))
+				trans_add(u.u_tp, nbp, TOP_USED, 0, 0);
+#endif
 			bdwrite(nbp);
 			bap[i] = nb;
 			CONV_TO_DISKORDER4(bap+i);
+#ifdef JOURNALING
+			trans_add(u.u_tp, bp, TOP_ILIST, sizeof(daddr_t)*i,sizeof(daddr_t)*(i+1));
+#endif
 			bdwrite(bp);
 		} else
 			brelse(bp);
diff -ru V7EM/sys/sys2.c V7JEM/sys/sys2.c
--- V7EM/sys/sys2.c	Tue Jan 29 17:28:58 2002
+++ V7JEM/sys/sys2.c	Sun Mar  3 04:24:47 2002
@@ -5,6 +5,7 @@
 #include "../h/reg.h"
 #include "../h/file.h"
 #include "../h/inode.h"
+#include "../h/trans.h"
 
 /*
  * read system call
@@ -253,7 +254,9 @@
 		u.u_error = EXDEV;
 		goto out;
 	}
+	u.u_tflag |= TRANS_FILEDATA;
 	wdir(ip);
+	u.u_tflag &= ~TRANS_FILEDATA;
 	if (u.u_error==0) {
 		ip->i_nlink++;
 		ip->i_flag |= ICHG;
diff -ru V7EM/sys/sys4.c V7JEM/sys/sys4.c
--- V7EM/sys/sys4.c	Tue Jan 29 18:16:03 2002
+++ V7JEM/sys/sys4.c	Sun Mar  3 04:25:37 2002
@@ -6,6 +6,7 @@
 #include "../h/inode.h"
 #include "../h/proc.h"
 #include "../h/timeb.h"
+#include "../h/trans.h"
 
 /*
  * Everything in this file is a routine implementing a system call.
@@ -102,7 +103,9 @@
 	u.u_base = (caddr_t)&u.u_dent;
 	u.u_count = sizeof(struct direct);
 	u.u_dent.d_ino = 0;
+	u.u_tflag |= TRANS_FILEDATA;
 	writei(pp);
+	u.u_tflag &= ~TRANS_FILEDATA;
 	ip->i_nlink--;
 	ip->i_flag |= ICHG;
 
diff -ru V7EM/sys/trans.c V7JEM/sys/trans.c
--- V7EM/sys/trans.c	Sun Mar  3 03:37:48 2002
+++ V7JEM/sys/trans.c	Sun Mar  3 04:11:30 2002
@@ -0,0 +1,66 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/seg.h"
+#include "../h/buf.h"
+#include "../h/conf.h"
+#include "../h/trans.h"
+
+struct trans * trans_get();
+void trans_add(struct trans *tp,struct buf *bp,int op,int from,int to);
+void trans_put(struct trans *tp);
+
+static int gen=1;
+
+extern void *kmemalloc(int size);
+extern void kmemfree(void *p,int size);
+
+struct trans * trans_get() {
+	struct trans *tp;
+	tp = kmemalloc(sizeof(struct trans));
+	tp->t_gen = gen++;
+	tp->t_opcount = 0;
+	return tp;
+}
+
+void trans_put(struct trans *tp) {
+	kmemfree(tp, sizeof(struct trans));
+}
+
+void trans_add(struct trans *tp,struct buf *bp,int op,int from,int to) {
+	if (!tp) {
+printf("%s: bno = %d %d - %d\n"
+	, (op == TOP_USED)?"TOP_USED"
+	 :(op == TOP_SUPER)?"TOP_SUPER"
+	 :(op == TOP_FREE)?"TOP_FREE"
+	 :(op == TOP_INODE)?"TOP_INODE"
+	 :(op == TOP_FDATA)?"TOP_FDATA"
+	 :"TOP_ERROR"
+	,bp->b_blkno,from,to);
+	return;
+	}
+	tp->t_opcount ++;
+printf("%s: %d %d bno = %d %d - %d\n"
+	, (op == TOP_USED)?"TOP_USED"
+	 :(op == TOP_SUPER)?"TOP_SUPER"
+	 :(op == TOP_FREE)?"TOP_FREE"
+	 :(op == TOP_INODE)?"TOP_INODE"
+	 :(op == TOP_ILIST)?"TOP_ILIST"
+	 :(op == TOP_FDATA)?"TOP_FDATA"
+	 :"TOP_ERROR"
+	,tp->t_gen,tp->t_opcount,bp->b_blkno,from,to);
+}
+
+
+#undef free
+#undef malloc
+
+void *kmemalloc(int size) {
+	extern void *malloc();
+	return malloc(size);
+}
+
+void kmemfree(void *p, int size) {
+	free(p);
+}
+
+
