<div dir="ltr">Replying to Kirill&#39;s comment here, since I didn&#39;t get it in my inbox.<div><br></div><div><div>&gt; This chooses service fd base for main criu process, usernsd process (possibly there are other helpers).</div><div>&gt; I&#39;m not sure, these guys never create many temporary fds before they install a service fd:</div><div>&gt;                                                                                                                                                                                                                                                                                                                              </div><div>&gt; criu main task:</div><div>&gt;    cached_fd1 = open()</div><div>&gt;    cached_fd2 = open()</div><div>&gt;    ...</div><div>&gt;    cached_fdn = open()</div><div>&gt; </div><div>&gt;    install_service_fd() -&gt; rewrites cached_fdn.</div><div>&gt; </div><div>&gt; It&#39;s need to review criu main task &amp; friends code and check there are no such the situations.</div><div>&gt; Also, if we are going to do this way, we will have to implement some things to detect such</div><div>&gt; the problems in the future code.</div><div>&gt; </div><div>&gt; Really restored tasks (init and its children) do not create many temporary fd by design,</div><div>&gt; and we check their fd leak by tests (in zdtm.py), so there is no such the problem.</div></div><div><br></div><div>Thanks, I wasn&#39;t aware of that. So the main CRIU process is effectively relying on a high</div><div>service_fd_base to avoid collisions with temporary fds, right?<br></div><div><br></div><div>In that case, we could still try to select a base by using a large enough pad.</div><div>In install_service_fd, we could then do:</div><div>  BUG_ON(close(new_fd) == 0);</div><div>(such a safety check may be generally useful, regardless of my changes).</div><div><br></div><div>What do you think? Even with RLIMIT_NOFILE of few billions, the fork delay is just few hundred ms</div><div>- so if it turns out that my change gets very complex, it might not be worth it.</div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Aug 3, 2018 at 3:12 AM Andrei Vagin &lt;<a href="mailto:avagin@virtuozzo.com" target="_blank">avagin@virtuozzo.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Kirill, could you review this patch?<br>
<br>
On Thu, Aug 02, 2018 at 02:53:10PM +0200, Radoslaw Burny wrote:<br>
&gt; choose_service_fd_base selects lowest possible numbers for service fds<br>
&gt; to keep fd table of the criu process small, making fork() faster.<br>
&gt; However, this method was only used in child processes, not the root CRIU<br>
&gt; process - thus forks from root were still slow. This fixes the issue.<br>
&gt; <br>
&gt; Sorry for slightly unreadable patch - the code move was necessary due to<br>
&gt; changes in the inter-function dependencies. The key part of the diff is<br>
&gt; this line:<br>
&gt;   service_fd_base = choose_service_fd_base(NULL);<br>
&gt; <br>
&gt; Signed-off-by: Radoslaw Burny &lt;<a href="mailto:rburny@google.com" target="_blank">rburny@google.com</a>&gt;<br>
&gt; ---<br>
&gt;  criu/util.c | 66 ++++++++++++++++++++++++++---------------------------<br>
&gt;  1 file changed, 33 insertions(+), 33 deletions(-)<br>
&gt; <br>
&gt; diff --git a/criu/util.c b/criu/util.c<br>
&gt; index ab4d89aa..114756a6 100644<br>
&gt; --- a/criu/util.c<br>
&gt; +++ b/criu/util.c<br>
&gt; @@ -441,27 +441,6 @@ static int service_fd_base;<br>
&gt;  /* Id of current process in shared fdt */<br>
&gt;  static int service_fd_id = 0;<br>
&gt;  <br>
&gt; -int init_service_fd(void)<br>
&gt; -{<br>
&gt; -     struct rlimit64 rlimit;<br>
&gt; -<br>
&gt; -     /*<br>
&gt; -      * Service FDs are those that most likely won&#39;t<br>
&gt; -      * conflict with any &#39;real-life&#39; ones<br>
&gt; -      */<br>
&gt; -<br>
&gt; -     if (syscall(__NR_prlimit64, getpid(), RLIMIT_NOFILE, NULL, &amp;rlimit)) {<br>
&gt; -             pr_perror(&quot;Can&#39;t get rlimit&quot;);<br>
&gt; -             return -1;<br>
&gt; -     }<br>
&gt; -<br>
&gt; -     service_fd_rlim_cur = (int)rlimit.rlim_cur;<br>
&gt; -     service_fd_base = service_fd_rlim_cur;<br>
&gt; -     BUG_ON(service_fd_base &lt; SERVICE_FD_MAX);<br>
&gt; -<br>
&gt; -     return 0;<br>
&gt; -}<br>
&gt; -<br>
&gt;  static int __get_service_fd(enum sfd_type type, int service_fd_id)<br>
&gt;  {<br>
&gt;       return service_fd_base - type - SERVICE_FD_MAX * service_fd_id;<br>
&gt; @@ -560,20 +539,20 @@ static void move_service_fd(struct pstree_item *me, int type, int new_id, int ne<br>
&gt;  <br>
&gt;  static int choose_service_fd_base(struct pstree_item *me)<br>
&gt;  {<br>
&gt; -     int nr, real_nr, fdt_nr = 1, id = rsti(me)-&gt;service_fd_id;<br>
&gt; +     int nr = -1, real_nr, fdt_nr = 1, id = rsti(me)-&gt;service_fd_id;<br>
&gt;  <br>
&gt; -     if (rsti(me)-&gt;fdt) {<br>
&gt; -             /* The base is set by owner of fdt (id 0) */<br>
&gt; -             if (id != 0)<br>
&gt; -                     return service_fd_base;<br>
&gt; -             fdt_nr = rsti(me)-&gt;fdt-&gt;nr;<br>
&gt; +     if (me != NULL) {<br>
&gt; +             if (rsti(me)-&gt;fdt) {<br>
&gt; +                     /* The base is set by owner of fdt (id 0) */<br>
&gt; +                     if (id != 0)<br>
&gt; +                             return service_fd_base;<br>
&gt; +                     fdt_nr = rsti(me)-&gt;fdt-&gt;nr;<br>
&gt; +             }<br>
&gt; +             /* Now find process&#39;s max used fd number */<br>
&gt; +             if (!list_empty(&amp;rsti(me)-&gt;fds))<br>
&gt; +                     nr = list_entry(rsti(me)-&gt;fds.prev,<br>
&gt; +                                     struct fdinfo_list_entry, ps_list)-&gt;fe-&gt;fd;<br>
&gt;       }<br>
&gt; -     /* Now find process&#39;s max used fd number */<br>
&gt; -     if (!list_empty(&amp;rsti(me)-&gt;fds))<br>
&gt; -             nr = list_entry(rsti(me)-&gt;fds.prev,<br>
&gt; -                             struct fdinfo_list_entry, ps_list)-&gt;fe-&gt;fd;<br>
&gt; -     else<br>
&gt; -             nr = -1;<br>
&gt;  <br>
&gt;       nr = max(nr, inh_fd_max);<br>
&gt;       /*<br>
&gt; @@ -607,6 +586,27 @@ static int choose_service_fd_base(struct pstree_item *me)<br>
&gt;       return nr;<br>
&gt;  }<br>
&gt;  <br>
&gt; +int init_service_fd(void)<br>
&gt; +{<br>
&gt; +     struct rlimit64 rlimit;<br>
&gt; +<br>
&gt; +     /*<br>
&gt; +      * Service FDs are those that most likely won&#39;t<br>
&gt; +      * conflict with any &#39;real-life&#39; ones<br>
&gt; +      */<br>
&gt; +<br>
&gt; +     if (syscall(__NR_prlimit64, getpid(), RLIMIT_NOFILE, NULL, &amp;rlimit)) {<br>
&gt; +             pr_perror(&quot;Can&#39;t get rlimit&quot;);<br>
&gt; +             return -1;<br>
&gt; +     }<br>
&gt; +<br>
&gt; +     service_fd_rlim_cur = (int)rlimit.rlim_cur;<br>
&gt; +     service_fd_base = choose_service_fd_base(NULL);<br>
&gt; +     BUG_ON(service_fd_base &lt; SERVICE_FD_MAX);<br>
&gt; +<br>
&gt; +     return 0;<br>
&gt; +}<br>
&gt; +<br>
&gt;  int clone_service_fd(struct pstree_item *me)<br>
&gt;  {<br>
&gt;       int id, new_base, i, ret = -1;<br>
&gt; -- <br>
&gt; 2.18.0.597.ga71716f1ad-goog<br>
&gt; <br>
&gt; _______________________________________________<br>
&gt; CRIU mailing list<br>
&gt; <a href="mailto:CRIU@openvz.org" target="_blank">CRIU@openvz.org</a><br>
&gt; <a href="https://lists.openvz.org/mailman/listinfo/criu" rel="noreferrer" target="_blank">https://lists.openvz.org/mailman/listinfo/criu</a><br>
</blockquote></div>