* 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
#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>
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);
* 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]
}
/*
+ * 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 *
}
/************************************************************************
- * 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 */
}
/************************************************************************
* new VFS equivalents (NMKDIR).
*/
+/*
+ * Journal vop_settattr { a_vp, a_vap, a_cred, a_td }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_write { a_vp, a_uio, a_ioflag, a_cred }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_fsync { a_vp, a_waitfor, a_td }
+ */
static
int
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)
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);
}
return (error);
}
+/*
+ * Journal vop_setacl { a_vp, a_type, a_aclp, a_cred, a_td }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_setextattr { a_vp, a_name, a_uio, a_cred, a_td }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_ncreate { a_ncp, a_vpp, a_cred, a_vap }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nmknod { a_ncp, a_vpp, a_cred, a_vap }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nlink { a_ncp, a_vp, a_cred }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_symlink { a_ncp, a_vpp, a_cred, a_vap, a_target }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nwhiteout { a_ncp, a_cred, a_flags }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nremove { a_ncp, a_cred }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nmkdir { a_ncp, a_vpp, a_cred, a_vap }
+ */
static
int
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);
}
return (error);
}
-
+/*
+ * Journal vop_nrmdir { a_ncp, a_cred }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nrename { a_fncp, a_tncp, a_cred }
+ */
static
int
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);
}
* 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
#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>
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);
* 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]
}
/*
+ * 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 *
}
/************************************************************************
- * 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 */
}
/************************************************************************
* new VFS equivalents (NMKDIR).
*/
+/*
+ * Journal vop_settattr { a_vp, a_vap, a_cred, a_td }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_write { a_vp, a_uio, a_ioflag, a_cred }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_fsync { a_vp, a_waitfor, a_td }
+ */
static
int
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)
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);
}
return (error);
}
+/*
+ * Journal vop_setacl { a_vp, a_type, a_aclp, a_cred, a_td }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_setextattr { a_vp, a_name, a_uio, a_cred, a_td }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_ncreate { a_ncp, a_vpp, a_cred, a_vap }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nmknod { a_ncp, a_vpp, a_cred, a_vap }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nlink { a_ncp, a_vp, a_cred }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_symlink { a_ncp, a_vpp, a_cred, a_vap, a_target }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nwhiteout { a_ncp, a_cred, a_flags }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nremove { a_ncp, a_cred }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nmkdir { a_ncp, a_vpp, a_cred, a_vap }
+ */
static
int
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);
}
return (error);
}
-
+/*
+ * Journal vop_nrmdir { a_ncp, a_cred }
+ */
static
int
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);
}
return (error);
}
+/*
+ * Journal vop_nrename { a_fncp, a_tncp, a_cred }
+ */
static
int
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);
}
* 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)
#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
*/
#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
* 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
*/
#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)
/*
};
#endif
+#endif