mirror of
https://github.com/isar/libmdbx.git
synced 2025-04-01 14:52:57 +08:00
mdbx: доработка osal_bootid()
для LXC (backport).
Из LXC-контейнера не доступен файл хостовой системы "/proc/sys/kernel/random/boot_id". Вместо него, при каждом старте контейнера, создается и заполняется случайными данными собственный boot_id смонтированный через bind из tmpfs. https://github.com/lxc/lxc/issues/3027 Поэтому полноценный контроль по boot_id не возможен, так как при рестарте LXC-контейнера (но не хоста) boot_id будет меняться, хотя данные в unified page cache сохраняются. Таким образом, при рестарте LXC-контейнера, libmdbx будет производить откат БД до крайней точки устойчивой фиксации, что может приводить к утрате данных пользователя в случаях когда они могли быть сохранены. Однако, улучшить ситуацию пока не представляется возможным, как минимум до доступности boot_id хостовой системы изнутри LXC-контейнера. Этот коммит частично улучшает ситуацию тем, что позволяет использовать фейковый/замещенный boot_id размещенный в файловой системе с типом tmpfs при работе внутри LXC-контейнера.
This commit is contained in:
parent
4447793652
commit
3baaf70249
168
src/osal.c
168
src/osal.c
@ -3011,6 +3011,29 @@ __cold static LSTATUS mdbx_RegGetValue(HKEY hKey, LPCSTR lpSubKey,
|
||||
}
|
||||
#endif
|
||||
|
||||
static size_t hamming_weight(size_t v) {
|
||||
const size_t m1 = (size_t)UINT64_C(0x5555555555555555);
|
||||
const size_t m2 = (size_t)UINT64_C(0x3333333333333333);
|
||||
const size_t m4 = (size_t)UINT64_C(0x0f0f0f0f0f0f0f0f);
|
||||
const size_t h01 = (size_t)UINT64_C(0x0101010101010101);
|
||||
v -= (v >> 1) & m1;
|
||||
v = (v & m2) + ((v >> 2) & m2);
|
||||
v = (v + (v >> 4)) & m4;
|
||||
return (v * h01) >> (sizeof(v) * 8 - 8);
|
||||
}
|
||||
|
||||
static inline size_t hw64(uint64_t v) {
|
||||
size_t r = hamming_weight((size_t)v);
|
||||
if (sizeof(v) > sizeof(r))
|
||||
r += hamming_weight((size_t)(v >> sizeof(r) * 4 >> sizeof(r) * 4));
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool check_uuid(bin128_t uuid) {
|
||||
size_t hw = hw64(uuid.x) + hw64(uuid.y) + hw64(uuid.x ^ uuid.y);
|
||||
return (hw >> 6) == 1;
|
||||
}
|
||||
|
||||
__cold MDBX_MAYBE_UNUSED static bool
|
||||
bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
|
||||
if (n > 31) {
|
||||
@ -3044,7 +3067,7 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
|
||||
s->y += aligned.y;
|
||||
} else
|
||||
bootid_collect(s, p, n);
|
||||
return true;
|
||||
return check_uuid(*s);
|
||||
}
|
||||
|
||||
if (n)
|
||||
@ -3052,28 +3075,53 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
|
||||
return false;
|
||||
}
|
||||
|
||||
__cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
bin128_t bin = {{0, 0}};
|
||||
#if defined(__linux__) || defined(__gnu_linux__)
|
||||
|
||||
__cold static bool is_inside_lxc(void) {
|
||||
bool inside_lxc = false;
|
||||
FILE *mounted = setmntent("/proc/mounts", "r");
|
||||
if (mounted) {
|
||||
const struct mntent *ent;
|
||||
while (nullptr != (ent = getmntent(mounted))) {
|
||||
if (strcmp(ent->mnt_fsname, "lxcfs") == 0 &&
|
||||
strncmp(ent->mnt_dir, "/proc/", 6) == 0) {
|
||||
inside_lxc = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
endmntent(mounted);
|
||||
}
|
||||
return inside_lxc;
|
||||
}
|
||||
|
||||
__cold static bool proc_read_uuid(const char *path, bin128_t *target) {
|
||||
const int fd = open(path, O_RDONLY | O_NOFOLLOW);
|
||||
if (fd != -1) {
|
||||
struct statfs fs;
|
||||
char buf[42];
|
||||
const ssize_t len =
|
||||
(fstatfs(fd, &fs) == 0 &&
|
||||
(fs.f_type == /* procfs */ 0x9FA0 ||
|
||||
(fs.f_type == /* tmpfs */ 0x1021994 && is_inside_lxc())))
|
||||
? read(fd, buf, sizeof(buf))
|
||||
: -1;
|
||||
const int err = close(fd);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
if (len > 0)
|
||||
return bootid_parse_uuid(target, buf, len);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif /* Linux */
|
||||
|
||||
__cold bin128_t osal_bootid(void) {
|
||||
bin128_t uuid = {{0, 0}};
|
||||
bool got_machineid = false, got_boottime = false, got_bootseq = false;
|
||||
|
||||
#if defined(__linux__) || defined(__gnu_linux__)
|
||||
{
|
||||
const int fd =
|
||||
open("/proc/sys/kernel/random/boot_id", O_RDONLY | O_NOFOLLOW);
|
||||
if (fd != -1) {
|
||||
struct statfs fs;
|
||||
char buf[42];
|
||||
const ssize_t len =
|
||||
(fstatfs(fd, &fs) == 0 && fs.f_type == /* procfs */ 0x9FA0)
|
||||
? read(fd, buf, sizeof(buf))
|
||||
: -1;
|
||||
const int err = close(fd);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
if (len > 0 && bootid_parse_uuid(&bin, buf, len))
|
||||
return bin;
|
||||
}
|
||||
}
|
||||
if (proc_read_uuid("/proc/sys/kernel/random/boot_id", &uuid))
|
||||
return uuid;
|
||||
#endif /* Linux */
|
||||
|
||||
#if defined(__APPLE__) || defined(__MACH__)
|
||||
@ -3081,16 +3129,15 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
char buf[42];
|
||||
size_t len = sizeof(buf);
|
||||
if (!sysctlbyname("kern.bootsessionuuid", buf, &len, nullptr, 0) &&
|
||||
bootid_parse_uuid(&bin, buf, len))
|
||||
return bin;
|
||||
bootid_parse_uuid(&uuid, buf, len))
|
||||
return uuid;
|
||||
|
||||
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
|
||||
__MAC_OS_X_VERSION_MIN_REQUIRED > 1050
|
||||
uuid_t uuid;
|
||||
uuid_t hostuuid;
|
||||
struct timespec wait = {0, 1000000000u / 42};
|
||||
if (!gethostuuid(uuid, &wait) &&
|
||||
bootid_parse_uuid(&bin, uuid, sizeof(uuid)))
|
||||
got_machineid = true;
|
||||
if (!gethostuuid(hostuuid, &wait))
|
||||
got_machineid = bootid_parse_uuid(&uuid, hostuuid, sizeof(hostuuid));
|
||||
#endif /* > 10.5 */
|
||||
|
||||
struct timeval boottime;
|
||||
@ -3128,7 +3175,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
"MachineGuid", &buf.MachineGuid,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len < sizeof(buf))
|
||||
got_machineid = bootid_parse_uuid(&bin, &buf.MachineGuid, len);
|
||||
got_machineid = bootid_parse_uuid(&uuid, &buf.MachineGuid, len);
|
||||
|
||||
if (!got_machineid) {
|
||||
/* again, Windows is madness */
|
||||
@ -3146,7 +3193,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
"DigitalProductId", &buf.DigitalProductId,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
bootid_collect(&uuid, &buf.DigitalProductId, len);
|
||||
got_machineid = true;
|
||||
}
|
||||
len = sizeof(buf);
|
||||
@ -3154,7 +3201,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
"DigitalProductId", &buf.DigitalProductId,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
bootid_collect(&uuid, &buf.DigitalProductId, len);
|
||||
got_machineid = true;
|
||||
}
|
||||
len = sizeof(buf);
|
||||
@ -3162,7 +3209,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
"DigitalProductId", &buf.DigitalProductId,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
bootid_collect(&uuid, &buf.DigitalProductId, len);
|
||||
got_machineid = true;
|
||||
}
|
||||
}
|
||||
@ -3174,7 +3221,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BootId",
|
||||
&buf.BootId, &len) == ERROR_SUCCESS &&
|
||||
len > 1 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.BootId, len);
|
||||
bootid_collect(&uuid, &buf.BootId, len);
|
||||
got_bootseq = true;
|
||||
}
|
||||
|
||||
@ -3182,7 +3229,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BaseTime",
|
||||
&buf.BaseTime, &len) == ERROR_SUCCESS &&
|
||||
len >= sizeof(buf.BaseTime) && buf.BaseTime) {
|
||||
bootid_collect(&bin, &buf.BaseTime, len);
|
||||
bootid_collect(&uuid, &buf.BaseTime, len);
|
||||
got_boottime = true;
|
||||
}
|
||||
|
||||
@ -3198,7 +3245,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
buf.SysTimeOfDayInfoHacked.BootTime.QuadPart -
|
||||
buf.SysTimeOfDayInfoHacked.BootTimeBias;
|
||||
if (UnbiasedBootTime) {
|
||||
bootid_collect(&bin, &UnbiasedBootTime, sizeof(UnbiasedBootTime));
|
||||
bootid_collect(&uuid, &UnbiasedBootTime, sizeof(UnbiasedBootTime));
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@ -3206,7 +3253,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
if (!got_boottime) {
|
||||
uint64_t boottime = windows_bootime();
|
||||
if (boottime) {
|
||||
bootid_collect(&bin, &boottime, sizeof(boottime));
|
||||
bootid_collect(&uuid, &boottime, sizeof(boottime));
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@ -3223,8 +3270,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
(int *)
|
||||
#endif
|
||||
mib,
|
||||
ARRAY_LENGTH(mib), &buf, &len, NULL, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&bin, buf, len);
|
||||
ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&uuid, buf, len);
|
||||
}
|
||||
#endif /* CTL_HW && HW_UUID */
|
||||
|
||||
@ -3238,8 +3285,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
(int *)
|
||||
#endif
|
||||
mib,
|
||||
ARRAY_LENGTH(mib), &buf, &len, NULL, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&bin, buf, len);
|
||||
ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&uuid, buf, len);
|
||||
}
|
||||
#endif /* CTL_KERN && KERN_HOSTUUID */
|
||||
|
||||
@ -3247,16 +3294,33 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
if (!got_machineid) {
|
||||
char buf[42];
|
||||
size_t len = sizeof(buf);
|
||||
if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, NULL, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&bin, buf, len);
|
||||
if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, nullptr, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&uuid, buf, len);
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#if !(defined(_WIN32) || defined(_WIN64))
|
||||
if (!got_machineid) {
|
||||
int fd = open("/etc/machine-id", O_RDONLY);
|
||||
if (fd == -1)
|
||||
fd = open("/var/lib/dbus/machine-id", O_RDONLY);
|
||||
if (fd != -1) {
|
||||
char buf[42];
|
||||
const ssize_t len = read(fd, buf, sizeof(buf));
|
||||
const int err = close(fd);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
if (len > 0)
|
||||
got_machineid = bootid_parse_uuid(&uuid, buf, len);
|
||||
}
|
||||
}
|
||||
#endif /* !Windows */
|
||||
|
||||
#if _XOPEN_SOURCE_EXTENDED
|
||||
if (!got_machineid) {
|
||||
const int hostid = gethostid();
|
||||
if (hostid > 0) {
|
||||
bootid_collect(&bin, &hostid, sizeof(hostid));
|
||||
const long hostid = gethostid();
|
||||
if (hostid != 0 && hostid != -1) {
|
||||
bootid_collect(&uuid, &hostid, sizeof(hostid));
|
||||
got_machineid = true;
|
||||
}
|
||||
}
|
||||
@ -3264,8 +3328,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
|
||||
if (!got_machineid) {
|
||||
lack:
|
||||
bin.x = bin.y = 0;
|
||||
return bin;
|
||||
uuid.x = uuid.y = 0;
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -3280,9 +3344,9 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
(int *)
|
||||
#endif
|
||||
mib,
|
||||
ARRAY_LENGTH(mib), &boottime, &len, NULL, 0) == 0 &&
|
||||
ARRAY_LENGTH(mib), &boottime, &len, nullptr, 0) == 0 &&
|
||||
len == sizeof(boottime) && boottime.tv_sec) {
|
||||
bootid_collect(&bin, &boottime, len);
|
||||
bootid_collect(&uuid, &boottime, len);
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@ -3299,11 +3363,11 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
switch (kn->data_type) {
|
||||
case KSTAT_DATA_INT32:
|
||||
case KSTAT_DATA_UINT32:
|
||||
bootid_collect(&bin, &kn->value, sizeof(int32_t));
|
||||
bootid_collect(&uuid, &kn->value, sizeof(int32_t));
|
||||
got_boottime = true;
|
||||
case KSTAT_DATA_INT64:
|
||||
case KSTAT_DATA_UINT64:
|
||||
bootid_collect(&bin, &kn->value, sizeof(int64_t));
|
||||
bootid_collect(&uuid, &kn->value, sizeof(int64_t));
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@ -3319,12 +3383,12 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
const struct utmpx id = {.ut_type = BOOT_TIME};
|
||||
const struct utmpx *entry = getutxid(&id);
|
||||
if (entry) {
|
||||
bootid_collect(&bin, entry, sizeof(*entry));
|
||||
bootid_collect(&uuid, entry, sizeof(*entry));
|
||||
got_boottime = true;
|
||||
while (unlikely((entry = getutxid(&id)) != nullptr)) {
|
||||
/* have multiple reboot records, assuming we can distinguish next
|
||||
* bootsession even if RTC is wrong or absent */
|
||||
bootid_collect(&bin, entry, sizeof(*entry));
|
||||
bootid_collect(&uuid, entry, sizeof(*entry));
|
||||
got_bootseq = true;
|
||||
}
|
||||
}
|
||||
@ -3353,7 +3417,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
|
||||
goto lack;
|
||||
}
|
||||
|
||||
return bin;
|
||||
return uuid;
|
||||
}
|
||||
|
||||
__cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages,
|
||||
|
Loading…
x
Reference in New Issue
Block a user