diff --git a/sbin/mount_dirfs/Makefile b/sbin/mount_dirfs/Makefile
index 8800775..036b560 100644
--- a/sbin/mount_dirfs/Makefile
+++ b/sbin/mount_dirfs/Makefile
@@ -2,6 +2,9 @@ PROG=	mount_dirfs
 SRCS=	mount_dirfs.c
 NOMAN=	sorry
 
+LDADD=  -lutil
+DPADD=  ${LIBUTIL}
+
 #CFLAGS+= -I${.CURDIR}/../../sys
 
-.include <bsd.prog.mk>
\ No newline at end of file
+.include <bsd.prog.mk>
diff --git a/sbin/mount_dirfs/mount_dirfs.c b/sbin/mount_dirfs/mount_dirfs.c
index c2fb497..7c4e840 100644
--- a/sbin/mount_dirfs/mount_dirfs.c
+++ b/sbin/mount_dirfs/mount_dirfs.c
@@ -1,29 +1,144 @@
+/*
+ * Copyright (c) 2011-2013 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
+ * by Matthew Dillon <dillon@dragonflybsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/diskslice.h>
+#include <sys/diskmbr.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/syslimits.h>
+#include <sys/mount.h>
+
 #include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <uuid.h>
 #include <err.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <strings.h>
+#include <assert.h>
+#include <ctype.h>
+#include <mntopts.h>
 
-#include <sys/param.h>
-#include <sys/mount.h>
+#define MOPT_UPDATE         { "update",     0, MNT_UPDATE, 0 }
+
+static struct mntopt mopts[] = { MOPT_STDOPTS, MOPT_UPDATE, MOPT_NULL };
+
+static void usage(void);
 
 int
-main(int argc, char *argv[])
+main(int ac, char **av)
 {
+	struct vfsconf vfc;
+	int mount_flags = 0;
 	int error;
-	char *mntpt, *hostdir;
+	int ch;
+	int init_flags = 0;
+	char *mountpt, *hostdir;
+
+	mount_flags = 0;
+
+	while ((ch = getopt(ac, av, "o:u")) != -1) {
+		switch(ch) {
+                case 'u':
+                        init_flags |= MNT_UPDATE;
+                        break;
+
+		case 'o':
+			getmntopts(optarg, mopts, &mount_flags, NULL);
+			break;
+		default:
+			usage();
+			/* not reached */
+		}
+	}
+	ac -= optind;
+	av += optind;
+	mount_flags |= init_flags;
+
+        /*
+         * Only the mount point need be specified in update mode.
+         */
+        if (init_flags & MNT_UPDATE) {
+                if (ac != 1) {
+                        usage();
+                        /* not reached */
+                }
+                mountpt = av[0];
+                if (mount(vfc.vfc_name, mountpt, mount_flags, NULL))
+                        err(1, "mountpoint %s", mountpt);
+                exit(0);
+        }
 
-	if (argc != 3)
-		errx(1, "%s: [host dir] [mount point]", argv[0]);
+	if (ac < 2) {
+		usage();
+		/* not reached */
+	}
 
-	hostdir = argv[1];
-	mntpt = argv[2];
+	hostdir = av[0];
+	mountpt = av[1];
 
-	error = mount("dirfs", mntpt, 0, hostdir);
+	/*
+	 * Load the dirfs module if necessary (this bit stolen from
+	 * mount_null).
+	 */
+	error = getvfsbyname("dirfs", &vfc);
+	if (error && vfsisloadable("dirfs")) {
+		if (vfsload("dirfs") != 0)
+			err(1, "vfsload(dirfs)");
+		endvfsent();
+		error = getvfsbyname("dirfs", &vfc);
+	}
 	if (error)
-		perror("mount");
+		errx(1, "dirfs filesystem is not available");
 
-	return 0;
+	error = mount(vfc.vfc_name, mountpt, mount_flags, hostdir);
+	if (error)
+		err(1, "failed to mount %s on %s", hostdir, mountpt);
+
+	exit (0);
 }
 
+static
+void
+usage(void)
+{
+	fprintf(stderr, "usage: mount_dirfs [-u] [-o options] "
+			"hostdir dir\n");
+	exit(1);
+}
diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c
index 700413c..63c6935 100644
--- a/sys/kern/vfs_conf.c
+++ b/sys/kern/vfs_conf.c
@@ -378,7 +378,8 @@ vfs_mountroot_try(const char *mountfrom)
 	char		*mf;
 	struct proc	*p;
 	struct vnode	*vp;
