Add riscv64 to ExclusiveArch

This commit is contained in:
Andrew Lukoshko 2026-07-17 01:19:55 +00:00 committed by root
commit 9027bcaa08
5 changed files with 1293 additions and 2 deletions

47
2876.patch Normal file
View File

@ -0,0 +1,47 @@
From 89150bea7218b9c7131b7a7712a84b9c564d8feb Mon Sep 17 00:00:00 2001
From: 3idey <elaidya225@gmail.com>
Date: Thu, 5 Feb 2026 20:58:01 +0200
Subject: [PATCH] fsnotify: Fix file descriptor leak in restore_one_inotify()
When restoring inotify watches, the restore_one_inotify() function opens
a file descriptor via get_mark_path() and stores it in the 'target'
variable. However, in two error paths, the function returns directly
without properly closing this file descriptor:
1. When INOTIFY_IOC_SETNEXTWD ioctl fails (line 556)
2. When has_inotify_setnextwd is true but watch descriptor mismatch
occurs (line 577)
Both cases bypass the cleanup code at the 'err' label which calls
close_safe(&target), resulting in a file descriptor leak.
Fix this by using 'goto err' instead of 'return -1' in both error paths,
ensuring proper cleanup of the target file descriptor.
Signed-off-by: 3idey <elaidya225@gmail.com>
---
criu/fsnotify.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/criu/fsnotify.c b/criu/fsnotify.c
index 8572dc2f3c..7ede629077 100644
--- a/criu/fsnotify.c
+++ b/criu/fsnotify.c
@@ -553,7 +553,7 @@ static int restore_one_inotify(int inotify_fd, struct fsnotify_mark_info *info)
if (kdat.has_inotify_setnextwd) {
if (ioctl(inotify_fd, INOTIFY_IOC_SETNEXTWD, iwe->wd)) {
pr_perror("Can't set next inotify wd");
- return -1;
+ goto err;
}
}
@@ -573,7 +573,7 @@ static int restore_one_inotify(int inotify_fd, struct fsnotify_mark_info *info)
}
if (kdat.has_inotify_setnextwd)
- return -1;
+ goto err;
inotify_rm_watch(inotify_fd, wd);
}

349
2880.patch Normal file
View File

