180 lines
3.7 KiB
Text
180 lines
3.7 KiB
Text
|
.SH
|
||
|
The server processes
|
||
|
.PP
|
||
|
The main file system algorithm is a set
|
||
|
of identical processes
|
||
|
named
|
||
|
.CW srv
|
||
|
that honor the
|
||
|
9P protocol.
|
||
|
Each file system process waits on
|
||
|
a message queue for an incoming request.
|
||
|
The request contains a 9P message and
|
||
|
the address of a reply queue.
|
||
|
A
|
||
|
.CW srv
|
||
|
process parses the message,
|
||
|
performs pseudo-disk I/O
|
||
|
to the corresponding file system block device,
|
||
|
formulates a response,
|
||
|
and sends the
|
||
|
response back to the reply queue.
|
||
|
.PP
|
||
|
The unit of storage is a
|
||
|
logical block
|
||
|
(not physical sector) of data on a device:
|
||
|
.Ex
|
||
|
.TA 0.5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i
|
||
|
enum
|
||
|
{
|
||
|
RBUFSIZE = 8*1024
|
||
|
};
|
||
|
|
||
|
typedef vlong Off;
|
||
|
typedef
|
||
|
struct
|
||
|
{
|
||
|
short pad;
|
||
|
short tag;
|
||
|
Off path;
|
||
|
} Tag;
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
BUFSIZE = RBUFSIZE - sizeof(Tag)
|
||
|
};
|
||
|
|
||
|
typedef
|
||
|
struct
|
||
|
{
|
||
|
uchar data[BUFSIZE];
|
||
|
Tag tag;
|
||
|
} Block;
|
||
|
.Ee
|
||
|
All devices are idealized as a perfect disk
|
||
|
of contiguously numbered blocks each of size
|
||
|
.CW RBUFSIZE .
|
||
|
Each block has a tag that identifies what type
|
||
|
of block it is and a unique id of the file or directory
|
||
|
where this block resides.
|
||
|
The remaining data in the block depends on
|
||
|
what type of block it is.
|
||
|
.PP
|
||
|
The
|
||
|
.CW srv
|
||
|
process's main data structure is the directory entry.
|
||
|
This is the equivalent of a UNIX i-node and
|
||
|
defines the set of block addresses that comprise a file or directory.
|
||
|
Unlike the i-node,
|
||
|
the directory entry also has the name of the
|
||
|
file or directory in it:
|
||
|
.Ex
|
||
|
enum
|
||
|
{
|
||
|
NAMELEN = 56,
|
||
|
NDBLOCK = 6,
|
||
|
NIBLOCK = 4,
|
||
|
};
|
||
|
.Ee
|
||
|
.Ex
|
||
|
typedef
|
||
|
struct
|
||
|
{
|
||
|
char name[NAMELEN];
|
||
|
short uid;
|
||
|
short gid;
|
||
|
ushort mode;
|
||
|
short wuid;
|
||
|
Qid qid;
|
||
|
Off size;
|
||
|
Off dblock[NDBLOCK];
|
||
|
Off iblocks[NIBLOCK];
|
||
|
long atime;
|
||
|
long mtime;
|
||
|
} Dentry;
|
||
|
.Ee
|
||
|
Each directory entry holds the file or directory
|
||
|
name, protection mode, access times, user-id, group-id, and addressing
|
||
|
information.
|
||
|
The entry
|
||
|
.CW wuid
|
||
|
is the user-id of the last writer of the file
|
||
|
and
|
||
|
.CW size
|
||
|
is the size of the file in bytes.
|
||
|
The addresses of the first 6
|
||
|
blocks of the file are held in the
|
||
|
.CW dblock
|
||
|
array.
|
||
|
If the file is larger than that,
|
||
|
an indirect block is allocated that holds
|
||
|
the next
|
||
|
.CW BUFSIZE/sizeof(Off)
|
||
|
block addresses of the file.
|
||
|
The indirect block address is held in
|
||
|
.CW iblocks[0] .
|
||
|
If the file is larger yet,
|
||
|
then there is a double indirect block that points
|
||
|
at indirect blocks.
|
||
|
The double indirect address is held in
|
||
|
.CW iblocks[1]
|
||
|
and can point at another
|
||
|
.CW (BUFSIZE/sizeof(Off))\u\s-2\&2\s+2\d
|
||
|
blocks of data.
|
||
|
This is extended through a quadruple indirect block at
|
||
|
.CW iblocks[3]
|
||
|
but the code is now parameterised to permit easily changing the
|
||
|
number of direct blocks and the depth of indirect blocks,
|
||
|
and also the maximum size of a file name component.
|
||
|
The maximum addressable size of a file is
|
||
|
therefore 7.93 petabytes at a block size of 8k,
|
||
|
but 7.98 exabytes (just under $2 sup 63$ bytes) at a block size of 32k.
|
||
|
File size is restricted to $2 sup 63 - 1$ bytes in any case
|
||
|
because the length of a file is maintained in a
|
||
|
(signed)
|
||
|
.I vlong .
|
||
|
These numbers are based on
|
||
|
.I fs64
|
||
|
which has a block size of 8k and
|
||
|
.CW sizeof(Off)
|
||
|
is 8.
|
||
|
.PP
|
||
|
The declarations of the indirect and double indirect blocks
|
||
|
are as follows.
|
||
|
.Ex
|
||
|
enum
|
||
|
{
|
||
|
INDPERBUF = BUFSIZE/sizeof(Off),
|
||
|
};
|
||
|
.Ee
|
||
|
.Ex
|
||
|
typedef
|
||
|
{
|
||
|
Off dblock[INDPERBUF];
|
||
|
Tag ibtag;
|
||
|
} Iblock;
|
||
|
.Ee
|
||
|
.Ex
|
||
|
typedef
|
||
|
{
|
||
|
Off iblock[INDPERBUF];
|
||
|
Tag dibtag;
|
||
|
} Diblock;
|
||
|
.Ee
|
||
|
.PP
|
||
|
The root of a file system is a single directory entry
|
||
|
at a known block address.
|
||
|
A directory is a file that consists of a list of
|
||
|
directory entries.
|
||
|
To make access easier,
|
||
|
a directory entry cannot cross blocks.
|
||
|
In
|
||
|
.I fs64
|
||
|
there are 47 directory entries per block.
|
||
|
.PP
|
||
|
The device on which the blocks reside is implicit
|
||
|
and ultimately comes from the 9P
|
||
|
.CW attach
|
||
|
message that specifies the name of the
|
||
|
device containing the root.
|