-
+	caddr_t		data;
+	data = NULL;
 	vfsname = NULL;
 	devname = NULL;
 	mp      = NULL;
@@ -409,6 +410,7 @@ vfs_mountroot_try(const char *mountfrom)
 			goto end;
 
 		/* allocate a root mount */
+		kprintf("Allocating mp for %s at %s\n", vfsname, devname);
 		error = vfs_rootmountalloc(vfsname,
 				devname[0] != 0 ? devname : ROOTNAME, &mp);
 		if (error != 0) {
@@ -419,9 +421,15 @@ vfs_mountroot_try(const char *mountfrom)
 		mp->mnt_flag |= MNT_ROOTFS;
 
 		/* do our best to set rootdev */
-		if ((strcmp(vfsname, "hammer") != 0) && (devname[0] != 0) &&
-		    setrootbyname(devname))
-			kprintf("setrootbyname failed\n");
+		kprintf("vfsname=%s devname=%s\n", vfsname, devname);
+		if ((strcmp(vfsname, "dirfs") == 0 && devname)) {
+			data = kmalloc(1024, M_TEMP, M_WAITOK | M_ZERO);
+			bcopy(devname, data, 1024);
+		} else {
+			if ((strcmp(vfsname, "hammer") != 0) && (devname[0] != 0) &&
+			    setrootbyname(devname))
+				kprintf("setrootbyname failed\n");
+		}
 
 		/* If the root device is a type "memory disk", mount RW */
 		if (rootdev != NULL && dev_is_good(rootdev) &&
@@ -429,7 +437,9 @@ vfs_mountroot_try(const char *mountfrom)
 			mp->mnt_flag &= ~MNT_RDONLY;
 		}
 
-		error = VFS_MOUNT(mp, NULL, NULL, proc0.p_ucred);
+		error = VFS_MOUNT(mp, NULL, data, proc0.p_ucred);
+		if (data)
+			kfree(data, M_TEMP);
 
 		if (!error)
 			break;
diff --git a/sys/vfs/dirfs/dirfs.h b/sys/vfs/dirfs/dirfs.h
index 98c972c..6a41329 100644
--- a/sys/vfs/dirfs/dirfs.h
+++ b/sys/vfs/dirfs/dirfs.h
@@ -3,6 +3,7 @@
  *
  * This code is derived from software contributed to The DragonFly Project
  * by Antonio Huete Jimenez <tuxillo@quantumachine.net>
+ * by Matthew Dillon <dillon@dragonflybsd.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,9 +38,10 @@
 #define _SYS_VFS_DIRFS_DIRFS_H_
 
 #include <unistd.h>
-#include <sys/vnode.h>
+
 #include <sys/lockf.h>
 #include <sys/stat.h>
+#include <sys/vnode.h>
 
 MALLOC_DECLARE(M_DIRFS);
 MALLOC_DECLARE(M_DIRFS_NODE);
@@ -49,25 +51,27 @@ MALLOC_DECLARE(M_DIRFS_MISC);
 #define KTR_DIRFS KTR_ALL
 #endif
 
-#define DIRFS_NOFD	-1
+#define DIRFS_NOFD	-1	/* No fd present */
 
 #define DIRFS_ROOT	0x00000001
 #define DIRFS_PASVFD	0x00000002
-#define DIRFS_NEEDSTAT	0x00000008
 
-#define DIRFS_TXTFLG "pasvfd", "wantfree"
+#define DIRFS_TXTFLG "pasvfd"
 
-#define BSIZE	16384          /* buffer cache size*/
+/* Used for buffer cache operations */
+#define BSIZE	16384
 #define BMASK	(BSIZE - 1)
 
 /*
- * XXX Need to find a proper way
+ * XXX This should be temporary. A semi-proper solution would be to expose
+ * below prototypes in the _KERNEL_VIRTUAL case.
  */
 extern int getdirentries(int, char *, int, long *);
 extern int statfs(const char *, struct statfs *);
 
 /*
- * Debugging macros
+ * Debugging macros. The impact should be determined and in case it has a
+ * considerable performance penalty, it should be enclosed in a DEBUG #ifdef.
  */
 #define debug_called() do {					\
 		dbg(9, "called\n", __func__);			\
@@ -109,9 +113,9 @@ extern int statfs(const char *, struct statfs *);
 #define dirfs_node_isroot(n)	(n->dn_state & DIRFS_ROOT)
 
 /*
- * dirfs' node in-memory struct. It corresponds exactly to a host file.
- * dirfs nodes are stated upon VOP_NRESOLVE() to populate most of its
- * generic fields.
+ * Main in-memory node structure which will represent a host file when active.
+ * Upon VOP_NRESOLVE() an attempt to initialize its generic fields will be made
+ * via a fstatat(2)/lstat(2) call.
  */
 struct dirfs_node {
 	enum vtype		dn_type;	/* Node type. Same as vnode
@@ -166,18 +170,18 @@ struct dirfs_mount {
 
 	struct lock	 	dm_lock;
 	struct lwkt_token	dm_token;
-	dirfs_node_t		dm_root;
+	dirfs_node_t		dm_root;	/* Root dirfs node */
 	struct mount *		dm_mount;
-	int			dm_flags;
+	int			dm_rdonly;
 
-	int			dm_fd_used;
+	int			dm_fd_used;	/* Opened file descriptors */
 
 	char			dm_path[MAXPATHLEN];
 };
 typedef struct dirfs_mount *dirfs_mount_t;
 
 /*
- * VFS conversion macros
+ * VFS <-> DIRFS conversion macros
  */
 #define VFS_TO_DIRFS(mp)	((dirfs_mount_t)((mp)->mnt_data))
 #define DIRFS_TO_VFS(dmp)	((struct mount *)((dmp)->dm_mount))
@@ -185,9 +189,9 @@ typedef struct dirfs_mount *dirfs_mount_t;
 #define NODE_TO_VP(dnp)		((dnp)->dn_vnode)
 
 /* Misc stuff */
+extern int debuglvl;
 extern int dirfs_fd_limit;
 extern int dirfs_fd_used;
-extern int debuglvl;
 extern long passive_fd_list_miss;
 extern long passive_fd_list_hits;
 
@@ -202,12 +206,12 @@ dirfs_node_ref(dirfs_node_t dnp)
 	atomic_add_int(&dnp->dn_refcnt, 1);
 }
 
