Journaling layer work. Generate output for path names, creds, and vattr,
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 28 Feb 2005 17:41:00 +0000 (17:41 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 28 Feb 2005 17:41:00 +0000 (17:41 +0000)
for all major modifying VFS operations.  Start working on a vnode
identification and uio abstraction.

sys/kern/vfs_jops.c
sys/kern/vfs_journal.c
sys/sys/journal.h [copied from sys/sys/mountctl.h with 78% similarity]
sys/sys/mountctl.h

index e2a1d93..e9ff430 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/vfs_jops.c,v 1.6 2005/01/09 03:04:51 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_jops.c,v 1.7 2005/02/28 17:41:00 dillon Exp $
  */
 /*
  * Each mount point may have zero or more independantly configured journals
@@ -84,7 +84,9 @@
 #include <sys/vnode.h>
 #include <sys/poll.h>
 #include <sys/mountctl.h>
+#include <sys/journal.h>
 #include <sys/file.h>
+#include <sys/proc.h>
 
 #include <machine/limits.h>
 
@@ -132,11 +134,6 @@ static struct journal_subrecord *jrecord_write(struct jrecord *jrec,
 static void jrecord_data(struct jrecord *jrec, const void *buf, int bytes);
 static void jrecord_done(struct jrecord *jrec, int abortit);
 
-static void jrecord_write_path(struct jrecord *jrec, 
-                           int16_t rectype, struct namecache *ncp);
-static void jrecord_write_vattr(struct jrecord *jrec, struct vattr *vat);
-
-
 static int journal_setattr(struct vop_setattr_args *ap);
 static int journal_write(struct vop_write_args *ap);
 static int journal_fsync(struct vop_fsync_args *ap);
@@ -976,6 +973,11 @@ jrecord_pop(struct jrecord *jrec, struct journal_subrecord *save)
      * pushptrgood.  Pointers become invalid when their related stream
      * record gets pushed out.
      *
+     * If no pointer is available (the data has already been pushed out),
+     * then no fixup of e.g. the length field is possible for non-leaf
+     * nodes.  The protocol allows for this situation by placing a larger
+     * burden on the program scanning the stream on the other end.
+     *
      * [parentA]
      *   [node X]
      *    [parentB]
@@ -1043,10 +1045,26 @@ jrecord_pop(struct jrecord *jrec, struct journal_subrecord *save)
 }
 
 /*
+ * Write out a leaf record, including associated data.
+ */
+static
+void
+jrecord_leaf(struct jrecord *jrec, int16_t rectype, void *ptr, int bytes)
+{
+    jrecord_write(jrec, rectype, bytes);
+    jrecord_data(jrec, ptr, bytes);
+    jrecord_done(jrec, 0);
+}
+
+/*
  * Write a leaf record out and return a pointer to its base.  The leaf
  * record may contain potentially megabytes of data which is supplied
  * in jrecord_data() calls.  The exact amount must be specified in this
  * call.
+ *
+ * THE RETURNED SUBRECORD POINTER IS ONLY VALID IMMEDIATELY AFTER THE
+ * CALL AND MAY BECOME INVALID AT ANY TIME.  ONLY THE PUSH/POP CODE SHOULD
+ * USE THE RETURN VALUE.
  */
 static
 struct journal_subrecord *
@@ -1207,21 +1225,156 @@ jrecord_done(struct jrecord *jrec, int abortit)
 }
 
 /************************************************************************
- *                     LEAF RECORD SUPPORT ROUTINES                    *
+ *                     LOW LEVEL RECORD SUPPORT ROUTINES               *
  ************************************************************************
  *
- * These routine create leaf subrecords representing common filesystem
- * structures.
+ * These routine create low level recursive and leaf subrecords representing
+ * common filesystem structures.
  */
 
+/*
+ * Write out a filename path relative to the base of the mount point.
+ * rectype is typically JLEAF_PATH{1,2,3,4}.
+ */
 static void
 jrecord_write_path(struct jrecord *jrec, int16_t rectype, struct namecache *ncp)
 {
+    char buf[64];      /* local buffer if it fits, else malloced */
+    char *base;
+    int pathlen;
+    int index;
+    struct namecache *scan;
+
+    /*
+     * Pass 1 - figure out the number of bytes required.  Include terminating
+     *                \0 on last element and '/' separator on other elements.
+     */
+again:
+    pathlen = 0;
+    for (scan = ncp; 
+        scan && (scan->nc_flag & NCF_MOUNTPT) == 0; 
+        scan = scan->nc_parent
+    ) {
+       pathlen += scan->nc_nlen + 1;
+    }
+
+    if (pathlen <= sizeof(buf))
+       base = buf;
+    else
+       base = malloc(pathlen, M_TEMP, M_INTWAIT);
+
+    /*
+     * Pass 2 - generate the path buffer
+     */
+    index = pathlen;
+    for (scan = ncp; 
+        scan && (scan->nc_flag & NCF_MOUNTPT) == 0; 
+        scan = scan->nc_parent
+    ) {
+       if (scan->nc_nlen >= index) {
+           if (base != buf)
+               free(base, M_TEMP);
+           goto again;
+       }
+       if (index == pathlen)
+           base[--index] = 0;
+       else
+           base[--index] = '/';
+       index -= scan->nc_nlen;
+       bcopy(scan->nc_name, base + index, scan->nc_nlen);
+    }
+    jrecord_leaf(jrec, rectype, base + index, pathlen - index);
+    if (base != buf)
+       free(base, M_TEMP);
 }
 
