* System call switch table.
*
* DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/kern/init_sysent.c,v 1.19 2004/12/24 05:00:17 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.13 2004/11/23 06:32:32 dillon Exp
+ * $DragonFly: src/sys/kern/init_sysent.c,v 1.20 2004/12/29 02:40:02 dillon Exp $
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.14 2004/12/24 05:00:17 dillon Exp
*/
#include "opt_compat.h"
* System call names.
*
* DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/kern/syscalls.c,v 1.19 2004/12/24 05:00:17 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.13 2004/11/23 06:32:32 dillon Exp
+ * $DragonFly: src/sys/kern/syscalls.c,v 1.20 2004/12/29 02:40:02 dillon Exp $
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.14 2004/12/24 05:00:17 dillon Exp
*/
char *syscallnames[] = {
- $DragonFly: src/sys/kern/syscalls.master,v 1.14 2004/12/24 05:00:17 dillon Exp $
+ $DragonFly: src/sys/kern/syscalls.master,v 1.15 2004/12/29 02:40:02 dillon Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
; $FreeBSD: src/sys/kern/syscalls.master,v 1.72.2.10 2002/07/12 08:22:46 alfred Exp $
465 STD BSD { int exec_sys_register(void *entry); }
466 STD BSD { int exec_sys_unregister(int id); }
467 STD BSD { int sys_checkpoint(int type, int fd, pid_t pid, int retval); }
-468 STD BSD { int mountctl(char *path, int op, const void *ctl, int ctllen, void *buf, int buflen); }
+468 STD BSD { int mountctl(const char *path, int op, int fd, const void *ctl, int ctllen, void *buf, int buflen); }
*
*
* $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
- * $DragonFly: src/sys/kern/vfs_default.c,v 1.24 2004/12/24 05:00:17 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_default.c,v 1.25 2004/12/29 02:40:02 dillon Exp $
*/
#include <sys/param.h>
{ &vop_nremove_desc, (void *) vop_compat_nremove },
{ &vop_nrmdir_desc, (void *) vop_compat_nrmdir },
{ &vop_nrename_desc, (void *) vop_compat_nrename },
- { &vop_mountctl_desc, (void *) vop_stdmountctl },
+ { &vop_mountctl_desc, (void *) journal_mountctl },
{ NULL, NULL }
};
return (vp->v_object ? 0 : EINVAL);
}
-/*
- * Standard mount controls. These are overridden when the journal is
- * installed so we only have to 'bootstrap' the journal installation
- * operation here.
- */
-int
-vop_stdmountctl(struct vop_mountctl_args *ap)
-{
- int error = EOPNOTSUPP;
-
- switch(ap->a_op) {
- case MOUNTCTL_INSTALL_VFS_JOURNAL:
- case MOUNTCTL_INSTALL_BLK_JOURNAL:
- default:
- break;
- }
- return (error);
-}
-
/*
* vfs default ops
* used to fill the vfs fucntion table to get reasonable default return values.
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/vfs_jops.c,v 1.2 2004/12/24 05:00:17 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_jops.c,v 1.3 2004/12/29 02:40:02 dillon Exp $
+ */
+/*
+ * Each mount point may have zero or more independantly configured journals
+ * attached to it. Each journal is represented by a memory FIFO and worker
+ * thread. Journal events are streamed through the FIFO to the thread,
+ * batched up (typically on one-second intervals), and written out by the
+ * thread.
+ *
+ * Journal vnode ops are executed instead of mnt_vn_norm_ops when one or
+ * more journals have been installed on a mount point. It becomes the
+ * responsibility of the journal op to call the underlying normal op as
+ * appropriate.
+ *
+ * The journaling protocol is intended to evolve into a two-way stream
+ * whereby transaction IDs can be acknowledged by the journaling target
+ * when the data has been committed to hard storage. Both implicit and
+ * explicit acknowledgement schemes will be supported, depending on the
+ * sophistication of the journaling stream, plus resynchronization and
+ * restart when a journaling stream is interrupted. This information will
+ * also be made available to journaling-aware filesystems to allow better
+ * management of their own physical storage synchronization mechanisms as
+ * well as to allow such filesystems to take direct advantage of the kernel's
+ * journaling layer so they don't have to roll their own.
+ *
+ * In addition, the journaling thread will have access to much larger
+ * spooling areas then the memory buffer is able to provide by e.g.
+ * reserving swap space, in order to absorb potentially long interruptions
+ * of off-site journaling streams, and to prevent 'slow' off-site linkages
+ * from radically slowing down local filesystem operations.
+ *
+ * Because of the non-trivial algorithms the journaling system will be
+ * required to support, use of a worker thread is mandatory. Efficiencies
+ * are maintained by utilitizing the memory FIFO to batch transactions when
+ * possible, reducing the number of gratuitous thread switches and taking
+ * advantage of cpu caches through the use of shorter batched code paths
+ * rather then trying to do everything in the context of the process
+ * originating the filesystem op.
*/
#include <sys/param.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <sys/poll.h>
+#include <sys/mountctl.h>
+#include <sys/file.h>
#include <machine/limits.h>
#include <vm/vm_pager.h>
#include <vm/vnode_pager.h>
+#include <sys/file2.h>
+#include <sys/thread2.h>
+
+static int journal_attach(struct mount *mp);
+static void journal_detach(struct mount *mp);
+static int journal_install_vfs_journal(struct mount *mp, struct file *fp,
+ const struct mountctl_install_journal *info);
+static int journal_remove_vfs_journal(struct mount *mp,
+ const struct mountctl_remove_journal *info);
+static int journal_resync_vfs_journal(struct mount *mp, const void *ctl);
+static void journal_thread(void *info);
+static void journal_write_record(struct journal *jo, const char *ctl,
+ const char *buf, int bytes);
+static void journal_write(struct journal *jo, const char *buf, int bytes);
+
+static int journal_nmkdir(struct vop_nmkdir_args *ap);
+
static struct vnodeopv_entry_desc journal_vnodeop_entries[] = {
- { &vop_default_desc, vop_journal_operate_ap },
-/* { &vop_mountctl_desc, NULL },*/
- { NULL, NULL }
+ { &vop_default_desc, vop_journal_operate_ap },
+ { &vop_mountctl_desc, (void *)journal_mountctl },
+ { &vop_nmkdir_desc, (void *)journal_nmkdir },
+ { NULL, NULL }
};
+static MALLOC_DEFINE(M_JOURNAL, "journal", "Journaling structure");
+static MALLOC_DEFINE(M_JFIFO, "journal-fifo", "Journal FIFO");
+
int
+journal_mountctl(struct vop_mountctl_args *ap)
+{
+ struct mount *mp;
+ int error = 0;
+
+ mp = ap->a_head.a_ops->vv_mount;
+ KKASSERT(mp);
+
+ if (mp->mnt_vn_journal_ops == NULL) {
+ switch(ap->a_op) {
+ case MOUNTCTL_INSTALL_VFS_JOURNAL:
+ error = journal_attach(mp);
+ if (error == 0 && ap->a_ctllen != sizeof(struct mountctl_install_journal))
+ error = EINVAL;
+ if (error == 0 && ap->a_fp == NULL)
+ error = EBADF;
+ if (error == 0)
+ error = journal_install_vfs_journal(mp, ap->a_fp, ap->a_ctl);
+ if (TAILQ_EMPTY(&mp->mnt_jlist))
+ journal_detach(mp);
+ break;
+ case MOUNTCTL_REMOVE_VFS_JOURNAL:
+ case MOUNTCTL_RESYNC_VFS_JOURNAL:
+ error = EINVAL;
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ } else {
+ switch(ap->a_op) {
+ case MOUNTCTL_INSTALL_VFS_JOURNAL:
+ if (ap->a_ctllen != sizeof(struct mountctl_install_journal))
+ error = EINVAL;
+ if (error == 0 && ap->a_fp == NULL)
+ error = EBADF;
+ if (error == 0)
+ error = journal_install_vfs_journal(mp, ap->a_fp, ap->a_ctl);
+ break;
+ case MOUNTCTL_REMOVE_VFS_JOURNAL:
+ if (ap->a_ctllen != sizeof(struct mountctl_remove_journal))
+ error = EINVAL;
+ if (error == 0)
+ error = journal_remove_vfs_journal(mp, ap->a_ctl);
+ if (TAILQ_EMPTY(&mp->mnt_jlist))
+ journal_detach(mp);
+ break;
+ case MOUNTCTL_RESYNC_VFS_JOURNAL:
+ if (ap->a_ctllen != 0)
+ error = EINVAL;
+ error = journal_resync_vfs_journal(mp, ap->a_ctl);
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ }
+ return (error);
+}
+
+/*
+ * High level mount point setup. When a
+ */
+static int
journal_attach(struct mount *mp)
{
- vfs_add_vnodeops(mp, &mp->mnt_vn_journal_ops, journal_vnodeop_entries);
- return(0);
+ vfs_add_vnodeops(mp, &mp->mnt_vn_journal_ops, journal_vnodeop_entries);
+ return(0);
}
-void
+static void
journal_detach(struct mount *mp)
{
- if (mp->mnt_vn_journal_ops)
- vfs_rm_vnodeops(&mp->mnt_vn_journal_ops);
+ if (mp->mnt_vn_journal_ops)
+ vfs_rm_vnodeops(&mp->mnt_vn_journal_ops);
+}
+
+/*
+ * Install a journal on a mount point
+ */
+static int
+journal_install_vfs_journal(struct mount *mp, struct file *fp,
+ const struct mountctl_install_journal *info)
+{
+ struct journal *jo;
+ int error = 0;
+ int size;
+
+ jo = malloc(sizeof(struct journal), M_JOURNAL, M_WAITOK|M_ZERO);
+ bcopy(info->id, jo->id, sizeof(jo->id));
+ jo->flags = info->flags & ~(MC_JOURNAL_ACTIVE | MC_JOURNAL_STOP_REQ);
+
+ /*
+ * Memory FIFO size, round to nearest power of 2
+ */
+ if (info->flags & MC_JOURNAL_MBSIZE_PROVIDED) {
+ if (info->membufsize < 65536)
+ size = 65536;
+ else if (info->membufsize > 128 * 1024 * 1024)
+ size = 128 * 1024 * 1024;
+ else
+ size = (int)info->membufsize;
+ } else {
+ size = 1024 * 1024;
+ }
+ jo->fifo.size = 1;
+ while (jo->fifo.size < size)
+ jo->fifo.size <<= 1;
+
+ /*
+ * Other parameters. If not specified the starting transaction id
+ * will be the current date.
+ */
+ if (info->flags & MC_JOURNAL_TRANSID_PROVIDED) {
+ jo->transid = info->transid;
+ } else {
+ struct timespec ts;
+ getnanotime(&ts);
+ jo->transid = ((int64_t)ts.tv_sec << 30) | ts.tv_nsec;
+ }
+
+ jo->fp = fp;
+
+ /*
+ * Allocate the memory FIFO
+ */
+ jo->fifo.mask = jo->fifo.size - 1;
+ jo->fifo.membase = malloc(jo->fifo.size, M_JFIFO, M_WAITOK|M_ZERO|M_NULLOK);
+ if (jo->fifo.membase == NULL)
+ error = ENOMEM;
+
+ if (error) {
+ free(jo, M_JOURNAL);
+ } else {
+ fhold(fp);
+ jo->flags |= MC_JOURNAL_ACTIVE;
+ lwkt_create(journal_thread, jo, NULL, &jo->thread,
+ TDF_STOPREQ, -1, "journal %.*s", JIDMAX, jo->id);
+ lwkt_setpri(&jo->thread, TDPRI_KERN_DAEMON);
+ lwkt_schedule(&jo->thread);
+ journal_write_record(jo, "INSTALL", NULL, 0);
+
+ TAILQ_INSERT_TAIL(&mp->mnt_jlist, jo, jentry);
+ }
+ return(error);
+}
+
+static int
+journal_remove_vfs_journal(struct mount *mp, const struct mountctl_remove_journal *info)
+{
+ struct journal *jo;
+ int error;
+
+ TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
+ if (bcmp(jo->id, info->id, sizeof(jo->id)) == 0)
+ break;
+ }
+ if (jo) {
+ error = 0;
+ TAILQ_REMOVE(&mp->mnt_jlist, jo, jentry);
+ journal_write_record(jo, "REMOVE", NULL, 0); /* XXX sequencing */
+ jo->flags |= MC_JOURNAL_STOP_REQ | (info->flags & MC_JOURNAL_STOP_IMM);
+ wakeup(&jo->fifo);
+ while (jo->flags & MC_JOURNAL_ACTIVE) {
+ tsleep(jo, 0, "jwait", 0);
+ }
+ lwkt_free_thread(&jo->thread); /* XXX SMP */
+ if (jo->fp)
+ fdrop(jo->fp, curthread);
+ if (jo->fifo.membase)
+ free(jo->fifo.membase, M_JFIFO);
+ free(jo, M_JOURNAL);
+ } else {
+ error = EINVAL;
+ }
+ return (error);
+}
+
+static int
+journal_resync_vfs_journal(struct mount *mp, const void *ctl)
+{
+ return(EINVAL);
+}
+
+static void
+journal_thread(void *info)
+{
+ struct journal *jo = info;
+ int bytes;
+ int error;
+ int res;
+
+ for (;;) {
+ bytes = (jo->fifo.windex - jo->fifo.rindex) & jo->fifo.mask;
+ if (bytes == 0 || (jo->flags & MC_JOURNAL_STOP_IMM)) {
+ if (jo->flags & MC_JOURNAL_STOP_REQ)
+ break;
+ tsleep(&jo->fifo, 0, "jfifo", 0); /* XXX add heartbeat */
+ }
+ if (bytes > jo->fifo.size - jo->fifo.windex)
+ bytes = jo->fifo.size - jo->fifo.windex;
+ error = fp_write(jo->fp, jo->fifo.membase + jo->fifo.rindex, bytes, &res);
+ if (error) {
+ printf("journal_thread(%s) write, error %d\n", jo->id, error);
+ jo->fifo.rindex = jo->fifo.windex; /* XXX flag out-of-sync */
+ } else {
+ printf("journal_thread(%s) write %d\n", jo->id, res);
+ jo->fifo.rindex = (jo->fifo.rindex + res) & jo->fifo.mask;
+ if (jo->flags & MC_JOURNAL_WWAIT) {
+ jo->flags &= ~MC_JOURNAL_WWAIT; /* XXX hysteresis */
+ wakeup(&jo->fifo.windex);
+ }
+ }
+ }
+ jo->flags &= ~MC_JOURNAL_ACTIVE;
+ wakeup(jo);
+ wakeup(&jo->fifo.windex);
+}
+
+static
+void
+journal_write_record(struct journal *jo, const char *ctl,
+ const char *buf, int bytes)
+{
+ char head[64];
+
+ if (jo->flags & MC_JOURNAL_STOP_REQ)
+ return;
+ snprintf(head, sizeof(head), "%016llx %s\n", jo->transid, ctl);
+ /* XXX locking (token) or cmpexgl space reservation */
+ ++jo->transid; /* XXX embed nanotime, force monotonic */
+ journal_write(jo, head, strlen(head));
+ if (bytes)
+ journal_write(jo, buf, bytes);
+}
+
+static
+void
+journal_write(struct journal *jo, const char *buf, int bytes)
+{
+ int avail;
+
+ while (bytes && (jo->flags & MC_JOURNAL_ACTIVE)) {
+ avail = (jo->fifo.windex - jo->fifo.rindex) & jo->fifo.mask;
+ avail = jo->fifo.size - avail - 1;
+ if (avail == 0) {
+ if (jo->flags & MC_JOURNAL_STOP_IMM)
+ break;
+ jo->flags |= MC_JOURNAL_WWAIT;
+ tsleep(&jo->fifo.windex, 0, "jwrite", 0);
+ continue;
+ }
+ if (avail > jo->fifo.size - jo->fifo.windex)
+ avail = jo->fifo.size - jo->fifo.windex;
+ if (avail > bytes)
+ avail = bytes;
+ bcopy(buf, jo->fifo.membase + jo->fifo.windex, avail);
+ bytes -= avail;
+ jo->fifo.windex = (jo->fifo.windex + avail) & jo->fifo.mask;
+ tsleep(&jo->fifo, 0, "jfifo", 0); /* XXX hysteresis */
+ }
+}
+
+/************************************************************************
+ * JOURNAL VNOPS *
+ ************************************************************************/
+
+static
+int
+journal_nmkdir(struct vop_nmkdir_args *ap)
+{
+ int error;
+
+ printf("JMKDIR %s\n", ap->a_ncp->nc_name);
+ error = vop_journal_operate_ap(&ap->a_head);
+ return (error);
}
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/vfs_journal.c,v 1.2 2004/12/24 05:00:17 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_journal.c,v 1.3 2004/12/29 02:40:02 dillon Exp $
+ */
+/*
+ * Each mount point may have zero or more independantly configured journals
+ * attached to it. Each journal is represented by a memory FIFO and worker
+ * thread. Journal events are streamed through the FIFO to the thread,
+ * batched up (typically on one-second intervals), and written out by the
+ * thread.
+ *
+ * Journal vnode ops are executed instead of mnt_vn_norm_ops when one or
+ * more journals have been installed on a mount point. It becomes the
+ * responsibility of the journal op to call the underlying normal op as
+ * appropriate.
+ *
+ * The journaling protocol is intended to evolve into a two-way stream
+ * whereby transaction IDs can be acknowledged by the journaling target
+ * when the data has been committed to hard storage. Both implicit and
+ * explicit acknowledgement schemes will be supported, depending on the
+ * sophistication of the journaling stream, plus resynchronization and
+ * restart when a journaling stream is interrupted. This information will
+ * also be made available to journaling-aware filesystems to allow better
+ * management of their own physical storage synchronization mechanisms as
+ * well as to allow such filesystems to take direct advantage of the kernel's
+ * journaling layer so they don't have to roll their own.
+ *
+ * In addition, the journaling thread will have access to much larger
+ * spooling areas then the memory buffer is able to provide by e.g.
+ * reserving swap space, in order to absorb potentially long interruptions
+ * of off-site journaling streams, and to prevent 'slow' off-site linkages
+ * from radically slowing down local filesystem operations.
+ *
+ * Because of the non-trivial algorithms the journaling system will be
+ * required to support, use of a worker thread is mandatory. Efficiencies
+ * are maintained by utilitizing the memory FIFO to batch transactions when
+ * possible, reducing the number of gratuitous thread switches and taking
+ * advantage of cpu caches through the use of shorter batched code paths
+ * rather then trying to do everything in the context of the process
+ * originating the filesystem op.
*/
#include <sys/param.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <sys/poll.h>
+#include <sys/mountctl.h>
+#include <sys/file.h>
#include <machine/limits.h>
#include <vm/vm_pager.h>
#include <vm/vnode_pager.h>
+#include <sys/file2.h>
+#include <sys/thread2.h>
+
+static int journal_attach(struct mount *mp);
+static void journal_detach(struct mount *mp);
+static int journal_install_vfs_journal(struct mount *mp, struct file *fp,
+ const struct mountctl_install_journal *info);
+static int journal_remove_vfs_journal(struct mount *mp,
+ const struct mountctl_remove_journal *info);
+static int journal_resync_vfs_journal(struct mount *mp, const void *ctl);
+static void journal_thread(void *info);
+static void journal_write_record(struct journal *jo, const char *ctl,
+ const char *buf, int bytes);
+static void journal_write(struct journal *jo, const char *buf, int bytes);
+
+static int journal_nmkdir(struct vop_nmkdir_args *ap);
+
static struct vnodeopv_entry_desc journal_vnodeop_entries[] = {
- { &vop_default_desc, vop_journal_operate_ap },
-/* { &vop_mountctl_desc, NULL },*/
- { NULL, NULL }
+ { &vop_default_desc, vop_journal_operate_ap },
+ { &vop_mountctl_desc, (void *)journal_mountctl },
+ { &vop_nmkdir_desc, (void *)journal_nmkdir },
+ { NULL, NULL }
};
+static MALLOC_DEFINE(M_JOURNAL, "journal", "Journaling structure");
+static MALLOC_DEFINE(M_JFIFO, "journal-fifo", "Journal FIFO");
+
int
+journal_mountctl(struct vop_mountctl_args *ap)
+{
+ struct mount *mp;
+ int error = 0;
+
+ mp = ap->a_head.a_ops->vv_mount;
+ KKASSERT(mp);
+
+ if (mp->mnt_vn_journal_ops == NULL) {
+ switch(ap->a_op) {
+ case MOUNTCTL_INSTALL_VFS_JOURNAL:
+ error = journal_attach(mp);
+ if (error == 0 && ap->a_ctllen != sizeof(struct mountctl_install_journal))
+ error = EINVAL;
+ if (error == 0 && ap->a_fp == NULL)
+ error = EBADF;
+ if (error == 0)
+ error = journal_install_vfs_journal(mp, ap->a_fp, ap->a_ctl);
+ if (TAILQ_EMPTY(&mp->mnt_jlist))
+ journal_detach(mp);
+ break;
+ case MOUNTCTL_REMOVE_VFS_JOURNAL:
+ case MOUNTCTL_RESYNC_VFS_JOURNAL:
+ error = EINVAL;
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ } else {
+ switch(ap->a_op) {
+ case MOUNTCTL_INSTALL_VFS_JOURNAL:
+ if (ap->a_ctllen != sizeof(struct mountctl_install_journal))
+ error = EINVAL;
+ if (error == 0 && ap->a_fp == NULL)
+ error = EBADF;
+ if (error == 0)
+ error = journal_install_vfs_journal(mp, ap->a_fp, ap->a_ctl);
+ break;
+ case MOUNTCTL_REMOVE_VFS_JOURNAL:
+ if (ap->a_ctllen != sizeof(struct mountctl_remove_journal))
+ error = EINVAL;
+ if (error == 0)
+ error = journal_remove_vfs_journal(mp, ap->a_ctl);
+ if (TAILQ_EMPTY(&mp->mnt_jlist))
+ journal_detach(mp);
+ break;
+ case MOUNTCTL_RESYNC_VFS_JOURNAL:
+ if (ap->a_ctllen != 0)
+ error = EINVAL;
+ error = journal_resync_vfs_journal(mp, ap->a_ctl);
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ }
+ return (error);
+}
+
+/*
+ * High level mount point setup. When a
+ */
+static int
journal_attach(struct mount *mp)
{
- vfs_add_vnodeops(mp, &mp->mnt_vn_journal_ops, journal_vnodeop_entries);
- return(0);
+ vfs_add_vnodeops(mp, &mp->mnt_vn_journal_ops, journal_vnodeop_entries);
+ return(0);
}
-void
+static void
journal_detach(struct mount *mp)
{
- if (mp->mnt_vn_journal_ops)
- vfs_rm_vnodeops(&mp->mnt_vn_journal_ops);
+ if (mp->mnt_vn_journal_ops)
+ vfs_rm_vnodeops(&mp->mnt_vn_journal_ops);
+}
+
+/*
+ * Install a journal on a mount point
+ */
+static int
+journal_install_vfs_journal(struct mount *mp, struct file *fp,
+ const struct mountctl_install_journal *info)
+{
+ struct journal *jo;
+ int error = 0;
+ int size;
+
+ jo = malloc(sizeof(struct journal), M_JOURNAL, M_WAITOK|M_ZERO);
+ bcopy(info->id, jo->id, sizeof(jo->id));
+ jo->flags = info->flags & ~(MC_JOURNAL_ACTIVE | MC_JOURNAL_STOP_REQ);
+
+ /*
+ * Memory FIFO size, round to nearest power of 2
+ */
+ if (info->flags & MC_JOURNAL_MBSIZE_PROVIDED) {
+ if (info->membufsize < 65536)
+ size = 65536;
+ else if (info->membufsize > 128 * 1024 * 1024)
+ size = 128 * 1024 * 1024;
+ else
+ size = (int)info->membufsize;
+ } else {
+ size = 1024 * 1024;
+ }
+ jo->fifo.size = 1;
+ while (jo->fifo.size < size)
+ jo->fifo.size <<= 1;
+
+ /*
+ * Other parameters. If not specified the starting transaction id
+ * will be the current date.
+ */
+ if (info->flags & MC_JOURNAL_TRANSID_PROVIDED) {
+ jo->transid = info->transid;
+ } else {
+ struct timespec ts;
+ getnanotime(&ts);
+ jo->transid = ((int64_t)ts.tv_sec << 30) | ts.tv_nsec;
+ }
+
+ jo->fp = fp;
+
+ /*
+ * Allocate the memory FIFO
+ */
+ jo->fifo.mask = jo->fifo.size - 1;
+ jo->fifo.membase = malloc(jo->fifo.size, M_JFIFO, M_WAITOK|M_ZERO|M_NULLOK);
+ if (jo->fifo.membase == NULL)
+ error = ENOMEM;
+
+ if (error) {
+ free(jo, M_JOURNAL);
+ } else {
+ fhold(fp);
+ jo->flags |= MC_JOURNAL_ACTIVE;
+ lwkt_create(journal_thread, jo, NULL, &jo->thread,
+ TDF_STOPREQ, -1, "journal %.*s", JIDMAX, jo->id);
+ lwkt_setpri(&jo->thread, TDPRI_KERN_DAEMON);
+ lwkt_schedule(&jo->thread);
+ journal_write_record(jo, "INSTALL", NULL, 0);
+
+ TAILQ_INSERT_TAIL(&mp->mnt_jlist, jo, jentry);
+ }
+ return(error);
+}
+
+static int
+journal_remove_vfs_journal(struct mount *mp, const struct mountctl_remove_journal *info)
+{
+ struct journal *jo;
+ int error;
+
+ TAILQ_FOREACH(jo, &mp->mnt_jlist, jentry) {
+ if (bcmp(jo->id, info->id, sizeof(jo->id)) == 0)
+ break;
+ }
+ if (jo) {
+ error = 0;
+ TAILQ_REMOVE(&mp->mnt_jlist, jo, jentry);
+ journal_write_record(jo, "REMOVE", NULL, 0); /* XXX sequencing */
+ jo->flags |= MC_JOURNAL_STOP_REQ | (info->flags & MC_JOURNAL_STOP_IMM);
+ wakeup(&jo->fifo);
+ while (jo->flags & MC_JOURNAL_ACTIVE) {
+ tsleep(jo, 0, "jwait", 0);
+ }
+ lwkt_free_thread(&jo->thread); /* XXX SMP */
+ if (jo->fp)
+ fdrop(jo->fp, curthread);
+ if (jo->fifo.membase)
+ free(jo->fifo.membase, M_JFIFO);
+ free(jo, M_JOURNAL);
+ } else {
+ error = EINVAL;
+ }
+ return (error);
+}
+
+static int
+journal_resync_vfs_journal(struct mount *mp, const void *ctl)
+{
+ return(EINVAL);
+}
+
+static void
+journal_thread(void *info)
+{
+ struct journal *jo = info;
+ int bytes;
+ int error;
+ int res;
+
+ for (;;) {
+ bytes = (jo->fifo.windex - jo->fifo.rindex) & jo->fifo.mask;
+ if (bytes == 0 || (jo->flags & MC_JOURNAL_STOP_IMM)) {
+ if (jo->flags & MC_JOURNAL_STOP_REQ)
+ break;
+ tsleep(&jo->fifo, 0, "jfifo", 0); /* XXX add heartbeat */
+ }
+ if (bytes > jo->fifo.size - jo->fifo.windex)
+ bytes = jo->fifo.size - jo->fifo.windex;
+ error = fp_write(jo->fp, jo->fifo.membase + jo->fifo.rindex, bytes, &res);
+ if (error) {
+ printf("journal_thread(%s) write, error %d\n", jo->id, error);
+ jo->fifo.rindex = jo->fifo.windex; /* XXX flag out-of-sync */
+ } else {
+ printf("journal_thread(%s) write %d\n", jo->id, res);
+ jo->fifo.rindex = (jo->fifo.rindex + res) & jo->fifo.mask;
+ if (jo->flags & MC_JOURNAL_WWAIT) {
+ jo->flags &= ~MC_JOURNAL_WWAIT; /* XXX hysteresis */
+ wakeup(&jo->fifo.windex);
+ }
+ }
+ }
+ jo->flags &= ~MC_JOURNAL_ACTIVE;
+ wakeup(jo);
+ wakeup(&jo->fifo.windex);
+}
+
+static
+void
+journal_write_record(struct journal *jo, const char *ctl,
+ const char *buf, int bytes)
+{
+ char head[64];
+
+ if (jo->flags & MC_JOURNAL_STOP_REQ)
+ return;
+ snprintf(head, sizeof(head), "%016llx %s\n", jo->transid, ctl);
+ /* XXX locking (token) or cmpexgl space reservation */
+ ++jo->transid; /* XXX embed nanotime, force monotonic */
+ journal_write(jo, head, strlen(head));
+ if (bytes)
+ journal_write(jo, buf, bytes);
+}
+
+static
+void
+journal_write(struct journal *jo, const char *buf, int bytes)
+{
+ int avail;
+
+ while (bytes && (jo->flags & MC_JOURNAL_ACTIVE)) {
+ avail = (jo->fifo.windex - jo->fifo.rindex) & jo->fifo.mask;
+ avail = jo->fifo.size - avail - 1;
+ if (avail == 0) {
+ if (jo->flags & MC_JOURNAL_STOP_IMM)
+ break;
+ jo->flags |= MC_JOURNAL_WWAIT;
+ tsleep(&jo->fifo.windex, 0, "jwrite", 0);
+ continue;
+ }
+ if (avail > jo->fifo.size - jo->fifo.windex)
+ avail = jo->fifo.size - jo->fifo.windex;
+ if (avail > bytes)
+ avail = bytes;
+ bcopy(buf, jo->fifo.membase + jo->fifo.windex, avail);
+ bytes -= avail;
+ jo->fifo.windex = (jo->fifo.windex + avail) & jo->fifo.mask;
+ tsleep(&jo->fifo, 0, "jfifo", 0); /* XXX hysteresis */
+ }
+}
+
+/************************************************************************
+ * JOURNAL VNOPS *
+ ************************************************************************/
+
+static
+int
+journal_nmkdir(struct vop_nmkdir_args *ap)
+{
+ int error;
+
+ printf("JMKDIR %s\n", ap->a_ncp->nc_name);
+ error = vop_journal_operate_ap(&ap->a_head);
+ return (error);
}
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/vfs_mount.c,v 1.3 2004/12/17 00:18:07 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_mount.c,v 1.4 2004/12/29 02:40:02 dillon Exp $
*/
/*
}
if (vfsp == NULL)
return (ENODEV);
- mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
+ mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK);
bzero((char *)mp, (u_long)sizeof(struct mount));
lockinit(&mp->mnt_lock, 0, "vfslock", VLKTIMEOUT, LK_NOPAUSE);
vfs_busy(mp, LK_NOWAIT, NULL, td);
TAILQ_INIT(&mp->mnt_nvnodelist);
TAILQ_INIT(&mp->mnt_reservedvnlist);
+ TAILQ_INIT(&mp->mnt_jlist);
mp->mnt_nvnodelistsize = 0;
mp->mnt_vfc = vfsp;
mp->mnt_op = vfsp->vfc_vfsops;
*
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
* $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.51 2004/12/28 04:39:59 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.52 2004/12/29 02:40:02 dillon Exp $
*/
#include <sys/param.h>
mp = malloc(sizeof(struct mount), M_MOUNT, M_ZERO|M_WAITOK);
TAILQ_INIT(&mp->mnt_nvnodelist);
TAILQ_INIT(&mp->mnt_reservedvnlist);
+ TAILQ_INIT(&mp->mnt_jlist);
mp->mnt_nvnodelistsize = 0;
lockinit(&mp->mnt_lock, 0, "vfslock", 0, LK_NOPAUSE);
vfs_busy(mp, LK_NOWAIT, NULL, td);
}
/*
- * mountctl(char *path, int op, const void *ctl, int ctllen,
+ * mountctl(char *path, int op, int fd, const void *ctl, int ctllen,
* void *buf, int buflen)
*
* This function operates on a mount point and executes the specified
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
void *ctl = NULL;
void *buf = NULL;
char *path = NULL;
buf = malloc(uap->buflen + 1, M_TEMP, M_WAITOK|M_ZERO);
/*
+ * Validate the descriptor
+ */
+ if (uap->fd == -1) {
+ fp = NULL;
+ } else if ((u_int)uap->fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[uap->fd]) == NULL) {
+ error = EBADF;
+ goto done;
+ }
+ if (fp)
+ fhold(fp);
+
+ /*
* Execute the internal kernel function and clean up.
*/
- error = kern_mountctl(path, uap->op, ctl, uap->ctllen, buf, uap->buflen, &uap->sysmsg_result);
+ error = kern_mountctl(path, uap->op, fp, ctl, uap->ctllen, buf, uap->buflen, &uap->sysmsg_result);
+ if (fp)
+ fdrop(fp, td);
if (error == 0 && uap->sysmsg_result > 0)
error = copyout(buf, uap->buf, uap->sysmsg_result);
done:
* and calling vop_mountctl().
*/
int
-kern_mountctl(const char *path, int op, const void *ctl, int ctllen,
+kern_mountctl(const char *path, int op, struct file *fp,
+ const void *ctl, int ctllen,
void *buf, int buflen, int *res)
{
- struct thread *td = curthread;
struct vnode *vp;
struct mount *mp;
struct nlookupdata nd;
vput(vp);
return (EINVAL);
}
- error = vop_mountctl(mp->mnt_vn_use_ops, op, ctl, ctllen,
+ error = vop_mountctl(mp->mnt_vn_use_ops, op, fp, ctl, ctllen,
buf, buflen, res);
vput(vp);
return (error);
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/vfs_vopops.c,v 1.12 2004/12/24 05:00:17 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_vopops.c,v 1.13 2004/12/29 02:40:02 dillon Exp $
*/
#include <sys/param.h>
}
int
-vop_mountctl(struct vop_ops *ops, int op, const void *ctl, int ctllen, void *buf, int buflen, int *res)
+vop_mountctl(struct vop_ops *ops, int op, struct file *fp,
+ const void *ctl, int ctllen, void *buf, int buflen, int *res)
{
struct vop_mountctl_args ap;
int error;
ap.a_head.a_ops = ops;
ap.a_op = op;
ap.a_ctl = ctl;
+ ap.a_fp = fp;
ap.a_ctllen = ctllen;
ap.a_buf = buf;
ap.a_buflen = buflen;
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/sys/kern_syscall.h,v 1.22 2004/12/24 05:00:22 dillon Exp $
+ * $DragonFly: src/sys/sys/kern_syscall.h,v 1.23 2004/12/29 02:40:03 dillon Exp $
*/
#ifndef _SYS_KERN_SYSCALL_H_
int kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res);
int kern_link(struct nlookupdata *nd, struct nlookupdata *linknd);
int kern_lseek(int fd, off_t offset, int whence, off_t *res);
-int kern_mountctl(const char *path, int op, const void *ctl, int ctllen,
+int kern_mountctl(const char *path, int op, struct file *fp,
+ const void *ctl, int ctllen,
void *buf, int buflen, int *res);
int kern_mkdir(struct nlookupdata *nd, int mode);
int kern_mkfifo(struct nlookupdata *nd, int mode);
*
* @(#)mount.h 8.21 (Berkeley) 5/20/95
* $FreeBSD: src/sys/sys/mount.h,v 1.89.2.7 2003/04/04 20:35:57 tegge Exp $
- * $DragonFly: src/sys/sys/mount.h,v 1.15 2004/12/17 00:18:09 dillon Exp $
+ * $DragonFly: src/sys/sys/mount.h,v 1.16 2004/12/29 02:40:03 dillon Exp $
*/
#ifndef _SYS_MOUNT_H_
#endif
struct thread;
+struct journal;
struct vop_ops;
+struct vop_mountctl_args;
typedef struct fsid { int32_t val[2]; } fsid_t; /* file system id type */
* vector via namecache->nc_mount.
*/
TAILQ_HEAD(vnodelst, vnode);
+TAILQ_HEAD(journallst, journal);
struct mount {
TAILQ_ENTRY(mount) mnt_list; /* mount list */
struct vop_ops *mnt_vn_spec_ops; /* for use by the VFS */
struct vop_ops *mnt_vn_fifo_ops; /* for use by the VFS */
struct namecache *mnt_ncp; /* NCF_MNTPT ncp */
+
+ struct journallst mnt_jlist; /* list of active journals */
};
+
#endif /* _KERNEL || _KERNEL_STRUCTURES */
/*
int vfs_stduninit (struct vfsconf *);
int vfs_stdextattrctl (struct mount *mp, int cmd, const char *attrname,
caddr_t arg, struct thread *p);
+int journal_mountctl(struct vop_mountctl_args *ap);
#else /* !_KERNEL */
int fhstat (const struct fhandle *, struct stat *);
int fhstatfs (const struct fhandle *, struct statfs *);
-int journal_attach(struct mount *mp);
-int journal_detach(struct mount *mp);
-
/* C library stuff */
void endvfsent (void);
struct ovfsconf *getvfsbyname (const char *);
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/sys/mountctl.h,v 1.1 2004/12/24 05:00:22 dillon Exp $
+ * $DragonFly: src/sys/sys/mountctl.h,v 1.2 2004/12/29 02:40:03 dillon Exp $
*/
/*
+ * General constants
+ */
+
+#define JIDMAX 32 /* id string buf[] size (incls \0) */
+
+/*
* Data structures for the journaling API
*/
#define MOUNTCTL_JOURNAL_BLK_STATUS 11
struct mountctl_install_journal {
- int id; /* journal identifier */
+ char id[JIDMAX];
int flags; /* journaling flags */
- int fd; /* streaming descriptor (-1 to close) */
int unused01;
int64_t membufsize; /* backing store */
int64_t swapbufsize; /* backing store */
#define MC_JOURNAL_REVERSABLE 0x00000001 /* reversable log */
#define MC_JOURNAL_BINARY 0x00000002 /* use binary format */
-#define MC_JOURNAL_UNUSED04 0x00000004
+#define MC_JOURNAL_ACTIVE 0x00000004 /* journal is active */
#define MC_JOURNAL_STREAM_TWO_WAY 0x00000008 /* trans id ack */
-#define MC_JOURNAL_FD_PROVIDED 0x00000100 /* stream desc */
+#define MC_JOURNAL_STOP_REQ 0x00000010 /* stop request pend */
+#define MC_JOURNAL_STOP_IMM 0x00000020 /* do not flush */
+#define MC_JOURNAL_WWAIT 0x00000040 /* write stall */
#define MC_JOURNAL_MBSIZE_PROVIDED 0x00000200 /* data space */
#define MC_JOURNAL_SWSIZE_PROVIDED 0x00000400 /* data space */
#define MC_JOURNAL_TRANSID_PROVIDED 0x00000800 /* restart transid */
#define MC_JOURNAL_STALLERROR_PROVIDED 0x00002000 /* restart transid */
struct mountctl_remove_journal {
- int id;
+ char id[JIDMAX];
int flags;
};
#define MC_JOURNAL_REMOVE_ASSYNC 0x00000002 /* asynchronous op */
struct mountctl_journal_status {
- int id;
+ char id[JIDMAX];
int flags;
- int fd;
int64_t membufsize;
int64_t membufused;
int64_t membufqueued;
#define MC_JOURNAL_STATUS_NEXT 0x80000000 /* find next id */
+#if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
+
+/*
+ * Support structures for the generic journaling structure
+ */
+struct journal_memfifo {
+ int size; /* size (power of two) */
+ int mask; /* index mask (size - 1) */
+ int rindex; /* stream reader index */
+ int xindex; /* last acked / reader restart */
+ int windex; /* stream writer index */
+ char *membase; /* memory buffer representing the FIFO */
+};
+
+/*
+ * 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;
+ struct journal_memfifo fifo;
+ struct thread thread;
+};
+#endif
# System call argument table.
# DO NOT EDIT-- this file is automatically generated.
-# $DragonFly: src/sys/sys/Attic/syscall-args,v 1.3 2004/12/24 05:00:22 dillon Exp $
+# $DragonFly: src/sys/sys/Attic/syscall-args,v 1.4 2004/12/29 02:40:03 dillon Exp $
-# Created from DragonFly: src/sys/kern/syscalls.master,v 1.13 2004/11/23 06:32:32 dillon Exp
+# Created from DragonFly: src/sys/kern/syscalls.master,v 1.14 2004/12/24 05:00:17 dillon Exp
int syscall nosys nosys_args
void exit sys_exit sys_exit_args int rval
int exec_sys_register exec_sys_register exec_sys_register_args void * entry
int exec_sys_unregister exec_sys_unregister exec_sys_unregister_args int id
int sys_checkpoint sys_checkpoint sys_checkpoint_args int type int fd pid_t pid int retval
-int mountctl mountctl mountctl_args char * path int op const void * ctl int ctllen void * buf int buflen
+int mountctl mountctl mountctl_args char * path int op int fd const void * ctl int ctllen void * buf int buflen
* System call hiders.
*
* DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/syscall-hide.h,v 1.20 2004/12/24 05:00:22 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.13 2004/11/23 06:32:32 dillon Exp
+ * $DragonFly: src/sys/sys/syscall-hide.h,v 1.21 2004/12/29 02:40:03 dillon Exp $
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.14 2004/12/24 05:00:17 dillon Exp
*/
HIDE_POSIX(fork)
* System call numbers.
*
* DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/syscall.h,v 1.20 2004/12/24 05:00:22 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.13 2004/11/23 06:32:32 dillon Exp
+ * $DragonFly: src/sys/sys/syscall.h,v 1.21 2004/12/29 02:40:03 dillon Exp $
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.14 2004/12/24 05:00:17 dillon Exp
*/
#define SYS_syscall 0
# DragonFly system call names.
# DO NOT EDIT-- this file is automatically generated.
-# $DragonFly: src/sys/sys/syscall.mk,v 1.20 2004/12/24 05:00:22 dillon Exp $
-# created from DragonFly: src/sys/kern/syscalls.master,v 1.13 2004/11/23 06:32:32 dillon Exp
+# $DragonFly: src/sys/sys/syscall.mk,v 1.21 2004/12/29 02:40:03 dillon Exp $
+# created from DragonFly: src/sys/kern/syscalls.master,v 1.14 2004/12/24 05:00:17 dillon Exp
MIASM = \
syscall.o \
exit.o \
* System call prototypes.
*
* DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/sysproto.h,v 1.20 2004/12/24 05:00:22 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.13 2004/11/23 06:32:32 dillon Exp
+ * $DragonFly: src/sys/sys/sysproto.h,v 1.21 2004/12/29 02:40:03 dillon Exp $
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.14 2004/12/24 05:00:17 dillon Exp
*/
#ifndef _SYS_SYSPROTO_H_
union usrmsg usrmsg;
char * path; char path_[PAD_(char *)];
int op; char op_[PAD_(int)];
+ int fd; char fd_[PAD_(int)];
const void * ctl; char ctl_[PAD_(const void *)];
int ctllen; char ctllen_[PAD_(int)];
void * buf; char buf_[PAD_(void *)];
* Union of syscall args for messaging.
*
* DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/sysunion.h,v 1.17 2004/12/24 05:00:22 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.13 2004/11/23 06:32:32 dillon Exp
+ * $DragonFly: src/sys/sys/sysunion.h,v 1.18 2004/12/29 02:40:03 dillon Exp $
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.14 2004/12/24 05:00:17 dillon Exp
*/
union sysunion {
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/sys/vfsops.h,v 1.11 2004/12/24 05:00:22 dillon Exp $
+ * $DragonFly: src/sys/sys/vfsops.h,v 1.12 2004/12/29 02:40:03 dillon Exp $
*/
/*
struct vop_mountctl_args {
struct vop_generic_args a_head;
int a_op;
+ struct file *a_fp;
const void *a_ctl;
int a_ctllen;
void *a_buf;
int vop_destroyvobject(struct vop_ops *ops, struct vnode *vp);
int vop_getvobject(struct vop_ops *ops,
struct vnode *vp, struct vm_object **objpp);
-int vop_mountctl(struct vop_ops *ops, int op, const void *ctl, int ctllen, void *buf, int buflen, int *res);
-
+int vop_mountctl(struct vop_ops *ops, int op, struct file *fp,
+ const void *ctl, int ctllen, void *buf, int buflen, int *res);
int vop_nresolve(struct vop_ops *ops, struct namecache *ncp,
struct ucred *cred);
int vop_nlookupdotdot(struct vop_ops *ops, struct vnode *dvp,
*
* @(#)vnode.h 8.7 (Berkeley) 2/4/94
* $FreeBSD: src/sys/sys/vnode.h,v 1.111.2.19 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/sys/vnode.h,v 1.29 2004/12/24 05:00:22 dillon Exp $
+ * $DragonFly: src/sys/sys/vnode.h,v 1.30 2004/12/29 02:40:03 dillon Exp $
*/
#ifndef _SYS_VNODE_H_
int vop_stdbwrite (struct vop_bwrite_args *ap);
int vop_stdislocked (struct vop_islocked_args *ap);
int vop_stdlock (struct vop_lock_args *ap);
-int vop_stdmountctl (struct vop_mountctl_args *ap);
int vop_stdrlock (struct vop_lock_args *ap);
int vop_stdunlock (struct vop_unlock_args *ap);
int vop_nopoll (struct vop_poll_args *ap);