Because the LFS obtains a shared latch for the vn_readdir operation,
there may be many users reading the same directory at the same time.
The vn_readdir output buffer is mapped by the DIRENT structure,
and its format is defined as follows:
- The buffer contains a variable number of variable-length directory
entries. Only full entries are placed in the buffer, up to the buffer
size specified, and the number of entries is returned on the interface.
- Each directory entry that is returned in the buffer has the following
format:
- 2-byte Entry_length. This length field includes itself.
- 2-byte Name_length. This is the length of the following Member_name
subfield.
- Member_name. A character field of length Name_length. This name
is not null-terminated.
- File-system-specific data. If Entry_length equals Name_length
plus 4 bytes, this subfield is not present. Whenever this field is
present, it must start with the file's inode number, st_ino, in 4
bytes.
To be XPG-conforming, the PFS must include the file's inode
number.
This subfield is not part of POSIX, but it is passed
through to all programs to use or ignore as they wish. A non-standards-conforming
program may take advantage of additional information provided by a
specific PFS that it knows about.
- The entries should be packed together. The length fields are
not aligned on any particular boundary.
An example of an entry for the name abc and inode number X'1234' is X'000B
0003 818283 00001234'.
Many applications expect entries for "." and ".." to
be returned. This is not strictly required for standards conformance.
Successive calls to vn_readdir for a particular end user must proceed
through the directory from the point at which the last one left off.
A call does not have to account for activity that occurred "behind" its
position in the directory, nor worry about items that may be deleted
from "in front" of the current position before it was reached.
The PFS does not directly maintain positioning over successive
calls to vn_readdir. The 8-byte UIO cursor is used to specify the
positioning within the directory.
Not all directories are implemented as simple linear files that
hold an array of name entries. Two continuation techniques may be
used, and these must both be supported by a PFS. These techniques
are:
- Cursor technique. The cursor that is returned by the PFS
in the UIO contains PFS-specific information that locates the next
directory entry. The caller is required to preserve the UIO cursor
and the entire output buffer from the last vn_readdir, and present
both of these on the next vn_readdir.
The
PFS may use the cursor as an offset into a simple linear directory
file, ignoring the buffer; or it may use it as an offset into the
output buffer of the last entry that was returned. The latter approach
can be used by a PFS with a tree-structured directory, where the previous
entry name is used as a key to search for the next entry. That is,
the last returned name, a 1-to-255-byte-long text string, is really
the cursor for the caller's position in the directory. To ensure data
integrity, you have to use the Move With Source Key instruction or
osi_copyin for the entry header, and then again for the name length.
The
cursor technique is used by the [ for POSIX-conforming functions.
- Index technique. The index that is set in the UIO by the
caller determines which entry to start reading from. To read through
the directory, the caller starts at 1 and maintains the index by adding
the number of entries returned to the previous index. The caller
may jump around in the directory, and there is no requirement that
the next index be related to the last vn_readdir.
This
technique views the directory as a one-based array, where the first
entry has an index of 1, the second entry has an index of 2, and so
on.
The index technique is used by the Network File System
and by the XL C/C++ runtime library for
XPG-conforming functions.
If the PFS wants the LFS to convert directory reads that use index
technique into cursor technique, the PFS must set the PfsiRddCursor
capability bit during its initialization. A PFS might want to do this
if its implementation of cursor technique has better performance than
index technique. Whenever possible, the LFS will convert to cursor
technique. However, a PFS that sets PfsiRddCursor must support the
following three requirements:
- If the PFS receives a vn_readdir with FuioRetCursor flag set
by the LFS, the PFS must return the cursor entry for each directory
entry in new field DirEntCursor.
- The PFS must return the dotdot entry in index 2.
- If a file tag was passed in the Mtab on the vfs_mount, the PFS
must save the file tag, and during readdirplus, must return the file
tag in the AttrFileTag of every entry that is not a directory or symbolic
link and does not already have a file tag.
The UIO contains both the cursor and index fields that are used
with these continuation techniques. The interpretation of these two
fields is summarized in the following table. :
Index |
Cursor |
Action |
---|
0 |
0 |
Start reading from the first entry. |
0 |
M |
Use the cursor value to resume reading. |
N |
0 |
Start reading from entry N. |
N |
M |
Start reading from entry N. |
Note: 0=zero; N and M are nonzero values.
A nonzero index overrides the cursor. When both are zero or the
index is 1, reading starts from the front of the directory.
The general flow for reading a directory is:
- On the first vn_readdir of a sequence, both fields are zero and
the PFS starts at the front of the directory. The normal cursor value
of the PFS and the number of entries that were placed in the buffer
are returned.
- On the next vn_readdir, the caller specifies whether the cursor
technique or index technique is being used to proceed through the
directory. The PFS positions itself in the directory based on the
technique used, reads more entries, and returns its normal updated
cursor value and the number of entries that were placed in the buffer.
The
PFS must always return an updated cursor value, even if the index
technique is being used. Some callers may switch between techniques,
as the XL C/C++ runtime library does
for the seekdir() function.
- In most cases, the caller continues in this way until the directory
is exhausted.
- The application can reset the directory stream to the beginning,
but this action is not passed through to the PFS. The next vn_readdir
simply has both cursor and index values of zero. The application
can also begin reading from any desired entry.