+/*
+ * Write out a file attribute structure.  While somewhat inefficient, using
+ * a recursive data structure is the most portable and extensible way.
+ */
 static void
 jrecord_write_vattr(struct jrecord *jrec, struct vattr *vat)
 {
+    void *save;
+
+    save = jrecord_push(jrec, JTYPE_VATTR);
+    if (vat->va_type != VNON)
+       jrecord_leaf(jrec, JLEAF_UID, &vat->va_type, sizeof(vat->va_type));
+    if (vat->va_uid != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_UID, &vat->va_mode, sizeof(vat->va_mode));
+    if (vat->va_nlink != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_NLINK, &vat->va_nlink, sizeof(vat->va_nlink));
+    if (vat->va_uid != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_UID, &vat->va_uid, sizeof(vat->va_uid));
+    if (vat->va_gid != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_GID, &vat->va_gid, sizeof(vat->va_gid));
+    if (vat->va_fsid != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_FSID, &vat->va_fsid, sizeof(vat->va_fsid));
+    if (vat->va_fileid != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_INUM, &vat->va_fileid, sizeof(vat->va_fileid));
+    if (vat->va_size != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_SIZE, &vat->va_size, sizeof(vat->va_size));
+    if (vat->va_atime.tv_sec != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_ATIME, &vat->va_atime, sizeof(vat->va_atime));
+    if (vat->va_mtime.tv_sec != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_MTIME, &vat->va_mtime, sizeof(vat->va_mtime));
+    if (vat->va_ctime.tv_sec != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_CTIME, &vat->va_ctime, sizeof(vat->va_ctime));
+    if (vat->va_gen != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_GEN, &vat->va_gen, sizeof(vat->va_gen));
+    if (vat->va_flags != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_FLAGS, &vat->va_flags, sizeof(vat->va_flags));
+    if (vat->va_rdev != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_UDEV, &vat->va_rdev, sizeof(vat->va_rdev));
+#if 0
+    if (vat->va_filerev != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_FILEREV, &vat->va_filerev, sizeof(vat->va_filerev));
+#endif
+    jrecord_pop(jrec, save);
+    jrecord_done(jrec, 0);
+}
+
+/*
+ * Write out the creds used to issue a file operation.  If a process is
+ * available write out additional tracking information related to the 
+ * process.
+ *
+ * XXX additional tracking info
+ * XXX tty line info
+ */
+static void
+jrecord_write_cred(struct jrecord *jrec, struct thread *td, struct ucred *cred)
+{
+    void *save;
+    struct proc *p;
+
+    save = jrecord_push(jrec, JTYPE_CRED);
+    jrecord_leaf(jrec, JLEAF_UID, &cred->cr_uid, sizeof(cred->cr_uid));
+    jrecord_leaf(jrec, JLEAF_GID, &cred->cr_gid, sizeof(cred->cr_gid));
+    if (td && (p = td->td_proc) != NULL) {
+       jrecord_leaf(jrec, JLEAF_PID, &p->p_pid, sizeof(p->p_pid));
+       jrecord_leaf(jrec, JLEAF_COMM, p->p_comm, sizeof(p->p_comm));
+    }
+    jrecord_pop(jrec, save);
+    jrecord_done(jrec, 0);
+}
+
+/*
+ * Write out information required to identify a vnode
+ */
+static void
+jrecord_write_vnode_ref(struct jrecord *jrec, struct vnode *vp)
+{
+    /* XXX */
+}
+
+/*
+ * Write out the data associated with a UIO
+ */
+static void
+jrecord_write_uio(struct jrecord *jrec, int16_t rectype, struct uio *uio)
+{
+    /* XXX */
 }
 
 /************************************************************************
@@ -1256,6 +1409,9 @@ jrecord_write_vattr(struct jrecord *jrec, struct vattr *vat)
  * new VFS equivalents (NMKDIR).
  */
 
+/*
+ * Journal vop_settattr { a_vp, a_vap, a_cred, a_td }
+ */
 static
 int
 journal_setattr(struct vop_setattr_args *ap)
