Changes

Jump to navigation Jump to search
use source highlighting; fixes and improvements in English
Line 1: Line 1: −
OK, let's imagine we have an information about a file we want to open.
+
Let's imagine we have an information about a file we want to open.
−
What should it contain? Apparently access mode and path
+
What should it contain? Apparently, access mode and path:
   −
<pre>
+
<source lang="C">
 
struct file {
 
struct file {
 
char *path;
 
char *path;
 
unsigned mode;
 
unsigned mode;
 
} *f;
 
} *f;
−
</pre>
+
</source>
    
and we'd like to have that path being opened by a process.  We would
 
and we'd like to have that path being opened by a process.  We would
 
do it like below:
 
do it like below:
   −
<pre>
+
<source lang="C">
 
int fd;
 
int fd;
    
fd = open(f->path, f->mode);
 
fd = open(f->path, f->mode);
−
</pre>
+
</source>
   −
right? Right, but it's not all. We all know, that not only regular
+
Right? Right, but it's not all of it. We all know, that not only regular
−
files might be opened via paths, but also such things as FIFO-s. And
+
files might be opened via paths, but also such things as FIFOs. And
−
plain open with the flags we want it to have may just hang. So we need
+
plain <code>open()</code> with the flags we want it to have may just hang. So we need
 
to change that code to look like this:
 
to change that code to look like this:
   −
<pre>
+
<source lang="C">
 
int fd, tfd = -1;
 
int fd, tfd = -1;
   Line 33: Line 33:  
if (tfd >= 0)
 
if (tfd >= 0)
 
close(tfd);
 
close(tfd);
−
</pre>
+
</source>
    
The tfd keeps FIFO read-write opened while we open it with any flags
 
The tfd keeps FIFO read-write opened while we open it with any flags
 
we want. Then we close it.
 
we want. Then we close it.
   −
Now this seems to be OK, but it's actually not. In Linux file can be
+
Now this seems to be OK, but it's actually not. In Linux, file can be
 
unlinked while being opened (these [[invisible files]] are treated carefully
 
unlinked while being opened (these [[invisible files]] are treated carefully
 
on dump). In that case what was formerly pointed by
 
on dump). In that case what was formerly pointed by
−
path may be kept in some temporary location. And we have to create a
+
path may be kept in some temporary location. We have to create a
−
temp name for it and unlink one afterwards. So we need to extend the
+
temporary name for it, and unlink it afterwards. So, we need to extend the
−
info about file
+
info about a file:
   −
<pre>
+
<source lang="C">
 
struct file {
 
struct file {
 
char *path;
 
char *path;
Line 51: Line 51:  
char *temp_path;
 
char *temp_path;
 
} *f;
 
} *f;
−
</pre>
+
</source>
   −
and the opening code to take care of that temorary location
+
and the opening code to take care of that temporary location
   −
<pre>
+
<source lang="C">
 
int fd, tfd = -1;
 
int fd, tfd = -1;
   Line 71: Line 71:  
if (f->temp_path)
 
if (f->temp_path)
 
unlink(f->path);
 
unlink(f->path);
−
</pre>
+
</source>
    
And we haven't seen all the code we need to manage what is pointed by
 
And we haven't seen all the code we need to manage what is pointed by
−
the temp_path, but let's proceed.
+
the <code>temp_path</code>, but let's proceed.
   −
We have forgotten, that opened and unl^w removed can also be a
+
We have forgotten, that opened and <s>unlinked</s> removed can also be a
−
directory. On directories link and unlink do not work and we have to
+
directory. For directories, link and unlink do not work, and we have to
−
slightly fix the code to at least try to make things work OK:
+
append the code to at least try to make things work OK:
   −
<pre>
+
<source lang="C">
 
int fd, tfd = -1;
 
int fd, tfd = -1;
   Line 104: Line 104:  
unlink(f->path);
 
unlink(f->path);
 
}
 
}
−
</pre>
+
</source>
   −
Done. But, we also should take care of hard links. If a file has such
+
Done. Oh wait, we also should take care of hard links! If a file has any,
−
and both were opened and removed, we cannot after opening just go
+
and both were opened and removed, we cannot just go
−
ahead and kill the temp_path -- it can be waiting for some other
+
ahead and kill the <code>temp_path</code> after opening, as
−
struct file to open one. A little bit more information should be added
+
it can be waiting for some other
−
to the struct file
+
<code>struct file</code> to open one. A little bit more information should be added
 +
to the <code>struct file</code>.
   −
<pre>
+
<source lang="C">
 
struct temp_file {
 
struct temp_file {
 
char *path;
 
char *path;
Line 123: Line 124:  
struct temp_file *temp;
 
struct temp_file *temp;
 
} *f;
 
} *f;
−
</pre>
+
</source>
    
and to the code that opens one now looks like this:
 
