[CRIU] [PATCH 2/6] dump: rework freeze of threads
Andrey Vagin
avagin at openvz.org
Thu Dec 19 04:59:42 PST 2013
When we try to freeze threads, some of them can exit
and a few new ones can be born. Currently we unfreeze process free
int this case, so we have the same chance to failed in the next case.
I suggest to not unfreeze frozen threads, just try to update thread list
and freeze unfrozen threads.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
cr-dump.c | 103 +++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 55 insertions(+), 48 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index ab53e6e..eb2ca90 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -73,6 +73,8 @@
#include "asm/dump.h"
+#define NR_ATTEMPTS 5
+
static char loc_buf[PAGE_SIZE];
bool privately_dump_vma(struct vma_area *vma)
@@ -681,31 +683,6 @@ err:
return ret;
}
-static int get_threads(struct pstree_item *item)
-{
- return parse_threads(item->pid.real, &item->threads, &item->nr_threads);
-}
-
-static int check_threads(const struct pstree_item *item)
-{
- struct pid *t = NULL;
- int nr, ret;
-
- ret = parse_threads(item->pid.real, &t, &nr);
- if (ret)
- return ret;
-
- ret = ((nr == item->nr_threads) && !memcmp(t, item->threads, nr));
- xfree(t);
-
- if (!ret) {
- pr_info("Threads set has changed while suspending\n");
- return -1;
- }
-
- return 0;
-}
-
static int parse_children(pid_t pid, pid_t **_c, int *_n)
{
FILE *file;
@@ -806,25 +783,49 @@ static pid_t item_ppid(const struct pstree_item *item)
return item ? item->pid.real : -1;
}
-static int seize_threads(const struct pstree_item *item)
+static int seize_threads(struct pstree_item *item,
+ struct pid *threads, int nr_threads)
{
- int i = 0, ret;
+ int i = 0, ret, j, nr;
- if ((item->state == TASK_DEAD) && (item->nr_threads > 1)) {
+ if ((item->state == TASK_DEAD) && (nr_threads > 1)) {
pr_err("Zombies with threads are not supported\n");
goto err;
}
- for (i = 0; i < item->nr_threads; i++) {
- pid_t pid = item->threads[i].real;
+ /* The number of threads can't be less than allready frozen */
+ item->threads = xrealloc(item->threads, nr_threads * sizeof(struct pid));
+ if (item->threads == NULL)
+ return -1;
+
+ if (item->nr_threads == 0) {
+ item->threads[0].real = item->pid.real;
+ item->nr_threads = 1;
+ }
+
+ nr = 0;
+ for (i = 0; i < nr_threads; i++) {
+ pid_t pid = threads[i].real;
if (item->pid.real == pid)
continue;
+ for (j = 0; j < item->nr_threads; j++)
+ if (pid == item->threads[j].real)
+ break;
+
+ if (j != item->nr_threads)
+ continue;
+ nr++;
+
pr_info("\tSeizing %d's %d thread\n",
item->pid.real, pid);
ret = seize_task(pid, item_ppid(item), NULL, NULL);
if (ret < 0)
- goto err;
+ continue;
+
+ BUG_ON(item->nr_threads + 1 > nr_threads);
+ item->threads[item->nr_threads].real = pid;
+ item->nr_threads++;
if (ret == TASK_DEAD) {
pr_err("Zombie thread not supported\n");
@@ -837,28 +838,34 @@ static int seize_threads(const struct pstree_item *item)
}
}
- return 0;
-
+ return nr;
err:
- for (i--; i >= 0; i--) {
- if (item->pid.real == item->threads[i].real)
- continue;
-
- unseize_task(item->threads[i].real, TASK_ALIVE);
- }
-
return -1;
}
static int collect_threads(struct pstree_item *item)
{
- int ret;
+ int ret, attempts = NR_ATTEMPTS;
+ struct pid *t;
+ int nr;
- ret = get_threads(item);
- if (!ret)
- ret = seize_threads(item);
- if (!ret)
- ret = check_threads(item);
+ ret = 1;
+ while (ret > 0 && attempts) {
+ attempts--;
+
+ t = NULL;
+ nr = 0;
+
+ ret = parse_threads(item->pid.real, &t, &nr);
+ if (ret < 0)
+ break;
+
+ ret = seize_threads(item, t, nr);
+ xfree(t);
+ if (ret < 0)
+ break;
+
+ }
return ret;
}
@@ -895,7 +902,7 @@ static int collect_task(struct pstree_item *item)
err_close:
close_pid_proc();
- unseize_task(pid, item->state);
+ unseize_task_and_threads(item, item->state);
err:
return -1;
}
@@ -970,7 +977,7 @@ static int collect_pstree_ids(void)
static int collect_pstree(pid_t pid)
{
- int ret, attempts = 5;
+ int ret, attempts = NR_ATTEMPTS;
timing_start(TIME_FREEZING);
--
1.8.3.1
More information about the CRIU
mailing list