Merge pull request #7774

ade464a ITS#9385 fix using MDB_NOSUBDIR with nonexistent file (Kris Zyp)
033a32a Remove check is_directory check on lmdb path (Howard Chu)
b096e16 Revert 'db_lmdb: test for mmap support at init time' (Howard Chu)
493577a Silence spurious fallthru warning (Howard Chu)
b46a60e Fix rawpart flag collision (Howard Chu)
4e7586c More RAWPART support (Howard Chu)
747f5d3 Preliminary raw partition support (Howard Chu)
This commit is contained in:
luigi1111 2022-07-03 17:24:47 -05:00
commit 30a9183091
No known key found for this signature in database
GPG Key ID: F4ACA0183641E010
3 changed files with 58 additions and 41 deletions

View File

@ -1467,6 +1467,8 @@ struct MDB_env {
#endif #endif
/** Failed to update the meta page. Probably an I/O error. */ /** Failed to update the meta page. Probably an I/O error. */
#define MDB_FATAL_ERROR 0x80000000U #define MDB_FATAL_ERROR 0x80000000U
/** using a raw block device */
#define MDB_RAWPART 0x40000000U
/** Some fields are initialized. */ /** Some fields are initialized. */
#define MDB_ENV_ACTIVE 0x20000000U #define MDB_ENV_ACTIVE 0x20000000U
/** me_txkey is set */ /** me_txkey is set */
@ -4038,6 +4040,8 @@ fail:
return rc; return rc;
} }
static int ESECT mdb_env_map(MDB_env *env, void *addr);
/** Read the environment parameters of a DB environment before /** Read the environment parameters of a DB environment before
* mapping it into memory. * mapping it into memory.
* @param[in] env the environment handle * @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; int i, rc, off;
enum { Size = sizeof(pbuf) }; 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. /* We don't know the page size yet, so use a minimum value.
* Read both meta pages so we can use the latest one. * 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; p = (MDB_page *)&pbuf;
if (!F_ISSET(p->mp_flags, P_META)) { 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)); DPRINTF(("page %"Yu" not a meta page", p->mp_pgno));
return MDB_INVALID; return MDB_INVALID;
} }
@ -4148,6 +4179,18 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
psize = env->me_psize; 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); p = calloc(NUM_METAS, psize);
if (!p) if (!p)
return ENOMEM; return ENOMEM;
@ -4410,7 +4453,7 @@ mdb_env_map(MDB_env *env, void *addr)
int prot = PROT_READ; int prot = PROT_READ;
if (flags & MDB_WRITEMAP) { if (flags & MDB_WRITEMAP) {
prot |= PROT_WRITE; 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(); return ErrCode();
} }
env->me_map = mmap(addr, env->me_mapsize, prot, MAP_SHARED, env->me_map = mmap(addr, env->me_mapsize, prot, MAP_SHARED,
@ -5448,6 +5491,17 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
if (rc) if (rc)
goto leave; goto leave;
#endif #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 #endif
flags |= MDB_ENV_ACTIVE; /* tell mdb_env_close0() to clean up */ flags |= MDB_ENV_ACTIVE; /* tell mdb_env_close0() to clean up */
@ -7668,7 +7722,7 @@ more:
offset *= 4; /* space for 4 more */ offset *= 4; /* space for 4 more */
break; break;
} }
/* FALLTHRU: Big enough MDB_DUPFIXED sub-page */ /* FALLTHRU *//* Big enough MDB_DUPFIXED sub-page */
case MDB_CURRENT: case MDB_CURRENT:
fp->mp_flags |= P_DIRTY; fp->mp_flags |= P_DIRTY;
COPY_PGNO(fp->mp_pgno, mp->mp_pgno); COPY_PGNO(fp->mp_pgno, mp->mp_pgno);

View File

@ -25,13 +25,6 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // 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. // 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 "db_lmdb.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -1303,26 +1296,6 @@ BlockchainLMDB::BlockchainLMDB(bool batch_transactions): BlockchainDB()
m_hardfork = nullptr; 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) void BlockchainLMDB::open(const std::string& filename, const int db_flags)
{ {
int result; 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")); throw0(DB_OPEN_FAILURE("Attempted to open db, but it's already open"));
boost::filesystem::path direc(filename); boost::filesystem::path direc(filename);
if (boost::filesystem::exists(direc)) if (!boost::filesystem::exists(direc) &&
{ !boost::filesystem::create_directories(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))
throw0(DB_OPEN_FAILURE(std::string("Failed to create directory ").append(filename).c_str())); 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; m_folder = filename;
try { check_mmap_support(); }
catch(...) { MERROR("Failed to check for mmap support, proceeding"); }
#ifdef __OpenBSD__ #ifdef __OpenBSD__
if ((mdb_flags & MDB_WRITEMAP) == 0) { if ((mdb_flags & MDB_WRITEMAP) == 0) {
MCLOG_RED(el::Level::Info, "global", "Running on OpenBSD: forcing WRITEMAP"); MCLOG_RED(el::Level::Info, "global", "Running on OpenBSD: forcing WRITEMAP");

View File

@ -359,7 +359,6 @@ public:
static int compare_string(const MDB_val *a, const MDB_val *b); static int compare_string(const MDB_val *a, const MDB_val *b);
private: private:
void check_mmap_support();
void do_resize(uint64_t size_increase=0); void do_resize(uint64_t size_increase=0);
bool need_resize(uint64_t threshold_size=0) const; bool need_resize(uint64_t threshold_size=0) const;