Changes

Jump to navigation Jump to search
3,332 bytes added ,  12:11, 13 September 2018
m
Line 3: Line 3:  
== Files, descriptors and inodes in Linux ==
 
== Files, descriptors and inodes in Linux ==
   −
When a task opens a file Linux kernel constructs a chain of 3 (well, 3.5) object to serve this.
+
When a task opens a file Linux kernel constructs a chain of 3 objects to serve this.
    
; Inode
 
; Inode
Line 19: Line 19:  
So after <code>open()</code> (or some other, see below) system call there will be this chain in the memory
 
So after <code>open()</code> (or some other, see below) system call there will be this chain in the memory
   −
<pre>
+
[[File:Dumping_files-001.svg|thumb|upright=2|center]]
+------+
+
 
+ Task +-----+
+
The File object can be referenced by more than on FDT, e.g. when a task calls <code>fork()</code> the child one gets new FDT, but it references the same Files as the parent does, i.e. Files become shared objects.
+------+    |
+
 
            v
+
[[File:Dumping_files-002.svg|thumb|upright=3|center]]
          +------------------------------+
+
 
          | File Descriptors Table (FDT) |
+
The Inode object is also interesting. First of all, remember that in Linux file descriptors can be obtained not only by the <code>open()</code> system call, but also by <code>pipe()</code> and <code>socket()</code> and a bunch of Linux-specific <code>epoll_create</code>, <code>signalfd</code> and others. So when serving ''this'' Linux would anyway create the mentioned above chain of File-Dentry-Inode objects, but the Inode one will be different for different calls. And CRIU knows this all and acts respectively :)
          +------------------------------+
+
 
          |  |  | 2 |      ...     |  |
+
== How info about opened files is stored in CRIU ==
          +------------------------------+
+
 
                    |
+
Having said that CRIU introduces several images to keep info about what files are opened by task.
                    |
+
 
                    |      +------+    +--------+    +-------+
+
=== File descriptors ===
                    +----->| File |--->| Dentry |--->| Inode |
+
 
                            +------+    +--------+    +-------+
+
First image is the <code>fdinfo-$id.img</code> one. This image contains info about FDT of a process. The entries have two important fields -- <code>fd</code> and <code>id</code>.
</pre>
+
 
 +
The ''fd'' is the descriptor number under which the created on restore File should be put. The ''id'' is the identifier to the File-Inode object pair in other images.
 +
 
 +
=== Files themselves ===
 +
 
 +
For the sake of simplicity, CRIU doesn't introduce separate states for Files, Dentries and Inodes, leaving it to the kernel. Instead, each triplet is treated as one object and for every Inode type (file, pipe, socket, etc.) separate image is introduced. Thus CRIU has
 +
 
 +
* reg-files.img for regular files, that are created by open() call
 +
* unixsk.img for unix sockets
 +
* pipes.img for pipes
 +
* inetsk for IP sockets (both TCP and UDP)
 +
* signalfd.img for signal fd
 +
* etc.
 +
 
 +
A full list of image files generated by CRIU is available in [[Images]].
 +
 
 +
In each of these image files is preserved appropriate information about File and Inode of respective file. Dentry information is effectively stored for regular files only -- the file's ''path''.
 +
 
 +
== How CRIU gets the information to dump ==
 +
 
 +
So on dump CRIU needs to find out several things.
 +
 
 +
# The FD numbers owned by tasks
 +
# How File-s are shared between tasks' FDTs
 +
# What Inode types are there
 +
# State of File and Inode objects
 +
 
 +
=== FD numbers ===
 +
 
 +
This is simple. Reading the ''/proc/$pid/fd'' or ''/proc/$pid/fdinfo'' directory just shows the required numbers.
 +
 
 +
=== Files sharing ===
 +
 
 +
In order to find out whether two Files sitting beyond two FDs of two tasks are the same CRIU [[Kcmp trees|uses]] the <code>kcmp</code> system call.
 +
 
 +
=== Determining Inode type ===
 +
 
 +
The inode type in most of the cases can be found out by <code>stat()</code>-ing the descriptor. To do this CRIU asks the [[parasite code]] to send back the files via unix socket's <code>SCM_RIGHTS</code> message. After this, having the same Files at hands CRIU <code>fstat</code>s each and checks the <code>st_mode</code> field.
 +
 
 +
For some stupid files (signalfd, inotify, etc.) the mode field is zero and CRIU reads the ''/proc/$pid/fd/$fd/'' link. For those the link target uniquely defines the Inode type.
 +
 
 +
=== State of File and Inode ===
 +
 
 +
From File CRIU needs only two things -- the mode and the position. Both can be read from ''/proc/$pid/fdinfo/$fd/'' and the latter one can be requested via <code>lseek</code> call.
 +
 
 +
Getting the Inode state is specific to Inode. CRIU uses the following sources of information:
 +
 
 +
# Data from ''/proc/$pid/fdinfo/$fd/''
 +
# Link target of ''/proc/$pid/fd/$fd/'' link
 +
# Inode-specific ioctl()-s
 +
# Fetch data directly from FD with recv + MSG_PEEK for socket queues and tee for pipes/fifos
 +
# Info from sock_diag modules to get info about sockets
 +
 
 +
[[Category:Under the hood]]
 +
[[Category:Files]]
 +
[[Category:Editor help needed]]
277

edits

Navigation menu