-/*
- * Returns non-zero on last unref.
- */
 static __inline int
 dirfs_node_unref(dirfs_node_t dnp)
 {
+	/*
+	 * Returns non-zero on last unref.
+	 */
 	KKASSERT(dnp->dn_refcnt > 0);
 	return (atomic_fetchadd_int(&dnp->dn_refcnt, -1) == 1);
 }
@@ -238,8 +242,8 @@ void dirfs_node_drop(dirfs_mount_t dmp, dirfs_node_t dnp);
 void dirfs_node_setpassive(dirfs_mount_t dmp, dirfs_node_t dnp, int state);
 void dirfs_alloc_vp(struct mount *, struct vnode **, int, dirfs_node_t);
 void dirfs_free_vp(dirfs_mount_t, dirfs_node_t);
-int dirfs_alloc_file(dirfs_mount_t, dirfs_node_t *, dirfs_node_t, struct namecache *,
-    struct vnode **, struct vattr *, int);
+int dirfs_alloc_file(dirfs_mount_t, dirfs_node_t *, dirfs_node_t,
+    struct namecache *, struct vnode **, struct vattr *, int);
 dirfs_node_t dirfs_findfd(dirfs_mount_t dmp, dirfs_node_t cur,
 			char **pathto, char **pathfree);
 void dirfs_dropfd(dirfs_mount_t dmp, dirfs_node_t dnp1, char *pathfree);
diff --git a/sys/vfs/dirfs/dirfs_subr.c b/sys/vfs/dirfs/dirfs_subr.c
index c812fa8..1a1d6d7 100644
--- a/sys/vfs/dirfs/dirfs_subr.c
+++ b/sys/vfs/dirfs/dirfs_subr.c
@@ -3,6 +3,7 @@
  *
  * This code is derived from software contributed to The DragonFly Project
  * by Antonio Huete Jimenez <tuxillo@quantumachine.net>
+ * by Matthew Dillon <dillon@dragonflybsd.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,21 +34,25 @@
  *
  */
 
-#include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <unistd.h>
 
 #include <sys/mount.h>
-#include <sys/vfscache.h>
-#include <sys/types.h>
-#include <sys/systm.h>
-#include <sys/stat.h>
-#include <sys/spinlock2.h>
 #include <sys/queue.h>
