From c66dac50c32f79f21612264dfb02a85d20394d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Fri, 13 Dec 2024 22:30:40 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20`osal=5Fbootid()`=20=D0=B4=D0=BB=D1=8F=20L?= =?UTF-8?q?XC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Из 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-контейнера. --- src/osal.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/osal.c b/src/osal.c index cdef5712..01f0b11d 100644 --- a/src/osal.c +++ b/src/osal.c @@ -2877,12 +2877,32 @@ __cold MDBX_MAYBE_UNUSED static bool bootid_parse_uuid(bin128_t *s, const void * } #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) ? read(fd, buf, sizeof(buf)) : -1; + 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; @@ -3061,10 +3081,27 @@ __cold static bin128_t osal_bootid(void) { } #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) { + const long hostid = gethostid(); + if (hostid != 0 && hostid != -1) { bootid_collect(&uuid, &hostid, sizeof(hostid)); got_machineid = true; }