divergefs - diverge file system


divergefs [ -p defaultpath ] [ -f rulefile ] [ -h holefile ] [ -d debuglevel ] mountpoint


Divergefs is a user level file server which layers arbitrary number of directory trees on top of the base directory mountpoint based on user specified rules from rulefile. Its uses include, but are not limited to, temporarily modifying a few files on read-only media or speeding up compilation by storing object files locally instead of on a distant file server.


Specifies a default path where the holefile will be defaultpath/holes. If rulefile is not specified, a default rule file will be written to defaultpath/rules with content of:

defaultpath/files all<>

which means that defaultpath/files will be layered on top of mountpoint. defaultpath and defaultpath/files will be automatically created if they do not exist. (default /tmp if both rulefile and holefile are not specified).

Sets the user configuration file which defines what and how the directory trees will be layered.
Specifies the file to store file or directory names that were removed during the mounted session. If holefile exists, it will be used to initialize the file system, and any file matching the filenames after mount will be masked out. (default /tmp/holes or defaultpath/holes if using default path invocation).
Allows the user to specify the amount of debugging messages to be outputted ranging from 1-5. (default 3)

Note: any relative paths supplied either through command line arguments or inside the rule file will be relative to the current directory when divergefs is invoked.


The easiest way to use divergefs is to call it without any argument which is equivalent to calling it with -p /tmp. The following is an example for building kernel:

 % divergefs /sys/src
 % cd /sys/src/9/pc
 % mk 'CONF=pccpuf'

If divergefs is invoked with default path, it will automatically output a rule file to defaultpath/rules, in this case /tmp/rules, which can be modified later to suit different needs.

Default path is easy to use but is limited to layering only one directory on top of the mountpoint if the supplied default rule file is used. For more advanced usage, writing your own config file may be necessary. The following is an example avoiding write-back to remote server to speed up the compilation:

 % ramfs -m /n/junk
 % cat > divergefs.conf << EOF
 /n/junk ext<8>
 /tmp/pcbuild all<>
 % divergefs -f divergefs.conf /sys/src
 % cd /sys/src/9/pc
 % mk 'CONF=pccpuf'

After mounting, writing to /sys/src/*/*.8 will be redirected to /n/junk/*/*.8 while writing to other files will be redirected to /tmp/pcbuild/*.

Note: the first rule ext<8> will be on the top of the layered directory tree while the last rule all<> will be on the bottom just above the mountpoint.


A hole is the name of a file or directory that has been removed, and thus should not appear during any file operations. However, if a file or directory with the same name is created where a hole is, the hole will be filled up and replaced by the file or directory instead.

Therefore, a more robust approach is to supply the holefile argument while mounting which defaults to /tmp/holes. Hole file is necessary for the file system to keep track of which files were removed and should not be used. In the case of read-only media, the files will not be actually removed, but the file system has to simulate the effect of removing by "covering up" the filenames through the use of a hole file.

It is suggested that you supply the holefile argument if you are not using the default path invocation, so that holefile can be reused from a previous session to recover the state on that mountpoint. If no holefile is specified, and there are two running instances of divergefs, then they will be racing for the hole file at /tmp/holes and the result is undefined. Therefore, it is important that you make sure the hole file from an entirely different session is not reused.

In the case of default path invocation, if no holefile is specified, it defaults to defaultpath/holes. If such file exists, it will be picked up to resume a previous session, so it is ok not to specify a hole file when supplying the -p defaultpath argument.


config_file = (rule '\n')*

rule = path complex_rule

path = absolute_path | relative_path

complex_rule = simple_rule (("||" | "&&") complex_rule)?

simple_rule = concrete_rule '<' setting '>' | '(' complex_rule ')'

Concrete rules and corresponding setting syntax are described in the next section. Note: relative_path is relative to the current path at the time of invocation.


Rules are applied in the order as they appear in the config file, so that means rules on the top will take precedence over the ones below.
Matches anything. Note: the setting field must be empty.
setting = 'A' | 'L' | 'f' | 'd' | 'r' | 'w' | 'x' | 'e' Matches file with the given mode. Each mode can only have one character in the setting field. Please refer to test(1) for details on the meaning of each character. To apply multiple modes in a single rule, please use the || or && construct. Example: mode<r> || mode<w>
setting = file extension
setting = regular expression, refer to regexp(2) for details. matches any file name that satisfies the regular expression given.
setting = regular expression, refer to regexp(2) for details. matches any directory name that satisfies the regular expression given.
setting = regular expression, refer to regexp(2) for details. matches any name that satisfies the regular expression given.



Plan 9 wiki divergefs entry,


Renaming read-only directory will result in error.

The rule syntax is experimental (contact author with suggestions).

Time: 19:33:00 GMT, August 04, 2005