+#include <sys/spinlock2.h>
+#include <sys/stat.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/vfscache.h>
 #include <sys/vnode.h>
 
 #include "dirfs.h"
 
+/*
+ * Allocate and setup all is needed for the dirfs node to hold the filename.
+ * Note: dn_name is NULL terminated.
+ */
 void
 dirfs_node_setname(dirfs_node_t dnp, const char *name, int len)
 {
@@ -61,6 +66,10 @@ dirfs_node_setname(dirfs_node_t dnp, const char *name, int len)
 	dnp->dn_namelen = len;
 }
 
+/*
+ * Allocate enough space to hold a dirfs node structure.
+ * Note: Node name and length isn't handled here.
+ */
 dirfs_node_t
 dirfs_node_alloc(struct mount *mp)
 {
@@ -76,6 +85,9 @@ dirfs_node_alloc(struct mount *mp)
         return dnp;
 }
 
+/*
+ * Drops a reference to the node and. Node is freed when in the last reference.
+ */
 void
 dirfs_node_drop(dirfs_mount_t dmp, dirfs_node_t dnp)
 {
@@ -84,7 +96,9 @@ dirfs_node_drop(dirfs_mount_t dmp, dirfs_node_t dnp)
 }
 
 /*
- * Do not call locked!
+ * Removes the association with its parent. Before freeing up its resources
+ * the node will be removed from the per-mount passive fd cache and its fd
+ * will be closed, either normally or forced.
  */
 int
 dirfs_node_free(dirfs_mount_t dmp, dirfs_node_t dnp)
@@ -105,6 +119,7 @@ dirfs_node_free(dirfs_mount_t dmp, dirfs_node_t dnp)
 	 * Root inode will be removed on VOP_UNMOUNT()
 	 */
 	dirfs_mount_gettoken(dmp);
+
 	if (dnp->dn_parent) {	/* NULL when children reaped parents */
 		dirfs_node_drop(dmp, dnp->dn_parent);
 		dnp->dn_parent = NULL;
@@ -114,10 +129,19 @@ dirfs_node_free(dirfs_mount_t dmp, dirfs_node_t dnp)
 		kfree(dnp->dn_name, M_DIRFS_MISC);
 		dnp->dn_name = NULL;
 	}
