diff --git a/libraries/libmdb/mdb.c b/libraries/libmdb/mdb.c
index 9bfe2f8d1fc7814743e60c8b08ebb042a816cf05..b39fbfbfcb52c9179f8a46eadfc45b1254dc246a 100644
--- a/libraries/libmdb/mdb.c
+++ b/libraries/libmdb/mdb.c
@@ -915,6 +915,8 @@ struct MDB_env {
 #define	MDB_FATAL_ERROR	0x80000000U
 	/** Read-only Filesystem. Allow read access, no locking. */
 #define	MDB_ROFS	0x40000000U
+	/** Some fields are initialized. */
+#define	MDB_ENV_ACTIVE	0x20000000U
 	uint32_t 	me_flags;		/**< @ref mdb_env */
 	unsigned int	me_psize;	/**< size of a page, from #GET_PAGESIZE */
 	unsigned int	me_maxreaders;	/**< size of the reader table */
@@ -2583,14 +2585,13 @@ mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers)
 /** Further setup required for opening an MDB environment
  */
 static int
-mdb_env_open2(MDB_env *env, unsigned int flags)
+mdb_env_open2(MDB_env *env)
 {
+	unsigned int flags = env->me_flags;
 	int i, newenv = 0, prot;
 	MDB_meta meta;
 	MDB_page *p;
 
-	env->me_flags |= flags;
-
 	memset(&meta, 0, sizeof(meta));
 
 	if ((i = mdb_env_read_header(env, &meta)) != 0) {
@@ -2931,7 +2932,7 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl)
 		FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
 		FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
 		rc = ErrCode();
-		if (rc == ERROR_WRITE_PROTECT) {
+		if (rc == ERROR_WRITE_PROTECT && (env->me_flags & MDB_RDONLY)) {
 			env->me_flags |= MDB_ROFS;
 			return MDB_SUCCESS;
 		}
@@ -2949,7 +2950,7 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl)
 		int fdflags;
 		if ((env->me_lfd = open(lpath, O_RDWR|O_CREAT, mode)) == -1) {
 			rc = ErrCode();
-			if (rc == EROFS) {
+			if (rc == EROFS && (env->me_flags & MDB_RDONLY)) {
 				env->me_flags |= MDB_ROFS;
 				return MDB_SUCCESS;
 			}
@@ -2962,7 +2963,7 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl)
 #else /* O_CLOEXEC on Linux: Open file and set FD_CLOEXEC atomically */
 	if ((env->me_lfd = open(lpath, O_RDWR|O_CREAT|O_CLOEXEC, mode)) == -1) {
 		rc = ErrCode();
-		if (rc == EROFS) {
+		if (rc == EROFS && (env->me_flags & MDB_RDONLY)) {
 			env->me_flags |= MDB_ROFS;
 			return MDB_SUCCESS;
 		}
@@ -3154,15 +3155,15 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mode_t mode)
 		sprintf(dpath, "%s" DATANAME, path);
 	}
 
-	env->me_flags = 0;
+	/* silently ignore WRITEMAP if we're only getting read access */
+	if (F_ISSET(flags, MDB_RDONLY|MDB_WRITEMAP))
+		flags ^= MDB_WRITEMAP;
+	env->me_flags = flags |= MDB_ENV_ACTIVE;
+
 	rc = mdb_env_setup_locks(env, lpath, mode, &excl);
 	if (rc)
 		goto leave;
 
-	/* silently ignore WRITEMAP if we're only getting read access */
-	if (F_ISSET(flags, MDB_RDONLY) && F_ISSET(flags, MDB_WRITEMAP))
-		flags ^= MDB_WRITEMAP;
-
 #ifdef _WIN32
 	if (F_ISSET(flags, MDB_RDONLY)) {
 		oflags = GENERIC_READ;
@@ -3187,7 +3188,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mode_t mode)
 		goto leave;
 	}
 
-	if ((rc = mdb_env_open2(env, flags)) == MDB_SUCCESS) {
+	if ((rc = mdb_env_open2(env)) == MDB_SUCCESS) {
 		if (flags & (MDB_RDONLY|MDB_NOSYNC|MDB_NOMETASYNC|MDB_WRITEMAP)) {
 			env->me_mfd = env->me_fd;
 		} else {
@@ -3242,7 +3243,7 @@ mdb_env_close0(MDB_env *env, int excl)
 {
 	int i;
 
-	if (env->me_lfd == INVALID_HANDLE_VALUE) /* 1st field to get inited */
+	if (!(env->me_flags & MDB_ENV_ACTIVE))
 		return;
 
 	free(env->me_dbflags);
@@ -3303,9 +3304,11 @@ mdb_env_close0(MDB_env *env, int excl)
 #endif
 		munmap((void *)env->me_txns, (env->me_maxreaders-1)*sizeof(MDB_reader)+sizeof(MDB_txninfo));
 	}
-	close(env->me_lfd);
+	if (env->me_lfd != INVALID_HANDLE_VALUE) {
+		close(env->me_lfd);
+	}
 
-	env->me_lfd = INVALID_HANDLE_VALUE;	/* Mark env as reset */
+	env->me_flags &= ~MDB_ENV_ACTIVE;
 }
 
 int
@@ -3357,13 +3360,25 @@ mdb_env_copy(MDB_env *env, const char *path)
 	}
 #endif
 
-	/* Temporarily block writers until we snapshot the meta pages */
-	LOCK_MUTEX_W(env);
-
+	/* Do the lock/unlock of the reader mutex before starting the
+	 * write txn.  Otherwise other read txns could block writers.
+	 */
 	rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
-	if (rc) {
-		UNLOCK_MUTEX_W(env);
+	if (rc)
 		goto leave;
+
+	if (!(env->me_flags & MDB_ROFS)) {
+		/* We must start the actual read txn after blocking writers */
+		mdb_txn_reset0(txn);
+
+		/* Temporarily block writers until we snapshot the meta pages */
+		LOCK_MUTEX_W(env);
+
+		rc = mdb_txn_renew0(txn);
+		if (rc) {
+			UNLOCK_MUTEX_W(env);
+			goto leave;
+		}
 	}
 
 	wsize = env->me_psize * 2;
@@ -3377,7 +3392,8 @@ mdb_env_copy(MDB_env *env, const char *path)
 	rc = write(newfd, env->me_map, wsize);
 	rc = (rc == (int)wsize) ? MDB_SUCCESS : ErrCode();
 #endif
-	UNLOCK_MUTEX_W(env);
+	if (! (env->me_flags & MDB_ROFS))
+		UNLOCK_MUTEX_W(env);
 
 	if (rc)
 		goto leave;