Difference between revisions of "Restorer v2"

From CRIU
Jump to navigation Jump to search
m (Grammar fix.)
 
(9 intermediate revisions by one other user not shown)
Line 1: Line 1:
The current way of restoring from images is quite straightforward -- we just fork the necessary amount of tasks, then each of them starts "dressing" itself based on the data from image files. Sometimes shared resources appear, e.g. files inherited or sessions inherited on fork, or CLONE_XXX objects. With these we write code, that handles only this type of resources -- files a sent to co-owners via unix sockets, CLONE_XXX stuff is pre-created on fork stage. Sometimes more interesting dependencies arise, for example -- [[invisible files]]. These are also special-cared.
+
The current way of restoring from images is quite straightforward -- we just fork the necessary amount of tasks, then each of them starts "dressing" itself based on the data from image files. Sometimes shared resources appear, e.g. files inherited or sessions inherited on fork, or CLONE_XXX objects. With these we write code, that handles only this type of resources -- files are sent to co-owners via unix sockets, CLONE_XXX stuff is pre-created on fork stage. Sometimes more interesting dependencies arise, for example -- [[invisible files]]. These are also special-cared.
  
 
All this is not nice. We believe, that the restoring process can (and should) look better. Like this.
 
All this is not nice. We believe, that the restoring process can (and should) look better. Like this.
Line 13: Line 13:
 
Another way of describing the thing is -- a string of sequences like <code>{o,t,[l]*}</code> where <code>o</code> is an ID of an object, <code>t</code> is its type, <code>[l]*</code> is an array of links to another objects. The generation rules can look like
 
Another way of describing the thing is -- a string of sequences like <code>{o,t,[l]*}</code> where <code>o</code> is an ID of an object, <code>t</code> is its type, <code>[l]*</code> is an array of links to another objects. The generation rules can look like
  
* fork() - <code>({(*),task,[(*)]}) -> \1,{$new,task,([parent=\2,\3])}</code> which means that any task can create a copy of itself having it as parent (link) and the rest of objects shared
+
* fork() <code>({(*),task,[(*)]}) -> \1,{$new,task,([parent=\2,\3])}</code> which means that any task can create a copy of itself having it as parent (link) and the rest of objects shared
* open() - <code>{(*),task,(*)} -> {-1,task,[file=$new]},{$new,file,[]}</code> which means that any task can create a new object of type file linked to it
+
* open() <code>{(*),task,(*)} -> {\1,task,[file=$new,\2]},{$new,file,[]}</code> which means that any task can create a new object of type file linked to it
  
 
The restoring process then is: given a final graph or string and the set of generating rules find out what sequence of the latter can produce the former.
 
The restoring process then is: given a final graph or string and the set of generating rules find out what sequence of the latter can produce the former.
  
 
This task (in its 2nd description) reminds the task of solving the context-sensitive grammar.
 
This task (in its 2nd description) reminds the task of solving the context-sensitive grammar.
 +
 +
== Examples ==
 +
=== Process tree, sessions and groups ===
 +
 +
In case of three IDs only we can define a task as a non-terminal looking like <code>{PGS[Ki]}</code> where <code>P</code> is task PID, <code>G</code> is task PGID, <code>S</code> is task Session ID and <code>[Ki]</code> is the list of children.
 +
 +
Initial tree would look like
 +
 +
<pre>
 +
{111}
 +
</pre>
 +
 +
and the rules would look like below.
 +
 +
<pre>
 +
FORK:      {T(..)(.*)}                  -> {T\1N\2}|{N\1}    // T forks N
 +
EXIT:      {I(..)(.*)}(.*){X(..)(.*)}  -> {I\1\2\5}\3        // X exits and all its kids are reparented to I (init)
 +
SETSID:    {S(.)(.)(.*)}                -> {S\1S\3}          // S becomes a new session leader
 +
SETPGID(0): {P(.)(.)(.*)}                -> {PP\2\3}          // P becomes a new group leader
 +
SETPGID(G): {GGS(.*)}(.*){P(.)S(.*)}    -> {GGS\1}\2{PGS\4}
 +
            {P(.)S(.*)}(.*){GGS(.*)}    -> {PGS\2}\3{GGS\4}  // P joins group of alive G
 +
</pre>
 +
 
[[Category: Plans]]
 
[[Category: Plans]]
 +
[[Category: Thinkers]]

Latest revision as of 16:38, 23 July 2020

The current way of restoring from images is quite straightforward -- we just fork the necessary amount of tasks, then each of them starts "dressing" itself based on the data from image files. Sometimes shared resources appear, e.g. files inherited or sessions inherited on fork, or CLONE_XXX objects. With these we write code, that handles only this type of resources -- files are sent to co-owners via unix sockets, CLONE_XXX stuff is pre-created on fork stage. Sometimes more interesting dependencies arise, for example -- invisible files. These are also special-cared.

All this is not nice. We believe, that the restoring process can (and should) look better. Like this.

Concept[edit]

The result that we want to achieve can be described as a graph of objects, each edge of it having a special "relationship" meaning. This graph should be generated using a set of pre-defined rules, e.g.

  • fork() -- an object type "task" may create a copy of itself, each "linked" node of this graph get "linked" to the new object
  • open() -- a new object type "file" appear in a graph "linked" to the "task" object doing open()

And so on.

Another way of describing the thing is -- a string of sequences like {o,t,[l]*} where o is an ID of an object, t is its type, [l]* is an array of links to another objects. The generation rules can look like

  • fork() — ({(*),task,[(*)]}) -> \1,{$new,task,([parent=\2,\3])} which means that any task can create a copy of itself having it as parent (link) and the rest of objects shared
  • open() — {(*),task,(*)} -> {\1,task,[file=$new,\2]},{$new,file,[]} which means that any task can create a new object of type file linked to it

The restoring process then is: given a final graph or string and the set of generating rules find out what sequence of the latter can produce the former.

This task (in its 2nd description) reminds the task of solving the context-sensitive grammar.

Examples[edit]

Process tree, sessions and groups[edit]

In case of three IDs only we can define a task as a non-terminal looking like {PGS[Ki]} where P is task PID, G is task PGID, S is task Session ID and [Ki] is the list of children.

Initial tree would look like

{111}

and the rules would look like below.

FORK:       {T(..)(.*)}                  -> {T\1N\2}|{N\1}     // T forks N
EXIT:       {I(..)(.*)}(.*){X(..)(.*)}   -> {I\1\2\5}\3        // X exits and all its kids are reparented to I (init)
SETSID:     {S(.)(.)(.*)}                -> {S\1S\3}           // S becomes a new session leader
SETPGID(0): {P(.)(.)(.*)}                -> {PP\2\3}           // P becomes a new group leader
SETPGID(G): {GGS(.*)}(.*){P(.)S(.*)}     -> {GGS\1}\2{PGS\4}
            {P(.)S(.*)}(.*){GGS(.*)}     -> {PGS\2}\3{GGS\4}   // P joins group of alive G