-	if (dnp->dn_fd) {
+
+	/*
+	 * The file descriptor should have been closed already by the
+	 * previous call to dirfs_set-passive. If not, force a sync and
+	 * close it.
+	 */
+	if (dnp->dn_fd != DIRFS_NOFD) {
+		if (dnp->dn_vnode)
+			VOP_FSYNC(vp, MNT_WAIT, 0);
 		close(dnp->dn_fd);
 		dnp->dn_fd = DIRFS_NOFD;
 	}
+
 	lockuninit(&dnp->dn_lock);
 	kfree(dnp, M_DIRFS_NODE);
 	dnp = NULL;
@@ -153,15 +177,18 @@ dirfs_alloc_file(dirfs_mount_t dmp, dirfs_node_t *dnpp, dirfs_node_t pdnp,
 	vp = NULL;
 	mp = DIRFS_TO_VFS(dmp);
 
+	/* Sanity check */
 	if (pdnp == NULL)
 		return EINVAL;
 
 	dnp = dirfs_node_alloc(mp);
 	KKASSERT(dnp != NULL);
 
+	dirfs_node_lock(dnp);
 	dirfs_node_setname(dnp, ncp->nc_name, ncp->nc_nlen);
 	dnp->dn_parent = pdnp;
 	dirfs_node_ref(pdnp);   /* Children ref */
+	dirfs_node_unlock(dnp);
 
 	pathnp = dirfs_findfd(dmp, dnp, &tmp, &pathfree);
 
@@ -550,7 +577,7 @@ dirfs_open_helper(dirfs_mount_t dmp, dirfs_node_t dnp, int parentfd,
 	if (dnp->dn_type & VDIR) {
 		flags |= O_DIRECTORY;
 	} else {
-		if ((dmp->dm_flags & MNT_RDONLY) == 0 && canwrite)
+		if (canwrite)
 			flags |= O_RDWR;
 		else
 			flags |= O_RDONLY;
@@ -819,21 +846,21 @@ dirfs_node_setpassive(dirfs_mount_t dmp, dirfs_node_t dnp, int state)
 		vp = dnp->dn_vnode;
 		if (dirfs_node_refcnt(dnp) == 2 && vp &&
 		    dnp->dn_fd != DIRFS_NOFD &&
-		    dnp != dmp->dm_root &&
+		    !dirfs_node_isroot(dnp) &&
 		    (vp->v_flag & (VINACTIVE|VOBJDIRTY)) == VINACTIVE &&
 		    RB_EMPTY(&vp->v_rbdirty_tree)) {
 			dbg(5, "passive cache: closing %d\n", dnp->dn_fd);
 			close(dnp->dn_fd);
 			dnp->dn_fd = DIRFS_NOFD;
-		} else
-		if (dirfs_node_refcnt(dnp) == 1 && dnp->dn_vnode == NULL &&
-		    dnp->dn_fd != DIRFS_NOFD &&
-		    dnp != dmp->dm_root) {
-			dbg(5, "passive cache: closing %d\n", dnp->dn_fd);
-			close(dnp->dn_fd);
-			dnp->dn_fd = DIRFS_NOFD;
+		} else {
+			if (dirfs_node_refcnt(dnp) == 1 && dnp->dn_vnode == NULL &&
+			    dnp->dn_fd != DIRFS_NOFD &&
+			    dnp != dmp->dm_root) {
+				dbg(5, "passive cache: closing %d\n", dnp->dn_fd);
+				close(dnp->dn_fd);
+				dnp->dn_fd = DIRFS_NOFD;
+			}
 		}
-
 		dirfs_node_drop(dmp, dnp);
 	}
 }
diff --git a/sys/vfs/dirfs/dirfs_vfsops.c b/sys/vfs/dirfs/dirfs_vfsops.c
index cac313a..a09c1de 100644
--- a/sys/vfs/dirfs/dirfs_vfsops.c
+++ b/sys/vfs/dirfs/dirfs_vfsops.c
@@ -3,6 +3,7 @@
  *
  * This code is derived from software contributed to The DragonFly Project
  * by Antonio Huete Jimenez <tuxillo@quantumachine.net>
+ * by Matthew Dillon <dillon@dragonflybsd.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -65,7 +66,7 @@ KTR_INFO(KTR_DIRFS, dirfs, root, 31,
     dirfs_node_t dnp, struct vnode *vp, char *hostdir, int fd, int error);
 
 /* System wide sysctl stuff */
-int debuglvl = 5;
+int debuglvl = 2;
 int dirfs_fd_limit = 100;
 int dirfs_fd_used = 0;
 long passive_fd_list_miss = 0;
@@ -97,8 +98,18 @@ dirfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
 	debug_called();
 
 	if (mp->mnt_flag & MNT_UPDATE) {
-		debug(2, "Can't update mountpoint\n");
-		return EOPNOTSUPP;
+		dmp = VFS_TO_DIRFS(mp);
+		if (dmp->dm_rdonly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
+			/* XXX We should make sure all writes are synced */
+			dmp->dm_rdonly = 1;
+			debug(2, "dirfs read-write -> read-only\n");
+		}
+
+		if (dmp->dm_rdonly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
+			debug(2, "dirfs read-only -> read-write\n");
+			dmp->dm_rdonly = 0;
+		}
+		return 0;
 	}
 
 	dmp = kmalloc(sizeof(*dmp), M_DIRFS, M_WAITOK | M_ZERO);
@@ -106,8 +117,14 @@ dirfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
 	dmp->dm_mount = mp;
 
 	error = copyinstr(data, &dmp->dm_path, MAXPATHLEN, &done);
-	if (error)
-		return error;
+	if (error) {
+		/* Attempt to copy from kernel address */
+		error = copystr(data, &dmp->dm_path, MAXPATHLEN, &done);
+		if (error) {
+			kfree(dmp, M_DIRFS);
+			return error;
+		}
+	}
 
 	/* Strip / character at the end to avoid problems */
 	nlen = strnlen(dmp->dm_path, MAXPATHLEN);
diff --git a/sys/vfs/dirfs/dirfs_vnops.c b/sys/vfs/dirfs/dirfs_vnops.c
index 046b4ff..f060f41 100644
--- a/sys/vfs/dirfs/dirfs_vnops.c
+++ b/sys/vfs/dirfs/dirfs_vnops.c
@@ -3,6 +3,7 @@
  *
  * This code is derived from software contributed to The DragonFly Project
  * by Antonio Huete Jimenez <tuxillo@quantumachine.net>
+ * by Matthew Dillon <dillon@dragonflybsd.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