and to the code that opens one now looks like this:
   −
<pre>
+
<source lang="C">
 
int fd, tfd = -1;
 
int fd, tfd = -1;
   Line 153: Line 154:  
}
 
}
 
}
 
}
−
</pre>
+
</source>
    
By the way, we've left behind the scenes all the code required to make
 
By the way, we've left behind the scenes all the code required to make
−
the temp_file data be shared between processes that need one and to
+
the <code>temp_file</code> data be shared between processes that need one and to
−
make the decrement of f->temp->users be smp-safe.
+
make the decrementing of <code>f->temp->users</code> be SMP-safe.
    
Also note, that we don't handle the case when the file/directory is
 
Also note, that we don't handle the case when the file/directory is
 
removed and some other file/directory is created under the same name.
 
removed and some other file/directory is created under the same name.
−
It's rare case.
+
It's a rare case.
    
Now, is that all? No, sorry. A couple of things left. First, Linux has
 
Now, is that all? No, sorry. A couple of things left. First, Linux has
Line 168: Line 169:  
info about what mount point the file belongs to like this:
 
info about what mount point the file belongs to like this:
   −
<pre>
+
<source lang="C">
 
struct file {
 
struct file {
 
char *path;
 
char *path;
Line 175: Line 176:  
unsigned mnt_id;
 
unsigned mnt_id;
 
} *f;
 
} *f;
−
</pre>
+
</source>
    
and the code to open file would now look like
 
and the code to open file would now look like
   −
<pre>
+
<source lang="C">
 
int fd, tfd = -1, ns_fd;
 
int fd, tfd = -1, ns_fd;
 
char *rel_path = f->path + 1;
 
char *rel_path = f->path + 1;
Line 210: Line 211:     
close(ns_fd);
 
close(ns_fd);
−
</pre>
+
</source>
   −
Let me not dive into the details of how the open_ns_root looks like.
+
Let's not dive into the details of how the <code>open_ns_root</code> looks like.
 
Just know, that it opens a file descriptor, that refers to the root
 
Just know, that it opens a file descriptor, that refers to the root
−
of the mount namespace that contains a mount point with the id mnt_id
+
of the mount namespace that contains a mount point with the id <code>mnt_id</code>
 
(they cannot be shared, and that's great).
 
(they cannot be shared, and that's great).
   Line 220: Line 221:  
First, opened files typically have a position. Flags we get need to be
 
First, opened files typically have a position. Flags we get need to be
 
sanitated not to container those that only make sense during open,
 
sanitated not to container those that only make sense during open,
−
like O_TRUNC or O_CREAT. And file may have a thing called fown managed
+
like <code>O_TRUNC</code> or <code>O_CREAT</code>. And file may have a thing called <code>fown</code> managed
−
by the F_SETSIG and F_SETOWN fcntls. All this results in
+
by the <code>F_SETSIG</code> and <code>F_SETOWN</code> fcntls. All this results in
   −
<pre>
+
<source lang="C">
 
struct file {
 
struct file {
 
char *path;
 
char *path;
Line 232: Line 233:  
struct fown fown;
 
struct fown fown;
 
} *f;
 
} *f;
−
</pre>
+
</source>
    
and
 
and
   −
<pre>
+
<source lang="C">
 
int fd, tfd = -1, ns_fd, open_flags;
 
int fd, tfd = -1, ns_fd, open_flags;
 
char *rel_path = f->path + 1;
 
char *rel_path = f->path + 1;
Line 272: Line 273:  
fcntl(fd, F_SETOWN, &f->fown->owner);
 
fcntl(fd, F_SETOWN, &f->fown->owner);
 
lseek(fd, SEEK_SET, f->pos);
 
lseek(fd, SEEK_SET, f->pos);
−
</pre>
+
</source>
   −
And don't ask for details of the f->fown thing. It's tricky, but just
+
And don't ask for details of the <code>f->fown</code> thing. It's tricky, but just
−
follows the ABI and thus boring.
+
follows the ABI and therefore boring.
   −
OK, we've finished with the top of the iceberg -- opening a file. Why
+
OK, we've finished with the top of the iceberg — opening a file. Why
 
top? Becase when opened file should be planted into a process' file
 
top? Becase when opened file should be planted into a process' file
−
descriptors table under desired number. You might thing, that it's as
+
descriptors table under desired number. You might think that it should be
−
simple as
+
as simple as:
−
 
+
<source lang="C">
−
<pre>
   
dup2(fd, desired_fd);
 
dup2(fd, desired_fd);
−
</pre>
+
</source>
   −
but it's not. Here's [[how to assign needed file descriptor to a file]] :)
+
but it's not. Here's [[how to assign needed file descriptor to a file]].
    
[[Category:Under the hood]]
 
[[Category:Under the hood]]
 
[[Category:Files]]
 
[[Category:Files]]

Navigation menu