@@ -1272,6 +1428,9 @@ journal_setattr(struct vop_setattr_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_SETATTR);
+           jrecord_write_cred(&jrec, ap->a_td, ap->a_cred);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           jrecord_write_vattr(&jrec, ap->a_vap);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1279,6 +1438,9 @@ journal_setattr(struct vop_setattr_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_write { a_vp, a_uio, a_ioflag, a_cred }
+ */
 static
 int
 journal_write(struct vop_write_args *ap)
@@ -1295,6 +1457,9 @@ journal_write(struct vop_write_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_WRITE);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           jrecord_write_uio(&jrec, JLEAF_FILEDATA, ap->a_uio);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1302,6 +1467,9 @@ journal_write(struct vop_write_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_fsync { a_vp, a_waitfor, a_td }
+ */
 static
 int
 journal_fsync(struct vop_fsync_args *ap)
@@ -1320,6 +1488,9 @@ journal_fsync(struct vop_fsync_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_putpages { a_vp, a_m, a_count, a_sync, a_rtvals, a_offset }
+ */
 static
 int
 journal_putpages(struct vop_putpages_args *ap)
@@ -1336,6 +1507,8 @@ journal_putpages(struct vop_putpages_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_PUTPAGES);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           /* XXX pagelist */
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1343,6 +1516,9 @@ journal_putpages(struct vop_putpages_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_setacl { a_vp, a_type, a_aclp, a_cred, a_td }
+ */
 static
 int
 journal_setacl(struct vop_setacl_args *ap)
@@ -1359,6 +1535,9 @@ journal_setacl(struct vop_setacl_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_SETACL);
+           jrecord_write_cred(&jrec, ap->a_td, ap->a_cred);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           /* XXX type, aclp */
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1366,6 +1545,9 @@ journal_setacl(struct vop_setacl_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_setextattr { a_vp, a_name, a_uio, a_cred, a_td }
+ */
 static
 int
 journal_setextattr(struct vop_setextattr_args *ap)
@@ -1382,6 +1564,10 @@ journal_setextattr(struct vop_setextattr_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_SETEXTATTR);
+           jrecord_write_cred(&jrec, ap->a_td, ap->a_cred);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           jrecord_leaf(&jrec, JLEAF_ATTRNAME, ap->a_name, strlen(ap->a_name));
+           jrecord_write_uio(&jrec, JLEAF_FILEDATA, ap->a_uio);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1389,6 +1575,9 @@ journal_setextattr(struct vop_setextattr_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_ncreate { a_ncp, a_vpp, a_cred, a_vap }
+ */
 static
 int
 journal_ncreate(struct vop_ncreate_args *ap)
@@ -1405,6 +1594,10 @@ journal_ncreate(struct vop_ncreate_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_CREATE);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           if (*ap->a_vpp)
+               jrecord_write_vnode_ref(&jrec, *ap->a_vpp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1412,6 +1605,9 @@ journal_ncreate(struct vop_ncreate_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nmknod { a_ncp, a_vpp, a_cred, a_vap }
+ */
 static
 int
 journal_nmknod(struct vop_nmknod_args *ap)
@@ -1428,6 +1624,11 @@ journal_nmknod(struct vop_nmknod_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_MKNOD);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_vattr(&jrec, ap->a_vap);
+           if (*ap->a_vpp)
+               jrecord_write_vnode_ref(&jrec, *ap->a_vpp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1435,6 +1636,9 @@ journal_nmknod(struct vop_nmknod_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nlink { a_ncp, a_vp, a_cred }
+ */
 static
 int
 journal_nlink(struct vop_nlink_args *ap)
@@ -1451,6 +1655,10 @@ journal_nlink(struct vop_nlink_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_LINK);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           /* XXX PATH to VP and inode number */
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1458,6 +1666,9 @@ journal_nlink(struct vop_nlink_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_symlink { a_ncp, a_vpp, a_cred, a_vap, a_target }
+ */
 static
 int
 journal_nsymlink(struct vop_nsymlink_args *ap)
@@ -1474,6 +1685,12 @@ journal_nsymlink(struct vop_nsymlink_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_SYMLINK);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_leaf(&jrec, JLEAF_SYMLINKDATA,
+                       ap->a_target, strlen(ap->a_target));
+           if (*ap->a_vpp)
+               jrecord_write_vnode_ref(&jrec, *ap->a_vpp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1481,6 +1698,9 @@ journal_nsymlink(struct vop_nsymlink_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nwhiteout { a_ncp, a_cred, a_flags }
+ */
 static
 int
 journal_nwhiteout(struct vop_nwhiteout_args *ap)
@@ -1497,6 +1717,8 @@ journal_nwhiteout(struct vop_nwhiteout_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_WHITEOUT);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1504,6 +1726,9 @@ journal_nwhiteout(struct vop_nwhiteout_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nremove { a_ncp, a_cred }
+ */
 static
 int
 journal_nremove(struct vop_nremove_args *ap)
@@ -1520,6 +1745,8 @@ journal_nremove(struct vop_nremove_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_REMOVE);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1527,6 +1754,9 @@ journal_nremove(struct vop_nremove_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nmkdir { a_ncp, a_vpp, a_cred, a_vap }
+ */
 static
 int
 journal_nmkdir(struct vop_nmkdir_args *ap)
@@ -1554,7 +1784,11 @@ journal_nmkdir(struct vop_nmkdir_args *ap)
 #endif
            save = jrecord_push(&jrec, JTYPE_MKDIR);
            jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
            jrecord_write_vattr(&jrec, ap->a_vap);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           if (*ap->a_vpp)
+               jrecord_write_vnode_ref(&jrec, *ap->a_vpp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1562,7 +1796,9 @@ journal_nmkdir(struct vop_nmkdir_args *ap)
     return (error);
 }
 
-
+/*
+ * Journal vop_nrmdir { a_ncp, a_cred }
+ */
 static
 int
 journal_nrmdir(struct vop_nrmdir_args *ap)
@@ -1579,6 +1815,8 @@ journal_nrmdir(struct vop_nrmdir_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_RMDIR);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1586,6 +1824,9 @@ journal_nrmdir(struct vop_nrmdir_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nrename { a_fncp, a_tncp, a_cred }
+ */
 static
 int
 journal_nrename(struct vop_nrename_args *ap)
@@ -1602,6 +1843,9 @@ journal_nrename(struct vop_nrename_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_RENAME);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_fncp);
+           jrecord_write_path(&jrec, JLEAF_PATH2, ap->a_tncp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
index 2d54de5..4864b92 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/vfs_journal.c,v 1.6 2005/01/09 03:04:51 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_journal.c,v 1.7 2005/02/28 17:41:00 dillon Exp $
  */
 /*
  * Each mount point may have zero or more independantly configured journals
@@ -84,7 +84,9 @@
 #include <sys/vnode.h>
 #include <sys/poll.h>
 #include <sys/mountctl.h>
+#include <sys/journal.h>
 #include <sys/file.h>
+#include <sys/proc.h>
 
 #include <machine/limits.h>
 
@@ -132,11 +134,6 @@ static struct journal_subrecord *jrecord_write(struct jrecord *jrec,
 static void jrecord_data(struct jrecord *jrec, const void *buf, int bytes);
 static void jrecord_done(struct jrecord *jrec, int abortit);
 
-static void jrecord_write_path(struct jrecord *jrec, 
-                           int16_t rectype, struct namecache *ncp);
-static void jrecord_write_vattr(struct jrecord *jrec, struct vattr *vat);
-
-
 static int journal_setattr(struct vop_setattr_args *ap);
 static int journal_write(struct vop_write_args *ap);
 static int journal_fsync(struct vop_fsync_args *ap);
@@ -976,6 +973,11 @@ jrecord_pop(struct jrecord *jrec, struct journal_subrecord *save)
      * pushptrgood.  Pointers become invalid when their related stream
      * record gets pushed out.
      *
+     * If no pointer is available (the data has already been pushed out),
+     * then no fixup of e.g. the length field is possible for non-leaf
+     * nodes.  The protocol allows for this situation by placing a larger
+     * burden on the program scanning the stream on the other end.
+     *
      * [parentA]
      *   [node X]
      *    [parentB]
@@ -1043,10 +1045,26 @@ jrecord_pop(struct jrecord *jrec, struct journal_subrecord *save)
 }
 
 /*
+ * Write out a leaf record, including associated data.
+ */
+static
+void
+jrecord_leaf(struct jrecord *jrec, int16_t rectype, void *ptr, int bytes)
+{
+    jrecord_write(jrec, rectype, bytes);
+    jrecord_data(jrec, ptr, bytes);
+    jrecord_done(jrec, 0);
+}
+
+/*
  * Write a leaf record out and return a pointer to its base.  The leaf
  * record may contain potentially megabytes of data which is supplied
  * in jrecord_data() calls.  The exact amount must be specified in this
  * call.
+ *
+ * THE RETURNED SUBRECORD POINTER IS ONLY VALID IMMEDIATELY AFTER THE
+ * CALL AND MAY BECOME INVALID AT ANY TIME.  ONLY THE PUSH/POP CODE SHOULD
+ * USE THE RETURN VALUE.
  */
 static
 struct journal_subrecord *
@@ -1207,21 +1225,156 @@ jrecord_done(struct jrecord *jrec, int abortit)
 }
 
 /************************************************************************
- *                     LEAF RECORD SUPPORT ROUTINES                    *
+ *                     LOW LEVEL RECORD SUPPORT ROUTINES               *
  ************************************************************************
  *
- * These routine create leaf subrecords representing common filesystem
- * structures.
+ * These routine create low level recursive and leaf subrecords representing
+ * common filesystem structures.
  */
 
+/*
+ * Write out a filename path relative to the base of the mount point.
+ * rectype is typically JLEAF_PATH{1,2,3,4}.
+ */
 static void
 jrecord_write_path(struct jrecord *jrec, int16_t rectype, struct namecache *ncp)
 {
+    char buf[64];      /* local buffer if it fits, else malloced */
+    char *base;
+    int pathlen;
+    int index;
+    struct namecache *scan;
+
+    /*
+     * Pass 1 - figure out the number of bytes required.  Include terminating
+     *                \0 on last element and '/' separator on other elements.
+     */
+again:
+    pathlen = 0;
+    for (scan = ncp; 
+        scan && (scan->nc_flag & NCF_MOUNTPT) == 0; 
+        scan = scan->nc_parent
+    ) {
+       pathlen += scan->nc_nlen + 1;
+    }
+
+    if (pathlen <= sizeof(buf))
+       base = buf;
+    else
+       base = malloc(pathlen, M_TEMP, M_INTWAIT);
+
+    /*
+     * Pass 2 - generate the path buffer
+     */
+    index = pathlen;
+    for (scan = ncp; 
+        scan && (scan->nc_flag & NCF_MOUNTPT) == 0; 
+        scan = scan->nc_parent
+    ) {
+       if (scan->nc_nlen >= index) {
+           if (base != buf)
+               free(base, M_TEMP);
+           goto again;
+       }
+       if (index == pathlen)
+           base[--index] = 0;
+       else
+           base[--index] = '/';
+       index -= scan->nc_nlen;
+       bcopy(scan->nc_name, base + index, scan->nc_nlen);
+    }
+    jrecord_leaf(jrec, rectype, base + index, pathlen - index);
+    if (base != buf)
+       free(base, M_TEMP);
 }
 
+/*
+ * Write out a file attribute structure.  While somewhat inefficient, using
+ * a recursive data structure is the most portable and extensible way.
+ */
 static void
 jrecord_write_vattr(struct jrecord *jrec, struct vattr *vat)
 {
+    void *save;
+
+    save = jrecord_push(jrec, JTYPE_VATTR);
+    if (vat->va_type != VNON)
+       jrecord_leaf(jrec, JLEAF_UID, &vat->va_type, sizeof(vat->va_type));
+    if (vat->va_uid != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_UID, &vat->va_mode, sizeof(vat->va_mode));
+    if (vat->va_nlink != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_NLINK, &vat->va_nlink, sizeof(vat->va_nlink));
+    if (vat->va_uid != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_UID, &vat->va_uid, sizeof(vat->va_uid));
+    if (vat->va_gid != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_GID, &vat->va_gid, sizeof(vat->va_gid));
+    if (vat->va_fsid != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_FSID, &vat->va_fsid, sizeof(vat->va_fsid));
+    if (vat->va_fileid != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_INUM, &vat->va_fileid, sizeof(vat->va_fileid));
+    if (vat->va_size != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_SIZE, &vat->va_size, sizeof(vat->va_size));
+    if (vat->va_atime.tv_sec != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_ATIME, &vat->va_atime, sizeof(vat->va_atime));
+    if (vat->va_mtime.tv_sec != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_MTIME, &vat->va_mtime, sizeof(vat->va_mtime));
+    if (vat->va_ctime.tv_sec != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_CTIME, &vat->va_ctime, sizeof(vat->va_ctime));
+    if (vat->va_gen != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_GEN, &vat->va_gen, sizeof(vat->va_gen));
+    if (vat->va_flags != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_FLAGS, &vat->va_flags, sizeof(vat->va_flags));
+    if (vat->va_rdev != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_UDEV, &vat->va_rdev, sizeof(vat->va_rdev));
+#if 0
+    if (vat->va_filerev != VNOVAL)
+       jrecord_leaf(jrec, JLEAF_FILEREV, &vat->va_filerev, sizeof(vat->va_filerev));
+#endif
+    jrecord_pop(jrec, save);
+    jrecord_done(jrec, 0);
+}
+
+/*
+ * Write out the creds used to issue a file operation.  If a process is
+ * available write out additional tracking information related to the 
+ * process.
+ *
+ * XXX additional tracking info
+ * XXX tty line info
+ */
+static void
+jrecord_write_cred(struct jrecord *jrec, struct thread *td, struct ucred *cred)
+{
+    void *save;
+    struct proc *p;
+
+    save = jrecord_push(jrec, JTYPE_CRED);
+    jrecord_leaf(jrec, JLEAF_UID, &cred->cr_uid, sizeof(cred->cr_uid));
+    jrecord_leaf(jrec, JLEAF_GID, &cred->cr_gid, sizeof(cred->cr_gid));
+    if (td && (p = td->td_proc) != NULL) {
+       jrecord_leaf(jrec, JLEAF_PID, &p->p_pid, sizeof(p->p_pid));
+       jrecord_leaf(jrec, JLEAF_COMM, p->p_comm, sizeof(p->p_comm));
+    }
+    jrecord_pop(jrec, save);
+    jrecord_done(jrec, 0);
+}
+
+/*
+ * Write out information required to identify a vnode
+ */
+static void
+jrecord_write_vnode_ref(struct jrecord *jrec, struct vnode *vp)
+{
+    /* XXX */
+}
+
+/*
+ * Write out the data associated with a UIO
+ */
+static void
+jrecord_write_uio(struct jrecord *jrec, int16_t rectype, struct uio *uio)
+{
+    /* XXX */
 }
 
 /************************************************************************
@@ -1256,6 +1409,9 @@ jrecord_write_vattr(struct jrecord *jrec, struct vattr *vat)
  * new VFS equivalents (NMKDIR).
  */
 
+/*
+ * Journal vop_settattr { a_vp, a_vap, a_cred, a_td }
+ */
 static
 int
 journal_setattr(struct vop_setattr_args *ap)
@@ -1272,6 +1428,9 @@ journal_setattr(struct vop_setattr_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_SETATTR);
+           jrecord_write_cred(&jrec, ap->a_td, ap->a_cred);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           jrecord_write_vattr(&jrec, ap->a_vap);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1279,6 +1438,9 @@ journal_setattr(struct vop_setattr_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_write { a_vp, a_uio, a_ioflag, a_cred }
+ */
 static
 int
 journal_write(struct vop_write_args *ap)
@@ -1295,6 +1457,9 @@ journal_write(struct vop_write_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_WRITE);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           jrecord_write_uio(&jrec, JLEAF_FILEDATA, ap->a_uio);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1302,6 +1467,9 @@ journal_write(struct vop_write_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_fsync { a_vp, a_waitfor, a_td }
+ */
 static
 int
 journal_fsync(struct vop_fsync_args *ap)
@@ -1320,6 +1488,9 @@ journal_fsync(struct vop_fsync_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_putpages { a_vp, a_m, a_count, a_sync, a_rtvals, a_offset }
+ */
 static
 int
 journal_putpages(struct vop_putpages_args *ap)
@@ -1336,6 +1507,8 @@ journal_putpages(struct vop_putpages_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_PUTPAGES);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           /* XXX pagelist */
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1343,6 +1516,9 @@ journal_putpages(struct vop_putpages_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_setacl { a_vp, a_type, a_aclp, a_cred, a_td }
+ */
 static
 int
 journal_setacl(struct vop_setacl_args *ap)
@@ -1359,6 +1535,9 @@ journal_setacl(struct vop_setacl_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_SETACL);
+           jrecord_write_cred(&jrec, ap->a_td, ap->a_cred);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           /* XXX type, aclp */
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1366,6 +1545,9 @@ journal_setacl(struct vop_setacl_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_setextattr { a_vp, a_name, a_uio, a_cred, a_td }
+ */
 static
 int
 journal_setextattr(struct vop_setextattr_args *ap)
@@ -1382,6 +1564,10 @@ journal_setextattr(struct vop_setextattr_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_SETEXTATTR);
+           jrecord_write_cred(&jrec, ap->a_td, ap->a_cred);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           jrecord_leaf(&jrec, JLEAF_ATTRNAME, ap->a_name, strlen(ap->a_name));
+           jrecord_write_uio(&jrec, JLEAF_FILEDATA, ap->a_uio);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1389,6 +1575,9 @@ journal_setextattr(struct vop_setextattr_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_ncreate { a_ncp, a_vpp, a_cred, a_vap }
+ */
 static
 int
 journal_ncreate(struct vop_ncreate_args *ap)
@@ -1405,6 +1594,10 @@ journal_ncreate(struct vop_ncreate_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_CREATE);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           if (*ap->a_vpp)
+               jrecord_write_vnode_ref(&jrec, *ap->a_vpp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1412,6 +1605,9 @@ journal_ncreate(struct vop_ncreate_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nmknod { a_ncp, a_vpp, a_cred, a_vap }
+ */
 static
 int
 journal_nmknod(struct vop_nmknod_args *ap)
@@ -1428,6 +1624,11 @@ journal_nmknod(struct vop_nmknod_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_MKNOD);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_vattr(&jrec, ap->a_vap);
+           if (*ap->a_vpp)
+               jrecord_write_vnode_ref(&jrec, *ap->a_vpp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1435,6 +1636,9 @@ journal_nmknod(struct vop_nmknod_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nlink { a_ncp, a_vp, a_cred }
+ */
 static
 int
 journal_nlink(struct vop_nlink_args *ap)
@@ -1451,6 +1655,10 @@ journal_nlink(struct vop_nlink_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_LINK);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_vnode_ref(&jrec, ap->a_vp);
+           /* XXX PATH to VP and inode number */
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1458,6 +1666,9 @@ journal_nlink(struct vop_nlink_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_symlink { a_ncp, a_vpp, a_cred, a_vap, a_target }
+ */
 static
 int
 journal_nsymlink(struct vop_nsymlink_args *ap)
@@ -1474,6 +1685,12 @@ journal_nsymlink(struct vop_nsymlink_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_SYMLINK);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_leaf(&jrec, JLEAF_SYMLINKDATA,
+                       ap->a_target, strlen(ap->a_target));
+           if (*ap->a_vpp)
+               jrecord_write_vnode_ref(&jrec, *ap->a_vpp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1481,6 +1698,9 @@ journal_nsymlink(struct vop_nsymlink_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nwhiteout { a_ncp, a_cred, a_flags }
+ */
 static
 int
 journal_nwhiteout(struct vop_nwhiteout_args *ap)
@@ -1497,6 +1717,8 @@ journal_nwhiteout(struct vop_nwhiteout_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_WHITEOUT);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1504,6 +1726,9 @@ journal_nwhiteout(struct vop_nwhiteout_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nremove { a_ncp, a_cred }
+ */
 static
 int
 journal_nremove(struct vop_nremove_args *ap)
@@ -1520,6 +1745,8 @@ journal_nremove(struct vop_nremove_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_REMOVE);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1527,6 +1754,9 @@ journal_nremove(struct vop_nremove_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nmkdir { a_ncp, a_vpp, a_cred, a_vap }
+ */
 static
 int
 journal_nmkdir(struct vop_nmkdir_args *ap)
@@ -1554,7 +1784,11 @@ journal_nmkdir(struct vop_nmkdir_args *ap)
 #endif
            save = jrecord_push(&jrec, JTYPE_MKDIR);
            jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
            jrecord_write_vattr(&jrec, ap->a_vap);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
+           if (*ap->a_vpp)
+               jrecord_write_vnode_ref(&jrec, *ap->a_vpp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1562,7 +1796,9 @@ journal_nmkdir(struct vop_nmkdir_args *ap)
     return (error);
 }
 
-
+/*
+ * Journal vop_nrmdir { a_ncp, a_cred }
+ */
 static
 int
 journal_nrmdir(struct vop_nrmdir_args *ap)
@@ -1579,6 +1815,8 @@ journal_nrmdir(struct vop_nrmdir_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_RMDIR);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_ncp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
@@ -1586,6 +1824,9 @@ journal_nrmdir(struct vop_nrmdir_args *ap)
     return (error);
 }
 
+/*
+ * Journal vop_nrename { a_fncp, a_tncp, a_cred }
+ */
 static
 int
 journal_nrename(struct vop_nrename_args *ap)
@@ -1602,6 +1843,9 @@ journal_nrename(struct vop_nrename_args *ap)
        TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
            jrecord_init(jo, &jrec, -1);
            save = jrecord_push(&jrec, JTYPE_RENAME);
+           jrecord_write_cred(&jrec, NULL, ap->a_cred);
+           jrecord_write_path(&jrec, JLEAF_PATH1, ap->a_fncp);
+           jrecord_write_path(&jrec, JLEAF_PATH2, ap->a_tncp);
            jrecord_pop(&jrec, save);
            jrecord_done(&jrec, 0);
        }
similarity index 78%
copy from sys/sys/mountctl.h
copy to sys/sys/journal.h
index b005e56..c9b04b0 100644 (file)
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/mountctl.h,v 1.5 2005/01/09 03:04:53 dillon Exp $
+ * $DragonFly: src/sys/sys/journal.h,v 1.1 2005/02/28 17:40:51 dillon Exp $
  */
 
-/*
- * General constants
- */
-
-#define JIDMAX         32      /* id string buf[] size (incls \0) */
-
-/*
- * Data structures for the journaling API
- */
-
-#define MOUNTCTL_INSTALL_VFS_JOURNAL   1
-#define MOUNTCTL_REMOVE_VFS_JOURNAL    2
-#define MOUNTCTL_RESYNC_VFS_JOURNAL    3
-#define MOUNTCTL_STATUS_VFS_JOURNAL    4
-
-#define MOUNTCTL_INSTALL_BLK_JOURNAL   8
-#define MOUNTCTL_REMOVE_BLK_JOURNAL    9
-#define MOUNTCTL_RESYNC_BLK_JOURNAL    10
-#define MOUNTCTL_STATUS_BLK_JOURNAL    11
-
-struct mountctl_install_journal {
-       char    id[JIDMAX];
-       int     flags;          /* journaling flags */
-       int     unused01;
-       int64_t membufsize;     /* backing store */
-       int64_t swapbufsize;    /* backing store */
-       int64_t transid;        /* starting with specified transaction id */
-       int64_t unused02;
-       int     stallwarn;      /* stall warning (seconds) */
-       int     stallerror;     /* stall error (seconds) */
-       int     unused03;
-       int     unused04;
-};
-
-#define MC_JOURNAL_ACTIVE              0x00000001      /* journal is active */
-#define MC_JOURNAL_STOP_REQ            0x00000002      /* stop request pend */
-#define MC_JOURNAL_STOP_IMM            0x00000004      /* STOP+trash fifo */
-#define MC_JOURNAL_WWAIT               0x00000040      /* write stall */
-#define MC_JOURNAL_WANT_AUDIT          0x00010000      /* audit trail */
-#define MC_JOURNAL_WANT_REVERSABLE     0x00020000      /* reversable stream */
-
-struct mountctl_remove_journal {
-       char    id[JIDMAX];
-       int     flags;
-};
-
-#define MC_JOURNAL_REMOVE_TRASH                0x00000001      /* data -> trash */
-#define MC_JOURNAL_REMOVE_ASSYNC       0x00000002      /* asynchronous op */
-
-struct mountctl_status_journal {
-       char    id[JIDMAX];
-       int     index;
-};
-
-#define MC_JOURNAL_INDEX_ALL           -2
-#define MC_JOURNAL_INDEX_ID            -1
-
-struct mountctl_journal_ret_status {
-       int     recsize;
-       char    id[JIDMAX];
-       int     index;
-       int     flags;
-       int64_t membufsize;
-       int64_t membufused;
-       int64_t membufiopend;
-       int64_t swapbufsize;
-       int64_t swapbufused;
-       int64_t swapbufiopend;
-       int64_t transidstart;
-       int64_t transidcurrent;
-       int64_t transidiopend;
-       int64_t transidacked;
-       int64_t bytessent;
-       int64_t bytesacked;
-       struct timeval lastack;
-};
-
-#define MC_JOURNAL_STATUS_MORETOCOME   0x00000001
+#ifndef _SYS_JOURNAL_H_
+#define _SYS_JOURNAL_H_
 
 /*
  * Physical file format (binary)
@@ -319,6 +243,9 @@ struct journal_subrecord {
 #define JTYPE_RMDIR            (JMASK_NESTED|0x001C)
 #define JTYPE_RENAME           (JMASK_NESTED|0x001D)
 
+#define JTYPE_VATTR            (JMASK_NESTED|0x0100)
+#define JTYPE_CRED             (JMASK_NESTED|0x0101)
+
 /*
  * Low level record types
  */
@@ -334,60 +261,54 @@ struct journal_subrecord {
 #define JLEAF_PID              0x040A
 #define JLEAF_PPID             0x040B
 #define JLEAF_COMM             0x040C
-#define JLEAF_RESERVED_0D      0x040D
+#define JLEAF_ATTRNAME         0x040D
 #define JLEAF_RESERVED_0E      0x040E
 #define JLEAF_RESERVED_0F      0x040F
 #define JLEAF_SYMLINKDATA      0x0410
 #define JLEAF_SEEKPOS          0x0411
 #define JLEAF_INUM             0x0412
-
-#if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
+#define JLEAF_NLINK            0x0413
+#define JLEAF_FSID             0x0414
+#define JLEAF_SIZE             0x0415
+#define JLEAF_ATIME            0x0416
+#define JLEAF_MTIME            0x0417
+#define JLEAF_CTIME            0x0418
+#define JLEAF_GEN              0x0419
+#define JLEAF_FLAGS            0x041A
+#define JLEAF_UDEV             0x041B
+#define JLEAF_FILEREV          0x041C
 
 /*
- * Support structures for the generic journaling structure
+ * Low level journal data file structures
+ *
+ * NOTE: embedded strings may use the full width of the field and thus
+ * may not be 0-terminated.
  */
-struct journal_memfifo {
-       int     size;           /* size (power of two) */
-       int     mask;           /* index mask (size - 1) */
-       int     rindex;         /* stream reader index (track fd writes) */
-       int     xindex;         /* last acked / reader restart */
-       int     windex;         /* stream writer index */
-       char    *membase;       /* memory buffer representing the FIFO */
+struct jleaf_path {
+       char    path[4];        /* path from base of mount point */
+       /* path is variable length and 0-terminated */
 };
 
-/*
- * Generic journaling structure attached to a mount point.
- */
-struct journal {
-       TAILQ_ENTRY(journal) jentry;
-       struct file     *fp;
-       char            id[JIDMAX];
-       int             flags;          /* journaling flags */
-       int64_t         transid;
-       int64_t         total_acked;
-       struct journal_memfifo fifo;
-       struct thread   thread;
+struct jleaf_vattr {
+       int32_t modes;
+       int32_t fflags;
+       struct timespec atime;
+       struct timespec mtime;
+       struct timespec ctime;
+       int64_t inum;
 };
 
-/*
- * The jrecord structure is used to build a journaling transaction.  Since
- * a single journaling transaction might encompass very large buffers it 
- * is possible for multiple transactions to be written out to the FIFO
- * in parallel and in peacemeal.
- */
-struct jrecord {
-       struct journal  *jo;
-       char            *stream_ptr;
-       int             stream_residual;
-       int             stream_reserved;
-       struct journal_rawrecbeg *rawp;
-       struct journal_subrecord *parent;
-       struct journal_subrecord *last;
-       int16_t         streamid;
-       int             pushcount;
-       int             pushptrgood;
-       int             residual;
-       int             residual_align;
+struct jleaf_cred {
+       int32_t uid;
+       int32_t gid;
+       int32_t pid;
+       int32_t flags;          /* suid/sgid and other flags */
+       char    line[8];        /* ttyname or other session identification */
+       char    comm[8];        /* simplified command name for reference */
+};
+
+struct jleaf_ioinfo {
+       int64_t offset;
 };
 
 #endif
index b005e56..36bfa92 100644 (file)
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/mountctl.h,v 1.5 2005/01/09 03:04:53 dillon Exp $
+ * $DragonFly: src/sys/sys/mountctl.h,v 1.6 2005/02/28 17:40:51 dillon Exp $
  */
 
+#ifndef _SYS_MOUNTCTL_H_
+#define _SYS_MOUNTCTL_H_
 /*
  * General constants
  */
@@ -113,234 +115,6 @@ struct mountctl_journal_ret_status {
 
 #define MC_JOURNAL_STATUS_MORETOCOME   0x00000001
 
-/*
- * Physical file format (binary)
- *
- * All raw records are 128-bit aligned, but all record sizes are actual.
- * This means that any scanning code must 16-byte-align the recsize field
- * when calculating skips.  The top level raw record has a header and a
- * trailer to allow both forwards and backwards scanning of the journal.
- * The alignment requirement allows the worker thread FIFO reservation
- * API to operate efficiently, amoung other things.
- *
- * Logical data stream records are usually no larger then the journal's
- * in-memory FIFO, since the journal's transactional APIs return contiguous
- * blocks of buffer space and since logical stream records are used to avoid
- * stalls when concurrent blocking operations are being written to the journal.
- * Programs can depend on a logical stream record being a 'reasonable' size.
- *
- * Multiple logical data streams may operate concurrently in the journal,
- * reflecting the fact that the system may be executing multiple blocking
- * operations on the filesystem all at the same time.  These logical data
- * streams are short-lived transactional entities which use a 13 bit id
- * plus a transaction start bit, end bit, and abort bit.
- *
- * Stream identifiers in the 0x00-0xFF range are special and not used for
- * normal transactional commands. 
- *
- * Stream id 0x00 indicates that no other streams should be active at that
- * point in the journal, which helps the journaling code detect corruption.
- *
- * Stream id 0x01 is used for pad.  Pads are used to align data on convenient
- * boundaries and to deal with dead space.
- *
- * Stream id 0x02 indicates a discontinuity in the streamed data and typically
- * contains information relating to the reason for the discontinuity.
- * JTYPE_ASSOCIATE and JTYPE_DISASSOCIATE are usually emplaced in stream 0x02.
- *
- * Stream id 0x03 may be used to annotate the journal with text comments
- * via mountctl commands.  This can be extremely useful to note situations
- * that may help with later recovery or audit operations.
- *
- * Stream id 0x04-0x7F are reserved by DragonFly for future protocol expansion.
- *
- * Stream id 0x80-0xFF may be used for third-party protocol expansion.
- *
- * Stream id's 0x0100-0x1FFF typically represent short-lived transactions
- * (i.e. an id may be reused once the previous use has completed).  The
- * journaling system runs through these id's sequentially which means that
- * the journaling code can handle up to 8192-256 = 7936 simultanious
- * transactions at any given moment.
- *
- * The sequence number field is context-sensitive.  It is typically used by
- * a journaling stream to provide an incrementing counter and/or timestamp
- * so recovery utilities can determine if any data is missing.
- *
- * The check word in the trailer may be used to provide an integrity check
- * on the journaled data.  A value of 0 always means that no check word
- * has been calculated.
- *
- * The journal_rawrecbeg structure MUST be a multiple of 16 bytes.
- * The journal_rawrecend structure MUST be a multiple of 8 bytes.
- *
- * NOTE: PAD RECORD SPECIAL CASE.  Pad records are 16 bytes and have the
- * rawrecend structure overlayed on the sequence number field of the 
- * rawrecbeg structure.  This is necessary because stream records are
- * 16 byte aligned, not 24 byte aligned, and dead space is not allowed.
- * So the pad record must fit into any dead space.
- */
-struct journal_rawrecbeg {
-       u_int16_t begmagic;     /* recovery scan, endianess detection */
-       u_int16_t streamid;     /* start/stop bits and stream identifier */
-       int32_t recsize;        /* stream data block (incls beg & end) */
-       int64_t seqno;          /* sequence number or transaction id */
-       /* ADDITIONAL DATA */
-};
-
-struct journal_rawrecend {
-       u_int16_t endmagic;     /* recovery scan, endianess detection */
-       u_int16_t check;        /* check word or 0 */
-       int32_t recsize;        /* same as rawrecbeg->recsize, for rev scan */
-};
-
-/*
- * Constants for stream record magic numbers.    The incomplete magic
- * number code is used internally by the memory FIFO reservation API
- * and worker thread, allowing a block of space in the journaling
- * stream (aka a stream block) to be reserved and then populated without
- * stalling other threads doing their own reservation and population.
- */
-#define JREC_BEGMAGIC          0x1234
-#define JREC_ENDMAGIC          0xCDEF
-#define JREC_INCOMPLETEMAGIC   0xFFFF
-
-/*
- * Stream ids are 14 bits.  The top 2 bits specify when a new logical
- * stream is being created or an existing logical stream is being terminated.
- * A single raw stream record will set both the BEGIN and END bits if the
- * entire transaction is encapsulated in a single stream record.
- */
-#define JREC_STREAMCTL_MASK    0xE000
-#define JREC_STREAMCTL_BEGIN   0x8000  /* start a new logical stream */
-#define JREC_STREAMCTL_END     0x4000  /* terminate a logical stream */
-#define JREC_STREAMCTL_ABORTED 0x2000
-
-#define JREC_STREAMID_MASK     0x1FFF
-#define JREC_STREAMID_SYNCPT   (JREC_STREAMCTL_BEGIN|JREC_STREAMCTL_END|0x0000)
-#define JREC_STREAMID_PAD      (JREC_STREAMCTL_BEGIN|JREC_STREAMCTL_END|0x0001)
-#define JREC_STREAMID_DISCONT  0x0002  /* discontinuity */
-#define JREC_STREAMID_ANNOTATE 0x0003  /* annotation */
-                               /* 0x0004-0x007F reserved by DragonFly */
-                               /* 0x0080-0x00FF for third party use */
-#define JREC_STREAMID_JMIN     0x0100  /* lowest allowed general id */
-#define JREC_STREAMID_JMAX     0x2000  /* (one past the highest allowed id) */
-
-#define JREC_DEFAULTSIZE       64      /* reasonable initial reservation */
-
-/*
- * Each logical journaling stream typically represents a transaction...
- * that is, a VFS operation.  The VFS operation is written out using 
- * sub-records and may contain multiple, possibly nested sub-transactions.
- * multiple sub-transactions occur when a VFS operation cannot be represented
- * by a single command.  This is typically the case when a journal is 
- * configured to be reversable because UNDO sequences almost always have to
- * be specified in such cases.  For example, if you ftruncate() a file the
- * journal might have to write out a sequence of WRITE records representing
- * the lost data, otherwise the journal would not be reversable.
- * Sub-transactions within a particular stream do not have their own sequence
- * number field and thus may not be parallelized (the protocol is already
- * complex enough!).
- *
- * In order to support streaming operation with a limited buffer the recsize
- * field is allowed to be 0 for subrecords with the JMASK_NESTED bit set.
- * If this case occurs a scanner can determine that the recursion has ended
- * by detecting a nested subrecord with the JMASK_LAST bit set.  A scanner
- * may also set the field to the proper value after the fact to make later
- * operations more efficient. 
- *
- * Note that this bit must be properly set even if the recsize field is
- * non-zero.  The recsize must always be properly specified for 'leaf'
- * subrecords, however in order to allow subsystems to potentially allocate
- * more data space then they use the protocol allows any 'dead' space to be
- * filled with JLEAF_PAD records.
- *
- * The recsize field may indicate data well past the size of the current
- * raw stream record.  That is, the scanner may have to glue together
- * multiple stream records with the same stream id to fully decode the
- * embedded subrecords.  In particular, a subrecord could very well represent
- * hundreds of megabytes of data (e.g. if a program were to do a
- * multi-megabyte write()) and be split up across thousands of raw streaming
- * records, possibly interlaced with other unrelated streams from other
- * unrelated processes.  
- *
- * If a large sub-transaction is aborted the logical stream may be
- * terminated without writing out all the expected data.  When this occurs
- * the stream's ending record must also have the JREC_STREAMCTL_ABORTED bit
- * set.  However, scanners should still be robust enough to detect such
- * overflows even if the aborted bit is not set and consider them data
- * corruption.
- * 
- * Aborts may also occur in the normal course of operations, especially once
- * the journaling API is integrated into the cache coherency API.  A normal
- * abort is issued by emplacing a JLEAF_ABORT record within the transaction
- * being aborted.  Such records must be the last record in the sub-transaction,
- * so JLEAF_LAST is also usually set.  In a transaction with many 
- * sub-transactions only those sub-transactions with an abort record are
- * aborted, the rest remain valid.  Abort records are considered S.O.P. for
- * two reasons:  First, limited memory buffer space may make it impossible
- * to delete the portion of the stream being aborted (the data may have
- * already been sent to the target).  Second, the journaling code will
- * eventually be used to support a cache coherency layer which may have to
- * abort operations as part of the cache coherency protocol.  Note that
- * subrecord aborts are different from stream record aborts.  Stream record
- * aborts are considered to be extrodinary situations while subrecord aborts
- * are S.O.P.
- */
-
-struct journal_subrecord {
-       int16_t rectype;        /* 2 control bits, 14 record type bits */
-       int16_t reserved;       /* future use */
-       int32_t recsize;        /* record size (mandatory if not NESTED) */
-       /* ADDITIONAL DATA */
-};
-
-#define JMASK_NESTED           0x8000  /* data is a nested recursion */
-#define JMASK_LAST             0x4000
-
-#define JLEAF_PAD              0x0000
-#define JLEAF_ABORT            0x0001
-#define JTYPE_ASSOCIATE                0x0002
-#define JTYPE_DISASSOCIATE     0x0003
-#define JTYPE_UNDO             (JMASK_NESTED|0x0004)
-#define JTYPE_AUDIT            (JMASK_NESTED|0x0005)
-
-#define JTYPE_SETATTR          (JMASK_NESTED|0x0010)
-#define JTYPE_WRITE            (JMASK_NESTED|0x0011)
-#define JTYPE_PUTPAGES         (JMASK_NESTED|0x0012)
-#define JTYPE_SETACL           (JMASK_NESTED|0x0013)
-#define JTYPE_SETEXTATTR       (JMASK_NESTED|0x0014)
-#define JTYPE_CREATE           (JMASK_NESTED|0x0015)
-#define JTYPE_MKNOD            (JMASK_NESTED|0x0016)
-#define JTYPE_LINK             (JMASK_NESTED|0x0017)
-#define JTYPE_SYMLINK          (JMASK_NESTED|0x0018)
-#define JTYPE_WHITEOUT         (JMASK_NESTED|0x0019)
-#define JTYPE_REMOVE           (JMASK_NESTED|0x001A)
-#define JTYPE_MKDIR            (JMASK_NESTED|0x001B)
-#define JTYPE_RMDIR            (JMASK_NESTED|0x001C)
-#define JTYPE_RENAME           (JMASK_NESTED|0x001D)
-
-/*
- * Low level record types
- */
-#define JLEAF_FILEDATA         0x0401
-#define JLEAF_PATH1            0x0402
-#define JLEAF_PATH2            0x0403
-#define JLEAF_PATH3            0x0404
-#define JLEAF_PATH4            0x0405
-#define JLEAF_UID              0x0406
-#define JLEAF_GID              0x0407
-#define JLEAF_MODES            0x0408
-#define JLEAF_FFLAGS           0x0409
-#define JLEAF_PID              0x040A
-#define JLEAF_PPID             0x040B
-#define JLEAF_COMM             0x040C
-#define JLEAF_RESERVED_0D      0x040D
-#define JLEAF_RESERVED_0E      0x040E
-#define JLEAF_RESERVED_0F      0x040F
-#define JLEAF_SYMLINKDATA      0x0410
-#define JLEAF_SEEKPOS          0x0411
-#define JLEAF_INUM             0x0412
-
 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
 
 /*
@@ -391,3 +165,4 @@ struct jrecord {
 };
 
 #endif
+#endif