aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--external/db_drivers/liblmdb/mdb.c58
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp40
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h1
3 files changed, 58 insertions, 41 deletions
diff --git a/external/db_drivers/liblmdb/mdb.c b/external/db_drivers/liblmdb/mdb.c
index 6314d5775..bf60c7013 100644
--- a/external/db_drivers/liblmdb/mdb.c
+++ b/external/db_drivers/liblmdb/mdb.c
@@ -1467,6 +1467,8 @@ struct MDB_env {
#endif
/** Failed to update the meta page. Probably an I/O error. */
#define MDB_FATAL_ERROR 0x80000000U
+ /** using a raw block device */
+#define MDB_RAWPART 0x40000000U
/** Some fields are initialized. */
#define MDB_ENV_ACTIVE 0x20000000U
/** me_txkey is set */
@@ -4038,6 +4040,8 @@ fail:
return rc;
}
+static int ESECT mdb_env_map(MDB_env *env, void *addr);
+
/** Read the environment parameters of a DB environment before
* mapping it into memory.
* @param[in] env the environment handle
@@ -4054,6 +4058,31 @@ mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta)
int i, rc, off;
enum { Size = sizeof(pbuf) };
+ if (env->me_flags & MDB_RAWPART) {
+#define VM_ALIGN 0x200000
+ env->me_mapsize += VM_ALIGN-1;
+ env->me_mapsize &= ~(VM_ALIGN-1);
+ env->me_psize = env->me_os_psize;
+ rc = mdb_env_map(env, NULL);
+ if (rc) {
+ DPRINTF(("mdb_env_map: %s", mdb_strerror(rc)));
+ return rc;
+ }
+ p = (MDB_page *)env->me_map;
+ for (i=0; i<NUM_METAS; i++) {
+ if (!F_ISSET(p->mp_flags, P_META))
+ return ENOENT;
+ if (env->me_metas[i]->mm_magic != MDB_MAGIC)
+ return MDB_INVALID;
+ if (env->me_metas[i]->mm_version != MDB_DATA_VERSION)
+ return MDB_VERSION_MISMATCH;
+ if (i == 0 || env->me_metas[i]->mm_txnid > meta->mm_txnid)
+ *meta = *env->me_metas[i];
+ p = (MDB_page *)((char *)p + env->me_psize);
+ }
+ return 0;
+ }
+
/* We don't know the page size yet, so use a minimum value.
* Read both meta pages so we can use the latest one.
*/
@@ -4081,6 +4110,8 @@ mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta)
p = (MDB_page *)&pbuf;
if (!F_ISSET(p->mp_flags, P_META)) {
+ if (env->me_flags & MDB_RAWPART)
+ return ENOENT;
DPRINTF(("page %"Yu" not a meta page", p->mp_pgno));
return MDB_INVALID;
}
@@ -4148,6 +4179,18 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
psize = env->me_psize;
+ if ((env->me_flags & (MDB_RAWPART|MDB_WRITEMAP)) == (MDB_RAWPART|MDB_WRITEMAP)) {
+ p = (MDB_page *)env->me_map;
+ p->mp_pgno = 0;
+ p->mp_flags = P_META;
+ *(MDB_meta *)METADATA(p) = *meta;
+ q = (MDB_page *)((char *)p + psize);
+ q->mp_pgno = 1;
+ q->mp_flags = P_META;
+ *(MDB_meta *)METADATA(q) = *meta;
+ return 0;
+ }
+
p = calloc(NUM_METAS, psize);
if (!p)
return ENOMEM;
@@ -4410,7 +4453,7 @@ mdb_env_map(MDB_env *env, void *addr)
int prot = PROT_READ;
if (flags & MDB_WRITEMAP) {
prot |= PROT_WRITE;
- if (ftruncate(env->me_fd, env->me_mapsize) < 0)
+ if (!(flags & MDB_RAWPART) && ftruncate(env->me_fd, env->me_mapsize) < 0)
return ErrCode();
}
env->me_map = mmap(addr, env->me_mapsize, prot, MAP_SHARED,
@@ -5449,6 +5492,17 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
goto leave;
#endif
#endif
+#ifndef _WIN32
+ {
+ struct stat st;
+ flags &= ~MDB_RAWPART;
+ if (!stat(path, &st) && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))) {
+ flags |= MDB_RAWPART | MDB_NOSUBDIR;
+ if (!env->me_mapsize)
+ env->me_mapsize = DEFAULT_MAPSIZE;
+ }
+ }
+#endif
flags |= MDB_ENV_ACTIVE; /* tell mdb_env_close0() to clean up */
if (flags & MDB_RDONLY) {
@@ -7668,7 +7722,7 @@ more:
offset *= 4; /* space for 4 more */
break;
}
- /* FALLTHRU: Big enough MDB_DUPFIXED sub-page */
+ /* FALLTHRU *//* Big enough MDB_DUPFIXED sub-page */
case MDB_CURRENT:
fp->mp_flags |= P_DIRTY;
COPY_PGNO(fp->mp_pgno, mp->mp_pgno);
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index e2ac9df0b..db7fa6c7c 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -25,13 +25,6 @@
// 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.
-#ifndef _WIN32
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#endif
-
#include "db_lmdb.h"
#include <boost/filesystem.hpp>
@@ -1303,26 +1296,6 @@ BlockchainLMDB::BlockchainLMDB(bool batch_transactions): BlockchainDB()
m_hardfork = nullptr;
}
-void BlockchainLMDB::check_mmap_support()
-{
-#ifndef _WIN32
- const boost::filesystem::path mmap_test_file = m_folder / boost::filesystem::unique_path();
- int mmap_test_fd = ::open(mmap_test_file.string().c_str(), O_RDWR | O_CREAT, 0600);
- if (mmap_test_fd < 0)
- throw0(DB_ERROR((std::string("Failed to check for mmap support: open failed: ") + strerror(errno)).c_str()));
- epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([mmap_test_fd, &mmap_test_file]() {
- ::close(mmap_test_fd);
- boost::filesystem::remove(mmap_test_file.string());
- });
- if (write(mmap_test_fd, "mmaptest", 8) != 8)
- throw0(DB_ERROR((std::string("Failed to check for mmap support: write failed: ") + strerror(errno)).c_str()));
- void *mmap_res = mmap(NULL, 8, PROT_READ, MAP_SHARED, mmap_test_fd, 0);
- if (mmap_res == MAP_FAILED)
- throw0(DB_ERROR("This filesystem does not support mmap: use --data-dir to place the blockchain on a filesystem which does"));
- munmap(mmap_res, 8);
-#endif
-}
-
void BlockchainLMDB::open(const std::string& filename, const int db_flags)
{
int result;
@@ -1334,14 +1307,8 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
throw0(DB_OPEN_FAILURE("Attempted to open db, but it's already open"));
boost::filesystem::path direc(filename);
- if (boost::filesystem::exists(direc))
- {
- if (!boost::filesystem::is_directory(direc))
- throw0(DB_OPEN_FAILURE("LMDB needs a directory path, but a file was passed"));
- }
- else
- {
- if (!boost::filesystem::create_directories(direc))
+ if (!boost::filesystem::exists(direc) &&
+ !boost::filesystem::create_directories(direc)) {
throw0(DB_OPEN_FAILURE(std::string("Failed to create directory ").append(filename).c_str()));
}
@@ -1364,9 +1331,6 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
m_folder = filename;
- try { check_mmap_support(); }
- catch(...) { MERROR("Failed to check for mmap support, proceeding"); }
-
#ifdef __OpenBSD__
if ((mdb_flags & MDB_WRITEMAP) == 0) {
MCLOG_RED(el::Level::Info, "global", "Running on OpenBSD: forcing WRITEMAP");
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index 20edab2e9..bdae44948 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -359,7 +359,6 @@ public:
static int compare_string(const MDB_val *a, const MDB_val *b);
private:
- void check_mmap_support();
void do_resize(uint64_t size_increase=0);
bool need_resize(uint64_t threshold_size=0) const;