1 0 . 4
H O W I T R E A L LY W O R K S
175
we can extend the C++ API to better support hard links and modify BFS to
implement them.
unlink() and rmdir()
A file system also needs to be able to delete files and directories. The
vnode layer API breaks this into three functions. The first two,
unlink()
and
rmdir()
, are almost identical except that
unlink()
only operates on files
and
rmdir()
only operates on directories. Both
unlink()
and
rmdir()
accept a
directory node pointer and a name to delete. First the name must be found in
the directory and the corresponding vnid loaded. The
unlink()
function must
check that the node being removed is a file (or symbolic link). The
rmdir()
function must ensure that the node being removed is a directory and that
the directory is empty. If the criteria are met, the file system should call the
vnode layer support routine
remove vnode()
on the vnid of the entity being
deleted. The next order of business for either routine is to delete the named
entry from the directory passed in by the vnode layer. This ensures that no
further access will be made to the file other than through already open file
descriptors. BFS also sets a flag in the node structure to indicate that the
file is deleted so that queries (which load the vnid directly instead of going
through path name translation) will not touch the file.
remove vnode()
The vnode layer support routine
remove vnode()
marks a vnode for dele-
tion. When the reference count on the marked vnode reaches zero, the vnode
layer calls the file system
remove vnode()
function. The file system
remove
vnode()
function is guaranteed to be single threaded and is only called once
for any vnid. The
remove vnode()
function takes the place of a call to
write
vnode()
. The vnode layer expects the file system
remove vnode()
function to
free up any of the permanent resources associated with the node as well as
any in-memory resources. For a disk-based file system such as BFS, the per-
manent resources associated with a file are the allocated data blocks of the
file and extra attributes belonging to the file. The
remove vnode()
function of
a file system is the last call ever made on a vnid.
rename()
The most difficult of all vnode operations is
rename()
. The complexity of
the
rename()
function derives from its guarantee of atomicity for a multistep
operation. The vnode layer passes four arguments to
rename()
: the old di-
rectory node pointer, the old name, the new directory pointer, and the new
name. The vnode layer expects the file system to look up the old name and
new name and call
get vnode()
for each node.
The simplest and most common
rename()
case is when the new name does
not exist. In this situation the old name is deleted from the old directory and
Practical File System Design:The Be File System
, Dominic Giampaolo
page 175