.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $DragonFly: src/sbin/mountctl/mountctl.8,v 1.4 2005/07/06 06:04:32 dillon Exp $
+.\" $DragonFly: src/sbin/mountctl/mountctl.8,v 1.5 2005/07/13 02:00:19 dillon Exp $
.\"
.Dd January 8, 2005
.Dt MOUNTCTL 8
.Op Fl o Ar option ...
.Ar mountpt:tag
.Nm
+.Fl r
+.Op Fl 2
+.Op Fl w Ar output_path
+.Op Fl x Ar filedesc
+.Ar mountpt:tag
+.Nm
.Fl d
.Op Ar tag/mountpt | mountpt:tag
.Nm
not the case at the moment.
.Pp
.Nm
+.Fl r
+will restart an existing journal, directing it to a new file descriptor.
+A shutdown is sent to the old journal and the system waits for the return
+diection (if running full-duplex) to EOF. The new descriptor is then
+installed and the FIFO index is reset to the last acknowledged transaction.
+Clients scanning a journal across such a disconnect must check for repeated
+transaction ids since some overlap between the old and new journal may occur.
+.Pp
+.Nm
.Fl d
will remove the specified journal(s). A mount point, a tag, or both may be
specified. This function will operate on all matching journals.
.Fl d
are not specified.
.It Fl S
-Start or restart a journal, equivalent to the 'start' keyword.
+Start a stopped journal, equivalent to the 'start' keyword.
This option implies
.Fl m .
.It Fl C
Specify the size of the kernel-managed swap-backed FIFO used to buffer
overflows.
.It Ar path=filepath
-Switch the journal's output stream to a new file. This feature is typically
-used to restart a dead stream.
+Specify where the journal's output stream should be directed.
Note that the
.Fl w
option is equivalent to specifying the path option. Both should not be
specified.
.It Ar fd=filedesc
-Switch the journal's output stream to a file descriptor specified by number.
-Use file descriptor 1 if you wish to reopen the journal to the current
-stdout. This feature is typically used to restart a dead stream (for example
-if a TCP stream fails).
+Specify where the journal's output stream should be directed by handing over
+a file desciptor.
+Use file descriptor 1 if you wish to output the journal to the current
+stdout.
Note that the
.Fl w
option is equivalent to specifying the path option. Both should not be
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sbin/mountctl/mountctl.c,v 1.5 2005/07/06 06:04:32 dillon Exp $
+ * $DragonFly: src/sbin/mountctl/mountctl.c,v 1.6 2005/07/13 02:00:19 dillon Exp $
*/
/*
* This utility implements the userland mountctl command which is used to
static void mountctl_list(const char *keyword, const char *mountpt,
int __unused fd, void *info);
static void mountctl_add(const char *keyword, const char *mountpt, int fd);
+static void mountctl_restart(const char *keyword, const char *mountpt,
+ int fd, void __unused *);
static void mountctl_delete(const char *keyword, const char *mountpt,
int __unused fd, void __unused *);
static void mountctl_modify(const char *keyword, const char *mountpt, int fd, void __unused *);
int fopt = 0;
int lopt = 0;
int mopt = 0;
+ int ropt = 0;
int mimplied = 0;
const char *wopt = NULL;
const char *xopt = NULL;
const char *mountpt = NULL;
char *tmp;
- while ((ch = getopt(ac, av, "2adflo:mw:x:ACFSZ")) != -1) {
+ while ((ch = getopt(ac, av, "2adflmo:rw:x:ACFSZ")) != -1) {
switch(ch) {
case '2':
twoway_opt = 1;
break;
+ case 'r':
+ ropt = 1;
+ if (aopt + dopt + lopt + mopt + ropt != 1) {
+ fprintf(stderr, "too many action options specified\n");
+ usage();
+ }
+ break;
case 'a':
aopt = 1;
- if (aopt + dopt + lopt + mopt != 1) {
+ if (aopt + dopt + lopt + mopt + ropt != 1) {
fprintf(stderr, "too many action options specified\n");
usage();
}
break;
case 'd':
dopt = 1;
- if (aopt + dopt + lopt + mopt != 1) {
+ if (aopt + dopt + lopt + mopt + ropt != 1) {
fprintf(stderr, "too many action options specified\n");
usage();
}
break;
case 'l':
lopt = 1;
- if (aopt + dopt + lopt + mopt != 1) {
+ if (aopt + dopt + lopt + mopt + ropt != 1) {
fprintf(stderr, "too many action options specified\n");
usage();
}
break;
case 'm':
mopt = 1;
- if (aopt + dopt + lopt + mopt != 1) {
+ if (aopt + dopt + lopt + mopt + ropt != 1) {
fprintf(stderr, "too many action options specified\n");
usage();
}
*/
switch(ac) {
case 0:
- if (aopt) {
+ if (aopt || ropt) {
fprintf(stderr, "action requires a tag and/or mount "
"point to be specified\n");
usage();
/*
* Additional sanity checks
*/
- if (aopt + dopt + lopt + mopt + mimplied == 0) {
+ if (aopt + dopt + lopt + mopt + ropt + mimplied == 0) {
fprintf(stderr, "no action or implied action options were specified\n");
usage();
}
- if (mimplied && aopt + dopt + lopt == 0)
+ if (mimplied && aopt + dopt + lopt + ropt == 0)
mopt = 1;
- if ((wopt || xopt) && !(aopt || mopt)) {
- fprintf(stderr, "-w/-x/path/fd options may only be used with -m/-a\n");
+ if ((wopt || xopt) && !(aopt || ropt || mopt)) {
+ fprintf(stderr, "-w/-x/path/fd options may only be used with -m/-a/-r\n");
usage();
}
if (aopt && (keyword == NULL || mountpt == NULL)) {
}
} else if (xopt) {
fd = strtol(xopt, NULL, 0);
- } else if (aopt) {
+ } else if (aopt || ropt) {
fd = 1; /* stdout default for -a */
} else {
fd = -1;
mountctl_scan(mountctl_list, keyword, mountpt, fd);
if (aopt)
mountctl_add(keyword, mountpt, fd);
+ if (ropt) {
+ ch = mountctl_scan(mountctl_restart, keyword, mountpt, fd);
+ if (ch)
+ fprintf(stderr, "%d journals restarted\n", ch);
+ else
+ fprintf(stderr, "Unable to locate any matching journals\n");
+ }
if (dopt) {
ch = mountctl_scan(mountctl_delete, keyword, mountpt, -1);
if (ch)
- printf("%d journals deleted\n", ch);
+ fprintf(stderr, "%d journals deleted\n", ch);
else
- printf("Unable to locate any matching journals\n");
+ fprintf(stderr, "Unable to locate any matching journals\n");
}
if (mopt) {
ch = mountctl_scan(mountctl_modify, keyword, mountpt, fd);
if (ch)
- printf("%d journals modified\n", ch);
+ fprintf(stderr, "%d journals modified\n", ch);
else
- printf("Unable to locate any matching journals\n");
+ fprintf(stderr, "Unable to locate any matching journals\n");
}
return(exitCode);
}
static void
-mountctl_delete(const char *keyword, const char *mountpt, int __unused fd, void __unused *info)
+mountctl_restart(const char *keyword, const char *mountpt,
+ int fd, void __unused *info)
+{
+ struct mountctl_restart_journal joinfo;
+ int error;
+
+ /* XXX make sure descriptor is not on same filesystem as journal */
+
+ bzero(&joinfo, sizeof(joinfo));
+
+ snprintf(joinfo.id, sizeof(joinfo.id), "%s", keyword);
+ if (twoway_opt > 0)
+ joinfo.flags |= MC_JOURNAL_WANT_FULLDUPLEX;
+ if (reversable_opt > 0)
+ joinfo.flags |= MC_JOURNAL_WANT_REVERSABLE;
+
+ error = mountctl(mountpt, MOUNTCTL_RESTART_VFS_JOURNAL, fd,
+ &joinfo, sizeof(joinfo), NULL, 0);
+ if (error == 0) {
+ fprintf(stderr, "%s:%s restarted\n", mountpt, joinfo.id);
+ } else {
+ fprintf(stderr, "%s:%s restart failed, error %s\n", mountpt, joinfo.id, strerror(errno));
+ }
+}
+
+static void
+mountctl_delete(const char *keyword, const char *mountpt,
+ int __unused fd, void __unused *info)
{
struct mountctl_remove_journal joinfo;
int error;
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/vfs_jops.c,v 1.17 2005/07/06 06:02:22 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_jops.c,v 1.18 2005/07/13 01:58:20 dillon Exp $
*/
/*
* Each mount point may have zero or more independantly configured journals
#include <sys/file.h>
#include <sys/proc.h>
#include <sys/msfbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <machine/limits.h>
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_restart_vfs_journal(struct mount *mp, struct file *fp,
+ const struct mountctl_restart_journal *info);
static int journal_remove_vfs_journal(struct mount *mp,
const struct mountctl_remove_journal *info);
+static int journal_restart(struct mount *mp, struct file *fp,
+ struct journal *jo, int flags);
static int journal_destroy(struct mount *mp, struct journal *jo, int flags);
static int journal_resync_vfs_journal(struct mount *mp, const void *ctl);
static int journal_status_vfs_journal(struct mount *mp,
const struct mountctl_status_journal *info,
struct mountctl_journal_ret_status *rstat,
int buflen, int *res);
+static void journal_create_threads(struct journal *jo);
+static void journal_destroy_threads(struct journal *jo, int flags);
static void journal_wthread(void *info);
static void journal_rthread(void *info);
if (TAILQ_EMPTY(&mp->mnt_jlist))
journal_detach(mp);
break;
+ case MOUNTCTL_RESTART_VFS_JOURNAL:
case MOUNTCTL_REMOVE_VFS_JOURNAL:
case MOUNTCTL_RESYNC_VFS_JOURNAL:
case MOUNTCTL_STATUS_VFS_JOURNAL:
if (error == 0)
error = journal_install_vfs_journal(mp, ap->a_fp, ap->a_ctl);
break;
+ case MOUNTCTL_RESTART_VFS_JOURNAL:
+ if (ap->a_ctllen != sizeof(struct mountctl_restart_journal))
+ error = EINVAL;
+ if (error == 0 && ap->a_fp == NULL)
+ error = EBADF;
+ if (error == 0)
+ error = journal_restart_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;
free(jo, M_JOURNAL);
} else {
fhold(fp);
- jo->flags |= MC_JOURNAL_WACTIVE;
- lwkt_create(journal_wthread, jo, NULL, &jo->wthread,
- TDF_STOPREQ, -1, "journal w:%.*s", JIDMAX, jo->id);
- lwkt_setpri(&jo->wthread, TDPRI_KERN_DAEMON);
- lwkt_schedule(&jo->wthread);
-
- if (jo->flags & MC_JOURNAL_WANT_FULLDUPLEX) {
- jo->flags |= MC_JOURNAL_RACTIVE;
- lwkt_create(journal_rthread, jo, NULL, &jo->rthread,
- TDF_STOPREQ, -1, "journal r:%.*s", JIDMAX, jo->id);
- lwkt_setpri(&jo->rthread, TDPRI_KERN_DAEMON);
- lwkt_schedule(&jo->rthread);
- }
+ journal_create_threads(jo);
jrecord_init(jo, &jrec, JREC_STREAMID_DISCONT);
jrecord_write(&jrec, JTYPE_ASSOCIATE, 0);
jrecord_done(&jrec, 0);
}
/*
+ * Restart a journal with a new descriptor. The existing reader and writer
+ * threads are terminated and a new descriptor is associated with the
+ * journal. The FIFO rindex is reset to xindex and the threads are then
+ * restarted.
+ */
+static int
+journal_restart_vfs_journal(struct mount *mp, struct file *fp,
+ const struct mountctl_restart_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 = journal_restart(mp, fp, jo, info->flags);
+ else
+ error = EINVAL;
+ return (error);
+}
+
+static int
+journal_restart(struct mount *mp, struct file *fp,
+ struct journal *jo, int flags)
+{
+ /*
+ * XXX lock the jo
+ */
+
+#if 0
+ /*
+ * Record the fact that we are doing a restart in the journal.
+ * XXX it isn't safe to do this if the journal is being restarted
+ * because it was locked up and the writer thread has already exited.
+ */
+ jrecord_init(jo, &jrec, JREC_STREAMID_RESTART);
+ jrecord_write(&jrec, JTYPE_DISASSOCIATE, 0);
+ jrecord_done(&jrec, 0);
+#endif
+
+ /*
+ * Stop the reader and writer threads and clean up the current
+ * descriptor.
+ */
+ printf("RESTART WITH FP %p KILLING %p\n", fp, jo->fp);
+ journal_destroy_threads(jo, flags);
+
+ if (jo->fp)
+ fdrop(jo->fp, curthread);
+
+ /*
+ * Associate the new descriptor, reset the FIFO index, and recreate
+ * the threads.
+ */
+ fhold(fp);
+ jo->fp = fp;
+ jo->fifo.rindex = jo->fifo.xindex;
+ journal_create_threads(jo);
+
+ return(0);
+}
+
+/*
* Disassociate a journal from a mount point and terminate its worker thread.
* A final termination record is written out before the file pointer is
* dropped.
journal_destroy(struct mount *mp, struct journal *jo, int flags)
{
struct jrecord jrec;
- int wcount;
TAILQ_REMOVE(&mp->mnt_jlist, jo, jentry);
jrecord_write(&jrec, JTYPE_DISASSOCIATE, 0);
jrecord_done(&jrec, 0);
- jo->flags |= MC_JOURNAL_STOP_REQ | (flags & MC_JOURNAL_STOP_IMM);
- wakeup(&jo->fifo);
- wcount = 0;
- while (jo->flags & (MC_JOURNAL_WACTIVE | MC_JOURNAL_RACTIVE)) {
- tsleep(jo, 0, "jwait", hz);
- if (++wcount % 10 == 0) {
- printf("Warning: journal %s waiting for descriptors to close\n",
- jo->id);
- }
- }
- lwkt_free_thread(&jo->wthread); /* XXX SMP */
- if (jo->flags & MC_JOURNAL_WANT_FULLDUPLEX)
- lwkt_free_thread(&jo->rthread); /* XXX SMP */
+ journal_destroy_threads(jo, flags);
+
if (jo->fp)
fdrop(jo->fp, curthread);
if (jo->fifo.membase)
return(error);
}
+static void
+journal_create_threads(struct journal *jo)
+{
+ jo->flags &= ~(MC_JOURNAL_STOP_REQ | MC_JOURNAL_STOP_IMM);
+ jo->flags |= MC_JOURNAL_WACTIVE;
+ lwkt_create(journal_wthread, jo, NULL, &jo->wthread,
+ TDF_STOPREQ, -1, "journal w:%.*s", JIDMAX, jo->id);
+ lwkt_setpri(&jo->wthread, TDPRI_KERN_DAEMON);
+ lwkt_schedule(&jo->wthread);
+
+ if (jo->flags & MC_JOURNAL_WANT_FULLDUPLEX) {
+ jo->flags |= MC_JOURNAL_RACTIVE;
+ lwkt_create(journal_rthread, jo, NULL, &jo->rthread,
+ TDF_STOPREQ, -1, "journal r:%.*s", JIDMAX, jo->id);
+ lwkt_setpri(&jo->rthread, TDPRI_KERN_DAEMON);
+ lwkt_schedule(&jo->rthread);
+ }
+}
+
+static void
+journal_destroy_threads(struct journal *jo, int flags)
+{
+ int wcount;
+
+ jo->flags |= MC_JOURNAL_STOP_REQ | (flags & MC_JOURNAL_STOP_IMM);
+ wakeup(&jo->fifo);
+ wcount = 0;
+ while (jo->flags & (MC_JOURNAL_WACTIVE | MC_JOURNAL_RACTIVE)) {
+ tsleep(jo, 0, "jwait", hz);
+ if (++wcount % 10 == 0) {
+ printf("Warning: journal %s waiting for descriptors to close\n",
+ jo->id);
+ }
+ }
+
+ /*
+ * XXX SMP - threads should move to cpu requesting the restart or
+ * termination before finishing up to properly interlock.
+ */
+ tsleep(jo, 0, "jwait", hz);
+ lwkt_free_thread(&jo->wthread);
+ if (jo->flags & MC_JOURNAL_WANT_FULLDUPLEX)
+ lwkt_free_thread(&jo->rthread);
+}
+
/*
* The per-journal worker thread is responsible for writing out the
* journal's FIFO to the target stream.
}
}
}
+ fp_shutdown(jo->fp, SHUT_WR);
jo->flags &= ~MC_JOURNAL_WACTIVE;
wakeup(jo);
wakeup(&jo->fifo.windex);
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/vfs_journal.c,v 1.17 2005/07/06 06:02:22 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_journal.c,v 1.18 2005/07/13 01:58:20 dillon Exp $
*/
/*
* Each mount point may have zero or more independantly configured journals
#include <sys/file.h>
#include <sys/proc.h>
#include <sys/msfbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <machine/limits.h>
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_restart_vfs_journal(struct mount *mp, struct file *fp,
+ const struct mountctl_restart_journal *info);
static int journal_remove_vfs_journal(struct mount *mp,
const struct mountctl_remove_journal *info);
+static int journal_restart(struct mount *mp, struct file *fp,
+ struct journal *jo, int flags);
static int journal_destroy(struct mount *mp, struct journal *jo, int flags);
static int journal_resync_vfs_journal(struct mount *mp, const void *ctl);
static int journal_status_vfs_journal(struct mount *mp,
const struct mountctl_status_journal *info,
struct mountctl_journal_ret_status *rstat,
int buflen, int *res);
+static void journal_create_threads(struct journal *jo);
+static void journal_destroy_threads(struct journal *jo, int flags);
static void journal_wthread(void *info);
static void journal_rthread(void *info);
if (TAILQ_EMPTY(&mp->mnt_jlist))
journal_detach(mp);
break;
+ case MOUNTCTL_RESTART_VFS_JOURNAL:
case MOUNTCTL_REMOVE_VFS_JOURNAL:
case MOUNTCTL_RESYNC_VFS_JOURNAL:
case MOUNTCTL_STATUS_VFS_JOURNAL:
if (error == 0)
error = journal_install_vfs_journal(mp, ap->a_fp, ap->a_ctl);
break;
+ case MOUNTCTL_RESTART_VFS_JOURNAL:
+ if (ap->a_ctllen != sizeof(struct mountctl_restart_journal))
+ error = EINVAL;
+ if (error == 0 && ap->a_fp == NULL)
+ error = EBADF;
+ if (error == 0)
+ error = journal_restart_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;
free(jo, M_JOURNAL);
} else {
fhold(fp);
- jo->flags |= MC_JOURNAL_WACTIVE;
- lwkt_create(journal_wthread, jo, NULL, &jo->wthread,
- TDF_STOPREQ, -1, "journal w:%.*s", JIDMAX, jo->id);
- lwkt_setpri(&jo->wthread, TDPRI_KERN_DAEMON);
- lwkt_schedule(&jo->wthread);
-
- if (jo->flags & MC_JOURNAL_WANT_FULLDUPLEX) {
- jo->flags |= MC_JOURNAL_RACTIVE;
- lwkt_create(journal_rthread, jo, NULL, &jo->rthread,
- TDF_STOPREQ, -1, "journal r:%.*s", JIDMAX, jo->id);
- lwkt_setpri(&jo->rthread, TDPRI_KERN_DAEMON);
- lwkt_schedule(&jo->rthread);
- }
+ journal_create_threads(jo);
jrecord_init(jo, &jrec, JREC_STREAMID_DISCONT);
jrecord_write(&jrec, JTYPE_ASSOCIATE, 0);
jrecord_done(&jrec, 0);
}
/*
+ * Restart a journal with a new descriptor. The existing reader and writer
+ * threads are terminated and a new descriptor is associated with the
+ * journal. The FIFO rindex is reset to xindex and the threads are then
+ * restarted.
+ */
+static int
+journal_restart_vfs_journal(struct mount *mp, struct file *fp,
+ const struct mountctl_restart_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 = journal_restart(mp, fp, jo, info->flags);
+ else
+ error = EINVAL;
+ return (error);
+}
+
+static int
+journal_restart(struct mount *mp, struct file *fp,
+ struct journal *jo, int flags)
+{
+ /*
+ * XXX lock the jo
+ */
+
+#if 0
+ /*
+ * Record the fact that we are doing a restart in the journal.
+ * XXX it isn't safe to do this if the journal is being restarted
+ * because it was locked up and the writer thread has already exited.
+ */
+ jrecord_init(jo, &jrec, JREC_STREAMID_RESTART);
+ jrecord_write(&jrec, JTYPE_DISASSOCIATE, 0);
+ jrecord_done(&jrec, 0);
+#endif
+
+ /*
+ * Stop the reader and writer threads and clean up the current
+ * descriptor.
+ */
+ printf("RESTART WITH FP %p KILLING %p\n", fp, jo->fp);
+ journal_destroy_threads(jo, flags);
+
+ if (jo->fp)
+ fdrop(jo->fp, curthread);
+
+ /*
+ * Associate the new descriptor, reset the FIFO index, and recreate
+ * the threads.
+ */
+ fhold(fp);
+ jo->fp = fp;
+ jo->fifo.rindex = jo->fifo.xindex;
+ journal_create_threads(jo);
+
+ return(0);
+}
+
+/*
* Disassociate a journal from a mount point and terminate its worker thread.
* A final termination record is written out before the file pointer is
* dropped.
journal_destroy(struct mount *mp, struct journal *jo, int flags)
{
struct jrecord jrec;
- int wcount;
TAILQ_REMOVE(&mp->mnt_jlist, jo, jentry);
jrecord_write(&jrec, JTYPE_DISASSOCIATE, 0);
jrecord_done(&jrec, 0);
- jo->flags |= MC_JOURNAL_STOP_REQ | (flags & MC_JOURNAL_STOP_IMM);
- wakeup(&jo->fifo);
- wcount = 0;
- while (jo->flags & (MC_JOURNAL_WACTIVE | MC_JOURNAL_RACTIVE)) {
- tsleep(jo, 0, "jwait", hz);
- if (++wcount % 10 == 0) {
- printf("Warning: journal %s waiting for descriptors to close\n",
- jo->id);
- }
- }
- lwkt_free_thread(&jo->wthread); /* XXX SMP */
- if (jo->flags & MC_JOURNAL_WANT_FULLDUPLEX)
- lwkt_free_thread(&jo->rthread); /* XXX SMP */
+ journal_destroy_threads(jo, flags);
+
if (jo->fp)
fdrop(jo->fp, curthread);
if (jo->fifo.membase)
return(error);
}
+static void
+journal_create_threads(struct journal *jo)
+{
+ jo->flags &= ~(MC_JOURNAL_STOP_REQ | MC_JOURNAL_STOP_IMM);
+ jo->flags |= MC_JOURNAL_WACTIVE;
+ lwkt_create(journal_wthread, jo, NULL, &jo->wthread,
+ TDF_STOPREQ, -1, "journal w:%.*s", JIDMAX, jo->id);
+ lwkt_setpri(&jo->wthread, TDPRI_KERN_DAEMON);
+ lwkt_schedule(&jo->wthread);
+
+ if (jo->flags & MC_JOURNAL_WANT_FULLDUPLEX) {
+ jo->flags |= MC_JOURNAL_RACTIVE;
+ lwkt_create(journal_rthread, jo, NULL, &jo->rthread,
+ TDF_STOPREQ, -1, "journal r:%.*s", JIDMAX, jo->id);
+ lwkt_setpri(&jo->rthread, TDPRI_KERN_DAEMON);
+ lwkt_schedule(&jo->rthread);
+ }
+}
+
+static void
+journal_destroy_threads(struct journal *jo, int flags)
+{
+ int wcount;
+
+ jo->flags |= MC_JOURNAL_STOP_REQ | (flags & MC_JOURNAL_STOP_IMM);
+ wakeup(&jo->fifo);
+ wcount = 0;
+ while (jo->flags & (MC_JOURNAL_WACTIVE | MC_JOURNAL_RACTIVE)) {
+ tsleep(jo, 0, "jwait", hz);
+ if (++wcount % 10 == 0) {
+ printf("Warning: journal %s waiting for descriptors to close\n",
+ jo->id);
+ }
+ }
+
+ /*
+ * XXX SMP - threads should move to cpu requesting the restart or
+ * termination before finishing up to properly interlock.
+ */
+ tsleep(jo, 0, "jwait", hz);
+ lwkt_free_thread(&jo->wthread);
+ if (jo->flags & MC_JOURNAL_WANT_FULLDUPLEX)
+ lwkt_free_thread(&jo->rthread);
+}
+
/*
* The per-journal worker thread is responsible for writing out the
* journal's FIFO to the target stream.
}
}
}
+ fp_shutdown(jo->fp, SHUT_WR);
jo->flags &= ~MC_JOURNAL_WACTIVE;
wakeup(jo);
wakeup(&jo->fifo.windex);
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/sys/journal.h,v 1.5 2005/07/06 06:02:23 dillon Exp $
+ * $DragonFly: src/sys/sys/journal.h,v 1.6 2005/07/13 01:58:23 dillon Exp $
*/
#ifndef _SYS_JOURNAL_H_
#define JREC_STREAMID_DISCONT 0x0002 /* discontinuity */
#define JREC_STREAMID_ANNOTATE 0x0003 /* annotation */
#define JREC_STREAMID_ACK 0x0004 /* acknowledgement */
- /* 0x0005-0x007F reserved by DragonFly */
+#define JREC_STREAMID_RESTART 0x0005 /* disctoninuity - journal restart */
+ /* 0x0006-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) */
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/sys/mountctl.h,v 1.8 2005/07/06 06:02:23 dillon Exp $
+ * $DragonFly: src/sys/sys/mountctl.h,v 1.9 2005/07/13 01:58:23 dillon Exp $
*/
#ifndef _SYS_MOUNTCTL_H_
#define MOUNTCTL_REMOVE_VFS_JOURNAL 2
#define MOUNTCTL_RESYNC_VFS_JOURNAL 3
#define MOUNTCTL_STATUS_VFS_JOURNAL 4
+#define MOUNTCTL_RESTART_VFS_JOURNAL 5
#define MOUNTCTL_INSTALL_BLK_JOURNAL 8
#define MOUNTCTL_REMOVE_BLK_JOURNAL 9
#define MC_JOURNAL_WANT_REVERSABLE 0x00020000 /* reversable stream */
#define MC_JOURNAL_WANT_FULLDUPLEX 0x00040000 /* has ack stream */
+struct mountctl_restart_journal {
+ char id[JIDMAX];
+ int flags;
+ int unused01;
+};
+
struct mountctl_remove_journal {
char id[JIDMAX];
int flags;