@ -0,0 +1,349 @@
From 9502782b84efbabfd603e66b665d95663a01086e Mon Sep 17 00:00:00 2001
From: 3idey <elaidya225@gmail.com>
Date: Sat, 7 Feb 2026 13:00:02 +0200
Subject: [PATCH] fsnotify: Improve error messages with more context
Error messages now include additional context to aid debugging:
- Device and inode numbers for file handles
- Watch descriptor (wd) for inotify operations
- Mask values for fanotify marks
- Mount ID for mount-related operations
This makes it much easier to diagnose checkpoint/restore failures
by providing complete information about which watch or mark failed
and why, without needing to add debug logging.
Signed-off-by: 3idey <elaidya225@gmail.com>
---
criu/fsnotify.c | 119 ++++++++++++++++++++++++++++++++++++------------
1 file changed, 89 insertions(+), 30 deletions(-)
diff --git a/criu/fsnotify.c b/criu/fsnotify.c
index 7ede629077..dd468ecaaf 100644
--- a/criu/fsnotify.c
+++ b/criu/fsnotify.c
@@ -102,7 +102,11 @@ static int open_by_handle(void *arg, int fd, int pid)
return syscall(__NR_open_by_handle_at, fd, arg, O_PATH);
}
-enum { ERR_NO_MOUNT = -1, ERR_NO_PATH_IN_MOUNT = -2, ERR_GENERIC = -3 };
+enum {
+ ERR_NO_MOUNT = -1,
+ ERR_NO_PATH_IN_MOUNT = -2,
+ ERR_GENERIC = -3
+};
static char *alloc_openable(unsigned int s_dev, unsigned long i_ino, FhEntry *f_handle)
{
@@ -306,8 +310,11 @@ static int check_one_wd(InotifyWdEntry *we)
pr_warn_once("\t\tDetected FS_EVENT_ON_CHILD bit "
"in mask (will be ignored on restore)\n");
- if (check_open_handle(we->s_dev, we->i_ino, we->f_handle))
+ if (check_open_handle(we->s_dev, we->i_ino, we->f_handle)) {
+ pr_err("Failed to check handle for inotify wd %#x (dev %#x ino %#" PRIx64 " mask %#x)\n",
+ we->wd, we->s_dev, we->i_ino, we->mask);
return -1;
+ }
return 0;
}
@@ -328,8 +335,10 @@ static int dump_one_inotify(int lfd, u32 id, const struct fd_parms *p)
ie.flags = p->flags;
ie.fown = (FownEntry *)&p->fown;
- if (parse_fdinfo(lfd, FD_TYPES__INOTIFY, &ie))
+ if (parse_fdinfo(lfd, FD_TYPES__INOTIFY, &ie)) {
+ pr_err("Failed to parse fdinfo for inotify id %#x\n", id);
goto free;
+ }
for (i = 0; i < ie.n_wd; i++)
if (check_one_wd(ie.wd[i]))
@@ -357,14 +366,19 @@ static int pre_dump_one_inotify(int pid, int lfd)
InotifyFileEntry ie = INOTIFY_FILE_ENTRY__INIT;
int i;
- if (parse_fdinfo_pid(pid, lfd, FD_TYPES__INOTIFY, &ie))
+ if (parse_fdinfo_pid(pid, lfd, FD_TYPES__INOTIFY, &ie)) {
+ pr_err("Failed to parse fdinfo for inotify (pid %d lfd %d)\n", pid, lfd);
return -1;
+ }
for (i = 0; i < ie.n_wd; i++) {
InotifyWdEntry *we = ie.wd[i];
- if (irmap_queue_cache(we->s_dev, we->i_ino, we->f_handle))
+ if (irmap_queue_cache(we->s_dev, we->i_ino, we->f_handle)) {
+ pr_err("Failed to queue irmap cache for inotify wd %#x (dev %#x ino %#" PRIx64 ")\n",
+ we->wd, we->s_dev, we->i_ino);
return -1;
+ }
xfree(we);
}
@@ -400,7 +414,8 @@ static int check_one_mark(FanotifyMarkEntry *fme)
m = lookup_mnt_id(fme->me->mnt_id);
if (!m) {
- pr_err("Can't find mnt_id 0x%x\n", fme->me->mnt_id);
+ pr_err("Can't find mnt_id %#x for fanotify mark (mask %#x)\n",
+ fme->me->mnt_id, fme->mask);
return -1;
}
if (!(root_ns_mask & CLONE_NEWNS))
@@ -430,8 +445,10 @@ static int dump_one_fanotify(int lfd, u32 id, const struct fd_parms *p)
fe.flags = p->flags;
fe.fown = (FownEntry *)&p->fown;
- if (parse_fdinfo(lfd, FD_TYPES__FANOTIFY, &fe) < 0)
+ if (parse_fdinfo(lfd, FD_TYPES__FANOTIFY, &fe) < 0) {
+ pr_err("Failed to parse fdinfo for fanotify id %#x\n", id);
goto free;
+ }
for (i = 0; i < fe.n_mark; i++)
if (check_one_mark(fe.mark[i]))
@@ -456,18 +473,23 @@ static int pre_dump_one_fanotify(int pid, int lfd)
FanotifyFileEntry fe = FANOTIFY_FILE_ENTRY__INIT;
int i;
- if (parse_fdinfo_pid(pid, lfd, FD_TYPES__FANOTIFY, &fe))
+ if (parse_fdinfo_pid(pid, lfd, FD_TYPES__FANOTIFY, &fe)) {
+ pr_err("Failed to parse fdinfo for fanotify (pid %d lfd %d)\n", pid, lfd);
return -1;
+ }
for (i = 0; i < fe.n_mark; i++) {
FanotifyMarkEntry *me = fe.mark[i];
- if (me->type == MARK_TYPE__INODE && irmap_queue_cache(me->s_dev, me->ie->i_ino, me->ie->f_handle))
+ if (me->type == MARK_TYPE__INODE && irmap_queue_cache(me->s_dev, me->ie->i_ino, me->ie->f_handle)) {
+ pr_err("Failed to queue irmap cache for fanotify mark (dev %#x ino %#" PRIx64 " mask %#x)\n",
+ me->s_dev, me->ie->i_ino, me->mask);
return -1;
+ }
xfree(me);
}
- xfree(fe.mark);
+
return 0;
}
@@ -507,7 +529,15 @@ static char *get_mark_path(const char *who, struct file_remap *remap, FhEntry *f
*target = open_handle(s_dev, i_ino, f_handle);
if (*target < 0) {
- pr_perror("Unable to open %s", f_handle->path);
+ if (remap)
+ pr_perror("Unable to open %s via remap %s (dev %#x ino %#lx)",
+ who, remap->rpath, s_dev, i_ino);
+ else if (f_handle->path)
+ pr_perror("Unable to open %s via path %s (dev %#x ino %#lx)",
+ who, f_handle->path, s_dev, i_ino);
+ else
+ pr_perror("Unable to open %s by handle (dev %#x ino %#lx)",
+ who, s_dev, i_ino);
goto err;
}
@@ -542,8 +572,11 @@ static int restore_one_inotify(int inotify_fd, struct fsnotify_mark_info *info)
uint32_t mask;
path = get_mark_path("inotify", info->remap, iwe->f_handle, iwe->i_ino, iwe->s_dev, buf, &target);
- if (!path)
+ if (!path) {
+ pr_err("Failed to get path for inotify wd %#x (dev %#x ino %#" PRIx64 " mask %#x)\n",
+ iwe->wd, iwe->s_dev, iwe->i_ino, iwe->mask);
goto err;
+ }
mask = iwe->mask & IN_ALL_EVENTS;
if (iwe->mask & ~IN_ALL_EVENTS) {
@@ -552,7 +585,8 @@ static int restore_one_inotify(int inotify_fd, struct fsnotify_mark_info *info)
if (kdat.has_inotify_setnextwd) {
if (ioctl(inotify_fd, INOTIFY_IOC_SETNEXTWD, iwe->wd)) {
- pr_perror("Can't set next inotify wd");
+ pr_perror("Can't set next inotify wd to %#x (dev %#x ino %#" PRIx64 ")",
+ iwe->wd, iwe->s_dev, iwe->i_ino);
goto err;
}
}
@@ -562,13 +596,15 @@ static int restore_one_inotify(int inotify_fd, struct fsnotify_mark_info *info)
wd = inotify_add_watch(inotify_fd, path, mask);
if (wd < 0) {
- pr_perror("Can't add watch for 0x%x with 0x%x", inotify_fd, iwe->wd);
+ pr_perror("Can't add inotify watch for fd %d wd %#x (dev %#x ino %#" PRIx64 " mask %#x)",
+ inotify_fd, iwe->wd, iwe->s_dev, iwe->i_ino, mask);
break;
} else if (wd == iwe->wd) {
ret = 0;
break;
} else if (wd > iwe->wd) {
- pr_err("Unsorted watch 0x%x found for 0x%x with 0x%x\n", wd, inotify_fd, iwe->wd);
+ pr_err("Unsorted inotify watch %#x found (expected %#x, dev %#x ino %#" PRIx64 ")\n",
+ wd, iwe->wd, iwe->s_dev, iwe->i_ino);
break;
}
@@ -599,7 +635,8 @@ static int restore_one_fanotify(int fd, struct fsnotify_mark_info *mark)
if (root_ns_mask & CLONE_NEWNS) {
m = lookup_mnt_id(fme->me->mnt_id);
if (!m) {
- pr_err("Can't find mount mnt_id 0x%x\n", fme->me->mnt_id);
+ pr_err("Can't find mount mnt_id %#x for fanotify mark (mask %#x)\n",
+ fme->me->mnt_id, fme->mask);
return -1;
}
nsid = m->nsid;
@@ -610,7 +647,8 @@ static int restore_one_fanotify(int fd, struct fsnotify_mark_info *mark)
target = openat(mntns_root, p, O_PATH);
if (target == -1) {
- pr_perror("Unable to open %s", p);
+ pr_perror("Unable to open mount point %s (mnt_id %#x)",
+ p, fme->me->mnt_id);
goto err;
}
@@ -620,10 +658,13 @@ static int restore_one_fanotify(int fd, struct fsnotify_mark_info *mark)
} else if (fme->type == MARK_TYPE__INODE) {
path = get_mark_path("fanotify", mark->remap, fme->ie->f_handle, fme->ie->i_ino, fme->s_dev, buf,
&target);
- if (!path)
+ if (!path) {
+ pr_err("Failed to get path for fanotify mark (dev %#x ino %#" PRIx64 " mask %#x)\n",
+ fme->s_dev, fme->ie->i_ino, fme->mask);
goto err;
+ }
} else {
- pr_err("Bad fsnotify mark type 0x%x\n", fme->type);
+ pr_err("Bad fsnotify mark type %#x (mask %#x)\n", fme->type, fme->mask);
goto err;
}
@@ -632,7 +673,8 @@ static int restore_one_fanotify(int fd, struct fsnotify_mark_info *mark)
if (mark->fme->mask) {
ret = fanotify_mark(fd, flags, fme->mask, AT_FDCWD, path);
if (ret) {
- pr_err("Adding fanotify mask 0x%x on 0x%x/%s failed (%d)\n", fme->mask, fme->id, path, ret);
+ pr_perror("Failed to add fanotify mask %#x on id %#x (dev %#x path %s)",
+ fme->mask, fme->id, fme->s_dev, path);
goto err;
}
}
@@ -640,8 +682,8 @@ static int restore_one_fanotify(int fd, struct fsnotify_mark_info *mark)
if (fme->ignored_mask) {
ret = fanotify_mark(fd, flags | FAN_MARK_IGNORED_MASK, fme->ignored_mask, AT_FDCWD, path);
if (ret) {
- pr_err("Adding fanotify ignored-mask 0x%x on 0x%x/%s failed (%d)\n", fme->ignored_mask, fme->id,
- path, ret);
+ pr_perror("Failed to add fanotify ignored-mask %#x on id %#x (dev %#x path %s)",
+ fme->ignored_mask, fme->id, fme->s_dev, path);
goto err;
}
}
@@ -661,13 +703,16 @@ static int open_inotify_fd(struct file_desc *d, int *new_fd)
tmp = inotify_init1(info->ife->flags);
if (tmp < 0) {
- pr_perror("Can't create inotify for %#08x", info->ife->id);
+ pr_perror("Can't create inotify fd for id %#08x (flags %#x)",
+ info->ife->id, info->ife->flags);
return -1;
}
list_for_each_entry(wd_info, &info->marks, list) {
pr_info("\tRestore 0x%x wd for %#08x\n", wd_info->iwe->wd, wd_info->iwe->id);
if (restore_one_inotify(tmp, wd_info)) {
+ pr_err("Failed to restore inotify wd %#x for id %#08x\n",
+ wd_info->iwe->wd, wd_info->iwe->id);
close_safe(&tmp);
return -1;
}
@@ -698,13 +743,15 @@ static int open_fanotify_fd(struct file_desc *d, int *new_fd)
ret = fanotify_init(flags, info->ffe->evflags);
if (ret < 0) {
- pr_perror("Can't init fanotify mark (%d)", ret);
+ pr_perror("Can't init fanotify for id %#08x (flags %#x evflags %#x)",
+ info->ffe->id, flags, info->ffe->evflags);
return -1;
}
list_for_each_entry(mark, &info->marks, list) {
pr_info("\tRestore fanotify for %#08x\n", mark->fme->id);
if (restore_one_fanotify(ret, mark)) {
+ pr_err("Failed to restore fanotify mark for id %#08x\n", mark->fme->id);
close_safe(&ret);
return -1;
}
@@ -786,15 +833,21 @@ static int collect_one_inotify(void *o, ProtobufCMessage *msg, struct cr_img *im
struct fsnotify_mark_info *mark;
mark = xmalloc(sizeof(*mark));
- if (!mark)
+ if (!mark) {
+ pr_err("Failed to allocate inotify mark for id %#08x wd %#x\n",
+ info->ife->id, info->ife->wd[i]->wd);
return -1;
+ }
mark->iwe = info->ife->wd[i];
INIT_LIST_HEAD(&mark->list);
mark->remap = NULL;
- if (__collect_inotify_mark(info, mark))
+ if (__collect_inotify_mark(info, mark)) {
+ pr_err("Failed to collect inotify mark for id %#08x wd %#x\n",
+ info->ife->id, info->ife->wd[i]->wd);
return -1;
+ }
}
return file_desc_add(&info->d, info->ife->id, &inotify_desc_ops);
@@ -820,15 +873,19 @@ static int collect_one_fanotify(void *o, ProtobufCMessage *msg, struct cr_img *i
struct fsnotify_mark_info *mark;
mark = xmalloc(sizeof(*mark));
- if (!mark)
+ if (!mark) {
+ pr_err("Failed to allocate fanotify mark for id %#08x\n", info->ffe->id);
return -1;
+ }
mark->fme = info->ffe->mark[i];
INIT_LIST_HEAD(&mark->list);
mark->remap = NULL;
- if (__collect_fanotify_mark(info, mark))
+ if (__collect_fanotify_mark(info, mark)) {
+ pr_err("Failed to collect fanotify mark for id %#08x\n", info->ffe->id);
return -1;
+ }
}
return file_desc_add(&info->d, info->ffe->id, &fanotify_desc_ops);
@@ -865,7 +922,8 @@ static int collect_one_inotify_mark(void *o, ProtobufCMessage *msg, struct cr_im
d = find_file_desc_raw(FD_TYPES__INOTIFY, mark->iwe->id);
if (!d) {
- pr_err("Can't find inotify with id %#08x\n", mark->iwe->id);
+ pr_err("Can't find inotify with id %#08x for wd %#x\n",
+ mark->iwe->id, mark->iwe->wd);
return -1;
}
@@ -893,7 +951,8 @@ static int collect_one_fanotify_mark(void *o, ProtobufCMessage *msg, struct cr_i
d = find_file_desc_raw(FD_TYPES__FANOTIFY, mark->fme->id);
if (!d) {
- pr_err("Can't find fanotify with id %#08x\n", mark->fme->id);
+ pr_err("Can't find fanotify with id %#08x for mark (mask %#x)\n",
+ mark->fme->id, mark->fme->mask);
return -1;
}

103
2881.patch Normal file
View File

@ -0,0 +1,103 @@
From 33ebc40be98ed7a7132c2daff155c582dc74b5ee Mon Sep 17 00:00:00 2001
From: 3idey <elaidya225@gmail.com>
Date: Sun, 8 Feb 2026 12:36:49 +0200
Subject: [PATCH 1/2] fsnotify: Fix memory leak in pre_dump_one_inotify error
path
When irmap_queue_cache fails, the remaining inotify watch descriptors
and the wd array are not freed, causing a memory leak.
Add cleanup label to ensure proper deallocation of remaining entries
and the wd array on error paths.
Signed-off-by: 3idey <elaidya225@gmail.com>
---
criu/fsnotify.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/criu/fsnotify.c b/criu/fsnotify.c
index dd468ecaaf..55bae63bd8 100644
--- a/criu/fsnotify.c
+++ b/criu/fsnotify.c
@@ -364,7 +364,7 @@ static int dump_one_inotify(int lfd, u32 id, const struct fd_parms *p)
static int pre_dump_one_inotify(int pid, int lfd)
{
InotifyFileEntry ie = INOTIFY_FILE_ENTRY__INIT;
- int i;
+ int i, ret = -1;
if (parse_fdinfo_pid(pid, lfd, FD_TYPES__INOTIFY, &ie)) {
pr_err("Failed to parse fdinfo for inotify (pid %d lfd %d)\n", pid, lfd);
@@ -377,13 +377,18 @@ static int pre_dump_one_inotify(int pid, int lfd)
if (irmap_queue_cache(we->s_dev, we->i_ino, we->f_handle)) {
pr_err("Failed to queue irmap cache for inotify wd %#x (dev %#x ino %#" PRIx64 ")\n",
we->wd, we->s_dev, we->i_ino);
- return -1;
+ goto err;
}
xfree(we);
}
- return 0;
+ ret = 0;
+err:
+ for (; i < ie.n_wd; i++)
+ xfree(ie.wd[i]);
+ xfree(ie.wd);
+ return ret;
}
const struct fdtype_ops inotify_dump_ops = {
From 19ac1d63287abaa5a2b49c507c45b0d0a2cb4bb8 Mon Sep 17 00:00:00 2001
From: 3idey <elaidya225@gmail.com>
Date: Sun, 8 Feb 2026 12:37:11 +0200
Subject: [PATCH 2/2] fsnotify: Fix memory leak in pre_dump_one_fanotify error
path
When irmap_queue_cache fails, the remaining fanotify mark entries
and the mark array are not freed, causing a memory leak.
Add cleanup label to ensure proper deallocation of remaining entries
and the mark array on error paths.
Signed-off-by: 3idey <elaidya225@gmail.com>
---
criu/fsnotify.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/criu/fsnotify.c b/criu/fsnotify.c
index 55bae63bd8..5c05fa28fe 100644
--- a/criu/fsnotify.c
+++ b/criu/fsnotify.c
@@ -476,7 +476,7 @@ static int dump_one_fanotify(int lfd, u32 id, const struct fd_parms *p)
static int pre_dump_one_fanotify(int pid, int lfd)
{
FanotifyFileEntry fe = FANOTIFY_FILE_ENTRY__INIT;
- int i;
+ int i, ret = -1;
if (parse_fdinfo_pid(pid, lfd, FD_TYPES__FANOTIFY, &fe)) {
pr_err("Failed to parse fdinfo for fanotify (pid %d lfd %d)\n", pid, lfd);
@@ -489,13 +489,18 @@ static int pre_dump_one_fanotify(int pid, int lfd)
if (me->type == MARK_TYPE__INODE && irmap_queue_cache(me->s_dev, me->ie->i_ino, me->ie->f_handle)) {
pr_err("Failed to queue irmap cache for fanotify mark (dev %#x ino %#" PRIx64 " mask %#x)\n",
me->s_dev, me->ie->i_ino, me->mask);
- return -1;
+ goto err;
}
xfree(me);
}
- return 0;
+ ret = 0;
+err:
+ for (; i < fe.n_mark; i++)
+ xfree(fe.mark[i]);
+ xfree(fe.mark);
+ return ret;
}
const struct fdtype_ops fanotify_dump_ops = {

778
3043.patch Normal file
View File

@ -0,0 +1,778 @@
From 143b1978b47c519c3754bd4139798bc177cddd97 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber@redhat.com>
Date: Thu, 11 Jun 2026 15:24:46 +0000
Subject: [PATCH 1/3] fsnotify: add overlay directory walk fallback
When a process has inotify (or fanotify) watches on files inside an
overlayfs mount, criu dump fails because open_by_handle_at() does not
work for overlay file handles (type OVL_FILEID_V1 = 0xf8). The dump
log shows:
fsnotify: wd 0x000001 s_dev 0x00002d i_ino 0x101ad2 mask 0x00033a
fsnotify: [fhandle] bytes 0x000020 type 0x0000f8 ...
fsnotify: Handle 0x2d:0x101ad2 cannot be opened
Error (criu/fsnotify.c:284): fsnotify: Can't dump that handle
To reproduce manually:
mkdir -p /tmp/{lower,upper,work,merged}
touch /tmp/lower/testfile
mount -t overlay overlay \
-o lowerdir=/tmp/lower,upperdir=/tmp/upper,workdir=/tmp/work \
/tmp/merged
inotifywait -m /tmp/merged/testfile &
PID=$!
criu dump -t $PID -D /tmp/imgs --shell-job --ext-unix-sk
alloc_openable() iterates mounts matching s_dev and tries
open_by_handle_at() for each one. Overlay file handles use the
private OVL_FILEID_V1 type which open_by_handle_at() does not
support, so the call always fails and the dump aborts.
Add a fallback for overlay mounts: when open_by_handle_at() fails
and the mount is identified as FSTYPE__OVERLAYFS, walk the overlay
mount's directory tree with opendir/readdir/fstatat to find the
file matching the (s_dev, i_ino) pair from the handle. Store the
discovered absolute path in f_handle->path so that get_mark_path()
uses the path-based openat() strategy on restore, which works on
overlay mounts.
The fallback only triggers when open_by_handle_at() fails AND the
mount type is FSTYPE__OVERLAYFS, so there is no impact on other
filesystems.
Assisted-by: Claude Code (claude-opus-4-6):default
Signed-off-by: Adrian Reber <areber@redhat.com>
---
criu/fsnotify.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 182 insertions(+), 1 deletion(-)
diff --git a/criu/fsnotify.c b/criu/fsnotify.c
index eb80dd9615..498e48635d 100644
--- a/criu/fsnotify.c
+++ b/criu/fsnotify.c
@@ -7,6 +7,7 @@
#include <string.h>
#include <utime.h>
#include <limits.h>
+#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/inotify.h>
@@ -108,6 +109,163 @@ enum {
ERR_GENERIC = -3
};
+#define OVL_WALK_MAX_DEPTH 64
+#define OVL_WALK_WARN_THRESHOLD 10000
+
+/*
+ * Recursively walk a directory tree looking for an inode matching
+ * (s_dev, i_ino). Returns an allocated path string on success,
+ * NULL when not found. The caller is responsible for freeing the
+ * returned string via xfree().
+ *
+ * Note: this function takes ownership of @dirfd and closes it
+ * (via fdopendir/closedir) whether it succeeds or fails.
+ *
+ * @visited is incremented for each inode examined and is used to
+ * emit a one-time warning when the walk becomes expensive.
+ */
+static char *__walk_overlay_dir(int dirfd, const char *base,
+ unsigned int s_dev,
+ unsigned long i_ino, int depth,
+ unsigned long *visited)
+{
+ DIR *dfd;
+ struct dirent *de;
+ char *found = NULL;
+
+ if (depth <= 0) {
+ close(dirfd);
+ return NULL;
+ }
+
+ dfd = fdopendir(dirfd);
+ if (!dfd) {
+ pr_perror("Can't fdopendir for overlay walk");
+ close(dirfd);
+ return NULL;
+ }
+
+ while (1) {
+ struct stat st;
+
+ errno = 0;
+ de = readdir(dfd);
+ if (!de)
+ break;
+
+ if (dir_dots(de))
+ continue;
+
+ if (fstatat(dirfd, de->d_name, &st,
+ AT_SYMLINK_NOFOLLOW) < 0) {
+ pr_debug("overlay walk: fstatat(%s/%s) failed: %s\n",
+ base, de->d_name, strerror(errno));
+ continue;
+ }
+
+ (*visited)++;
+ if (*visited == OVL_WALK_WARN_THRESHOLD)
+ pr_warn("overlay walk: examined %lu entries so far "
+ "looking for ino %lx, mount may be large\n",
+ *visited, i_ino);
+
+ if (MKKDEV(major(st.st_dev), minor(st.st_dev)) == s_dev &&
+ st.st_ino == i_ino) {
+ found = xsprintf("%s/%s", base, de->d_name);
+ if (!found)
+ pr_err("OOM building overlay path for ino %lx\n",
+ i_ino);
+ break;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ int subfd;
+ char *subbase;
+
+ subfd = openat(dirfd, de->d_name,
+ O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ if (subfd < 0)
+ continue;
+
+ subbase = xsprintf("%s/%s", base, de->d_name);
+ if (!subbase) {
+ close(subfd);
+ continue;
+ }
+
+ found = __walk_overlay_dir(subfd, subbase,
+ s_dev, i_ino,
+ depth - 1,
+ visited);
+ xfree(subbase);
+ if (found)
+ break;
+ }
+ }
+
+ if (!de && errno)
+ pr_perror("overlay walk: readdir failed on %s", base);
+
+ closedir(dfd);
+ return found;
+}
+
+/*
+ * Try to locate a file on an overlay mount by walking the directory
+ * tree and matching (s_dev, i_ino). Returns an allocated absolute
+ * path (e.g. "/tmp/merged/subdir/file") on success, NULL on failure.
+ */
+static char *find_path_on_overlay(struct mount_info *m,
+ unsigned int s_dev,
+ unsigned long i_ino)
+{
+ int root_fd, mount_fd;
+ unsigned long visited = 0;
+ char *base, *found;
+ struct stat st;
+
+ root_fd = mntns_get_root_fd(m->nsid);
+ if (root_fd < 0)
+ return NULL;
+
+ /*
+ * ns_mountpoint has a leading dot, e.g. "./tmp/merged",
+ * which makes it relative to mntns root for openat.
+ */
+ mount_fd = openat(root_fd, m->ns_mountpoint, O_RDONLY | O_DIRECTORY);
+ if (mount_fd < 0) {
+ pr_perror("Can't open overlay mountpoint %s",
+ m->ns_mountpoint);
+ return NULL;
+ }
+
+ /*
+ * The path stored in f_handle->path must be absolute so
+ * that get_mark_path() can strip the leading "/" and use
+ * openat(mntns_root, path + 1, O_PATH) on restore.
+ * ns_mountpoint + 1 gives us e.g. "/tmp/merged".
+ */
+ base = m->ns_mountpoint + 1;
+
+ /* Check if the mountpoint directory itself is the target */
+ if (fstat(mount_fd, &st) == 0 &&
+ MKKDEV(major(st.st_dev), minor(st.st_dev)) == s_dev &&
+ st.st_ino == i_ino) {
+ close(mount_fd);
+ return xstrdup(base);
+ }
+
+ found = __walk_overlay_dir(mount_fd, base, s_dev, i_ino,
+ OVL_WALK_MAX_DEPTH, &visited);
+ /* mount_fd is consumed by fdopendir inside __walk_overlay_dir */
+
+ if (found)
+ pr_debug("overlay walk: found ino %lx after %lu entries\n",
+ i_ino, visited);
+
+ return found;
+}
+
static char *alloc_openable(unsigned int s_dev, unsigned long i_ino, FhEntry *f_handle)
{
struct mount_info *m;
@@ -144,8 +302,31 @@ static char *alloc_openable(unsigned int s_dev, unsigned long i_ino, FhEntry *f_
fd = userns_call(open_by_handle, UNS_FDOUT, &handle, sizeof(handle), mntfd);
close(mntfd);
- if (fd < 0)
+ if (fd < 0) {
+ if (m->fstype->code == FSTYPE__OVERLAYFS) {
+ char *ovl_path;
+
+ pr_debug("\t\tHandle open failed on overlay,"
+ " trying dir walk for %lx\n",
+ i_ino);
+ ovl_path = find_path_on_overlay(m, s_dev,
+ i_ino);
+ if (ovl_path) {
+ if (root_ns_mask & CLONE_NEWNS) {
+ f_handle->has_mnt_id = true;
+ f_handle->mnt_id = m->mnt_id;
+ }
+ return ovl_path;
+ }
+ /*
+ * Mark as found so the caller gets
+ * ERR_NO_PATH_IN_MOUNT and falls
+ * through to irmap lookup.
+ */
+ suitable_mount_found = 1;
+ }
continue;
+ }
suitable_mount_found = 1;
if (read_fd_link(fd, buf, sizeof(buf)) < 0) {
From 53b8358a1f39f9f94844f2c147be472fa0b38da1 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber@redhat.com>
Date: Thu, 11 Jun 2026 15:41:19 +0000
Subject: [PATCH 2/3] test/others/overlayfs: add inotify C/R test
Add a test that exercises checkpoint/restore of a process with an
inotify watch on a file inside an overlayfs mount.
The test compiles inotify_test.c (a simple program that sets up an
inotify watch and blocks reading events), starts it watching a file
on an overlay mount, dumps and restores via criu, then verifies the
restored process is still alive.
Run with: make -C test/others/overlayfs run-inotify
Assisted-by: Claude Code (claude-opus-4-6):default
Signed-off-by: Adrian Reber <areber@redhat.com>
---
test/others/overlayfs/.gitignore | 1 +
test/others/overlayfs/Makefile | 17 ++++--
test/others/overlayfs/inotify_test.c | 69 ++++++++++++++++++++++++
test/others/overlayfs/run-inotify.sh | 78 ++++++++++++++++++++++++++++
4 files changed, 162 insertions(+), 3 deletions(-)
create mode 100644 test/others/overlayfs/.gitignore
create mode 100644 test/others/overlayfs/inotify_test.c
create mode 100755 test/others/overlayfs/run-inotify.sh
diff --git a/test/others/overlayfs/.gitignore b/test/others/overlayfs/.gitignore
new file mode 100644
index 0000000000..ec554b8965
--- /dev/null
+++ b/test/others/overlayfs/.gitignore
@@ -0,0 +1 @@
+inotify_test
diff --git a/test/others/overlayfs/Makefile b/test/others/overlayfs/Makefile
index 78c246bd88..1ebf139f60 100644
--- a/test/others/overlayfs/Makefile
+++ b/test/others/overlayfs/Makefile
@@ -1,6 +1,17 @@
-run:
+CC ?= cc
+
+inotify_test: inotify_test.c
+ $(CC) -Wall -o $@ $<
+
+run: run-inotify
./run.sh
+run-inotify: inotify_test
+ ./run-inotify.sh
+
clean:
- umount -f overlay_test/z
- rm -rf overlay_test output checkpoint
+ umount -f overlay_test/z 2>/dev/null || true
+ umount -f ovl_inotify/merged 2>/dev/null || true
+ rm -rf overlay_test ovl_inotify output checkpoint inotify_test
+
+.PHONY: run run-inotify clean
diff --git a/test/others/overlayfs/inotify_test.c b/test/others/overlayfs/inotify_test.c
new file mode 100644
index 0000000000..00f1b7f99b
--- /dev/null
+++ b/test/others/overlayfs/inotify_test.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/inotify.h>
+
+#define EVENT_SIZE (sizeof(struct inotify_event))
+#define BUF_LEN (1024 * (EVENT_SIZE + 16))
+
+int main(int argc, char **argv)
+{
+ char buf[BUF_LEN];
+ int fd, wd, len, i;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <path>\n", argv[0]);
+ return 1;
+ }
+
+ fd = inotify_init();
+ if (fd < 0) {
+ perror("inotify_init");
+ return 1;
+ }
+
+ wd = inotify_add_watch(fd, argv[1],
+ IN_MODIFY | IN_CREATE | IN_DELETE |
+ IN_OPEN | IN_CLOSE);
+ if (wd < 0) {
+ perror("inotify_add_watch");
+ close(fd);
+ return 1;
+ }
+
+ printf("Watching %s for events...\n", argv[1]);
+
+ while (1) {
+ len = read(fd, buf, BUF_LEN);
+ if (len < 0) {
+ perror("read");
+ break;
+ }
+
+ i = 0;
+ while (i < len) {
+ struct inotify_event *event;
+
+ event = (struct inotify_event *)&buf[i];
+
+ if (event->mask & IN_CREATE)
+ printf("CREATE: %s\n", event->name);
+ if (event->mask & IN_DELETE)
+ printf("DELETE: %s\n", event->name);
+ if (event->mask & IN_MODIFY)
+ printf("MODIFY: %s\n", event->name);
+ if (event->mask & IN_OPEN)
+ printf("OPEN: %s\n", event->name);
+ if (event->mask & IN_CLOSE)
+ printf("CLOSE: %s\n", event->name);
+
+ i += EVENT_SIZE + event->len;
+ }
+ }
+
+ inotify_rm_watch(fd, wd);
+ close(fd);
+
+ return 0;
+}
diff --git a/test/others/overlayfs/run-inotify.sh b/test/others/overlayfs/run-inotify.sh
new file mode 100755
index 0000000000..8711797221
--- /dev/null
+++ b/test/others/overlayfs/run-inotify.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+set -eu
+
+SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
+CRIU="${SCRIPT_DIR}/../../../criu/criu"
+ORIG_WD=$(pwd)
+PROC_PID=""
+
+cleanup() {
+ if [ -n "${PROC_PID}" ]; then
+ kill "${PROC_PID}" > /dev/null 2>&1 || true
+ wait "${PROC_PID}" 2>/dev/null || true
+ fi
+ cd "${ORIG_WD}"
+ umount ovl_inotify/merged 2>/dev/null || true
+ rm -rf ovl_inotify
+}
+
+trap cleanup EXIT
+
+setup() {
+ mkdir -p ovl_inotify
+ cd ovl_inotify
+ mkdir -p lower upper work merged checkpoint
+
+ cp "${SCRIPT_DIR}/inotify_test" .
+ touch lower/testfile
+ mount -t overlay overlay \
+ -o lowerdir=lower,upperdir=upper,workdir=work merged
+
+ setsid bash -c 'echo $$ > inotify.pid; exec ./inotify_test "$@"' \
+ -- merged/testfile < /dev/null &> output &
+ sleep 1
+ PROC_PID=$(cat inotify.pid)
+ echo "PROC_PID=$PROC_PID"
+}
+
+check_criu() {
+ echo "Dumping $PROC_PID..."
+ if ! $CRIU dump -D checkpoint -t "${PROC_PID}" --shell-job -v4; then
+ echo "ERROR! dump failed"
+ return 1
+ fi
+
+ echo "Restoring..."
+ if ! $CRIU restore -d -D checkpoint --shell-job -v4; then
+ echo "ERROR! restore failed"
+ return 1
+ fi
+
+ sleep 1
+
+ # Trigger an inotify event on the restored process
+ touch merged/testfile
+ sleep 1
+
+ # The restored process should still be alive
+ if ! kill -0 "${PROC_PID}" 2>/dev/null; then
+ echo "ERROR! restored process is not running"
+ return 1
+ fi
+
+ return 0
+}
+
+main() {
+ setup
+
+ if ! check_criu; then
+ exit 1
+ fi
+
+ echo "OverlayFS inotify C/R successful."
+ exit 0
+}
+
+main
From 082ca25d2280a632e0c19540a52d54460a23cff4 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber@redhat.com>
Date: Thu, 11 Jun 2026 15:50:54 +0000
Subject: [PATCH 3/3] zdtm: add inotify_overlayfs test
Add a ZDTM test that verifies inotify watches on files inside an
overlayfs mount survive checkpoint/restore.
The test uses the external mount pattern (like mnt_ext_auto): in
the ZDTM_NEWNS=1 phase it creates an overlay mount before
unshare(CLONE_NEWNS), so CRIU treats it as an external mount and
does not attempt to reconstruct the overlay on restore. After
restore the test opens the watched file and reads back the inotify
event to confirm the watch is intact.
This is needed because the test/others/overlayfs test only checks
that the process survives C/R. This ZDTM test validates that the
inotify watch itself is properly dumped and restored by exercising
the overlay directory walk fallback added in fsnotify.c.
The test is restricted to the 'ns' flavor because the overlay
setup requires the ZDTM_NEWNS=1 lifecycle and root privileges
for mounting overlayfs.
Assisted-by: Claude Code (claude-opus-4-6):default
Signed-off-by: Adrian Reber <areber@redhat.com>
---
test/zdtm/static/Makefile | 1 +
test/zdtm/static/inotify_overlayfs.c | 213 ++++++++++++++++++++++++
test/zdtm/static/inotify_overlayfs.desc | 2 +
test/zdtm/static/inotify_overlayfs.hook | 19 +++
4 files changed, 235 insertions(+)
create mode 100644 test/zdtm/static/inotify_overlayfs.c
create mode 100644 test/zdtm/static/inotify_overlayfs.desc
create mode 100755 test/zdtm/static/inotify_overlayfs.hook
diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 0e2580ed6e..d53eec2e2d 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -481,6 +481,7 @@ TST_DIR = \
symlink \
symlink01 \
unbindable \
+ inotify_overlayfs \
TST_DIR_FILE = \
chroot \
diff --git a/test/zdtm/static/inotify_overlayfs.c b/test/zdtm/static/inotify_overlayfs.c
new file mode 100644
index 0000000000..5044037a9e
--- /dev/null
+++ b/test/zdtm/static/inotify_overlayfs.c
@@ -0,0 +1,213 @@
+#include <sched.h>
+#include <unistd.h>
+#include <limits.h>
+#include <ftw.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/inotify.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc = "Check inotify C/R on overlayfs";
+const char *test_author = "CRIU contributors";
+
+char *dirname = "inotify_overlayfs.test";
+TEST_OPTION(dirname, string, "directory name", 1);
+
+#define BUFF_SIZE ((sizeof(struct inotify_event) + PATH_MAX))
+#define TEST_FNAME "testfile"
+
+#define OVL_DIR_SUFFIX "zdtm_inotify_ovl.XXXXXX"
+
+static int rm_entry(const char *path, const struct stat *st,
+ int flag, struct FTW *ftw)
+{
+ return remove(path);
+}
+
+/*
+ * Clean up overlay backing dirs matching the zdtm_inotify_ovl prefix
+ * in the given directory. Called at setup to remove leftovers from
+ * previous runs. Post-test cleanup is handled by
+ * inotify_overlayfs.hook (--clean).
+ */
+static void cleanup_stale_ovl_dirs(const char *parent)
+{
+ DIR *d;
+ struct dirent *de;
+ char path[PATH_MAX];
+
+ d = opendir(parent);
+ if (!d)
+ return;
+
+ while ((de = readdir(d)) != NULL) {
+ if (strncmp(de->d_name, "zdtm_inotify_ovl.",
+ strlen("zdtm_inotify_ovl.")) != 0)
+ continue;
+ snprintf(path, sizeof(path), "%s/%s", parent, de->d_name);
+ nftw(path, rm_entry, 16, FTW_DEPTH | FTW_PHYS);
+ }
+ closedir(d);
+}
+
+int main(int argc, char *argv[])
+{
+ char merged[PATH_MAX], watch_path[PATH_MAX];
+ char buf[BUFF_SIZE];
+ int inotify_fd, wd, fd, dir_fd;
+ char *zdtm_newns = getenv("ZDTM_NEWNS");
+ cleanup_free char *cwd = NULL;
+
+ cwd = get_current_dir_name();
+ snprintf(merged, sizeof(merged), "%s/%s", cwd, dirname);
+
+ if (zdtm_newns && !strcmp(zdtm_newns, "1")) {
+ char ovl_dir[PATH_MAX - 2];
+ char ovl_lower[PATH_MAX], ovl_upper[PATH_MAX];
+ char ovl_work[PATH_MAX];
+ char ovl_mnt[] = "/tmp/zdtm_ino_mnt.XXXXXX";
+ char opts[3 * PATH_MAX + 32];
+
+ /*
+ * Phase 1: running before namespace creation.
+ *
+ * Overlay backing dirs (lower/upper/work) are placed
+ * in cwd so they live on a real filesystem — tmpfs
+ * does not support overlayfs upperdir on all kernels.
+ *
+ * The overlay is mounted at a temporary directory
+ * under /tmp, which is outside ZDTM_ROOT and will
+ * not be visible after pivot_root. After unshare
+ * we bind-mount it into the test directory; the bind
+ * creates a shared/master relationship that
+ * --external mnt[]:s can detect.
+ */
+ cleanup_stale_ovl_dirs(cwd);
+
+ snprintf(ovl_dir, sizeof(ovl_dir), "%s/" OVL_DIR_SUFFIX, cwd);
+ if (!mkdtemp(ovl_dir)) {
+ pr_perror("Can't create overlay tmpdir");
+ return 1;
+ }
+
+ snprintf(ovl_lower, sizeof(ovl_lower), "%s/l", ovl_dir);
+ snprintf(ovl_upper, sizeof(ovl_upper), "%s/u", ovl_dir);
+ snprintf(ovl_work, sizeof(ovl_work), "%s/w", ovl_dir);
+
+ if (mkdir(ovl_lower, 0700) < 0) {
+ pr_perror("Can't mkdir %s", ovl_lower);
+ return 1;
+ }
+ if (mkdir(ovl_upper, 0700) < 0) {
+ pr_perror("Can't mkdir %s", ovl_upper);
+ return 1;
+ }
+ if (mkdir(ovl_work, 0700) < 0) {
+ pr_perror("Can't mkdir %s", ovl_work);
+ return 1;
+ }
+
+ /* Create a test file in the lower layer */
+ dir_fd = openat(AT_FDCWD, ovl_lower, O_RDONLY | O_DIRECTORY);
+ if (dir_fd < 0) {
+ pr_perror("Can't open lower dir %s", ovl_lower);
+ return 1;
+ }
+ fd = openat(dir_fd, TEST_FNAME, O_CREAT | O_WRONLY, 0644);
+ close(dir_fd);
+ if (fd < 0) {
+ pr_perror("Can't create test file in lower");
+ return 1;
+ }
+ close(fd);
+
+ /*
+ * Mount overlay at a path outside ZDTM_ROOT so it
+ * does not appear in mountinfo after pivot_root.
+ */
+ if (!mkdtemp(ovl_mnt)) {
+ pr_perror("Can't create overlay mount dir");
+ return 1;
+ }
+ snprintf(opts, sizeof(opts),
+ "lowerdir=%s,upperdir=%s,workdir=%s",
+ ovl_lower, ovl_upper, ovl_work);
+
+ if (mount("overlay", ovl_mnt, "overlay", 0, opts) < 0) {
+ pr_perror("Can't mount overlayfs at %s", ovl_mnt);
+ return 1;
+ }
+
+ if (unshare(CLONE_NEWNS)) {
+ pr_perror("unshare");
+ return 1;
+ }
+
+ /* Bind-mount into test directory inside new mntns */
+ if (mkdir(merged, 0700) < 0) {
+ pr_perror("Can't mkdir %s", merged);
+ return 1;
+ }
+ if (mount(ovl_mnt, merged, NULL, MS_BIND, NULL) < 0) {
+ pr_perror("Can't bind-mount overlay to %s", merged);
+ return 1;
+ }
+ }
+
+ /*
+ * test_init handles ZDTM_NEWNS internally:
+ * "1" -> ns_create() re-execs with "2" (never returns)
+ * "2" -> ns_init() forks, child continues
+ * unset -> normal execution
+ */
+ test_init(argc, argv);
+
+ snprintf(watch_path, sizeof(watch_path),
+ "%s/" TEST_FNAME, dirname);
+
+ inotify_fd = inotify_init1(IN_NONBLOCK);
+ if (inotify_fd < 0) {
+ pr_perror("inotify_init1 failed");
+ return 1;
+ }
+
+ wd = inotify_add_watch(inotify_fd, watch_path, IN_OPEN);
+ if (wd < 0) {
+ pr_perror("inotify_add_watch failed for %s", watch_path);
+ close(inotify_fd);
+ return 1;
+ }
+
+ test_daemon();
+ test_waitsig();
+
+ /* After restore, trigger an inotify event */
+ fd = open(watch_path, O_RDONLY);
+ if (fd < 0) {
+ fail("Can't open %s after restore", watch_path);
+ close(inotify_fd);
+ return 1;
+ }
+ close(fd);
+
+ /* Check that we got the event */
+ memset(buf, 0, sizeof(buf));
+ if (read(inotify_fd, buf, sizeof(buf)) <= 0) {
+ fail("No inotify events after restore");
+ close(inotify_fd);
+ return 1;
+ }
+
+ close(inotify_fd);
+ pass();
+ return 0;
+}
diff --git a/test/zdtm/static/inotify_overlayfs.desc b/test/zdtm/static/inotify_overlayfs.desc
new file mode 100644
index 0000000000..f1c3a17143
--- /dev/null
+++ b/test/zdtm/static/inotify_overlayfs.desc
@@ -0,0 +1,2 @@
+{'flags': 'suid', 'flavor': 'ns', 'feature': 'mnt_id',
+ 'opts': '--external mnt[]:s'}
diff --git a/test/zdtm/static/inotify_overlayfs.hook b/test/zdtm/static/inotify_overlayfs.hook
new file mode 100755
index 0000000000..06d128755e
--- /dev/null
+++ b/test/zdtm/static/inotify_overlayfs.hook
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+[ "$1" == "--clean" ] || exit 0
+
+# Remove overlay backing dirs left by the ZDTM_NEWNS=1 phase.
+# The test creates them in its working directory, which is the
+# same directory as this hook script.
+test_dir=$(dirname "$(readlink -f "$0")")
+for dir in "$test_dir"/zdtm_inotify_ovl.* ; do
+ [ -d "$dir" ] && rm -rf "$dir"
+done
+
+# Remove overlay mount point dirs from /tmp.
+for dir in /tmp/zdtm_ino_mnt.* ; do
+ umount "$dir" 2>/dev/null || true
+ [ -d "$dir" ] && rmdir "$dir"
+done
+
+exit 0

View File

@ -13,7 +13,7 @@
Name: criu
Version: 4.2
Release: 6%{?dist}.alma.1
Release: 7%{?dist}.alma.1
Summary: Tool for Checkpoint/Restore in User-space
License: GPL-2.0-only AND LGPL-2.1-only AND MIT
URL: http://criu.org/
@ -34,6 +34,12 @@ Patch2: https://patch-diff.githubusercontent.com/raw/checkpoint-restore/criu/pul
# RHEL-189245 RHEL-189246 RHEL-189248
Patch3: https://patch-diff.githubusercontent.com/raw/checkpoint-restore/criu/pull/3025.patch
# RHEL-193276
Patch4: https://patch-diff.githubusercontent.com/raw/checkpoint-restore/criu/pull/2876.patch
Patch5: https://patch-diff.githubusercontent.com/raw/checkpoint-restore/criu/pull/2880.patch
Patch6: https://patch-diff.githubusercontent.com/raw/checkpoint-restore/criu/pull/2881.patch
Patch7: https://patch-diff.githubusercontent.com/raw/checkpoint-restore/criu/pull/3043.patch
# Add protobuf-c as a dependency.
# We use this patch because the protobuf-c package name
# in RPM and DEB is different.
@ -118,6 +124,10 @@ This script can help to workaround the so called "PID mismatch" problem.
%patch -P 1 -p1
%patch -P 2 -p1
%patch -P 3 -p1
%patch -P 4 -p1
%patch -P 5 -p1
%patch -P 6 -p1
%patch -P 7 -p1
%patch -P 99 -p1
%build
@ -193,9 +203,13 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/libcriu.a
%doc %{_mandir}/man1/criu-ns.1*
%changelog
* Fri Jul 03 2026 Andrew Lukoshko <alukoshko@almalinux.org> - 4.2-6.alma.1
* Fri Jul 17 2026 Andrew Lukoshko <alukoshko@almalinux.org> - 4.2-7.alma.1
- Add riscv64 to ExclusiveArch
* Wed Jul 08 2026 Adrian Reber <areber@redhat.com> - 4.2-7
- Apply patch to fix RHEL-193276
- Resolves: RHEL-193276
* Thu Jul 02 2026 Adrian Reber <areber@redhat.com> - 4.2-6
- Apply patch to fix RHEL-189245 RHEL-189246 RHEL-189248
- Resolves: RHEL-189245