The PFS is responsible for actually moving data that is to be read
or written, and for implementing the semantics that are required by
the standards supported by z/OS UNIX.
See also Opening and closing files and first references to files.
vn_rdwr and vn_readwritev are UIO
operations, which means that:
- The UIO structure is part of the interface.
- The UIO contains the address, ALET, storage key, and address space
ID of the user's buffer or buffers. It has a read/write flag to distinguish
direction. For reads, it contains the length of the user's buffer
or buffers. For writes, it contains the number of bytes that are to
be written.
- The UIO contains the process file size limit for the file. On
a write or writev request it is the responsibility of the PFS to determine
when this limit has been reached or exceeded. When a write or writev
request is unable to write any data without exceeding the file size
limit, the PFS must set the bit in the UIO that indicates that the
limit was exceeded, and set the errno to EFBIG. The PFS must also
be aware of one other special value for the file size limit: If both
UIO.u_fssizelimithw and UIO.u_fssizelimitlw are equal to 0, there
is no file size limit set for the process.
- It is the responsibility of the PFS to maintain system integrity
while moving data between the address spaces. This means that the
Move With Source Key and Move With Destination Key machine instructions
or the osi_copyin, osi_copyout, and osi_uiomove services must be used.
- The caller maintains file positioning for the PFS, and the current
file cursor is in the UIO for every operation. This indicates the
position from which the read or write is to start.
When the O_APPEND
flag is set on in the open flags parameter for a write operation,
the UIO cursor is ignored by the PFS. Writing begins at the end of
the file, as it is known by the PFS at the time of the write.
The
UIO cursor may reflect the last read/write operation that was seen
by the PFS; it may be from a different instance of vn_open; or it
may have been changed through seek operations that were issued by
the user and that are not seen by the PFS.
The PFS modifies
the UIO cursor to reflect the file position after the operation.
The
UIO cursor area is 8 bytes long, to support large files. It is the
responsibility of the PFS to handle file offsets greater than 231 or
to reject them. The 8-byte cursor is a doubleword signed binary integer.
During vn_rdwr and vn_readwritev the PFS must:
- Do access checking, if the UIO check-access bit is on.
- Move the data. During vn_rdwr, if the UIO real-page bit is on,
use the DATOFF services of MVS™ to
move the data. The ability to refer to real pages is indicated by
the PFS during its initialization. If this cannot be supported, the
LFS supplies an intermediate virtual page buffer.
- Synchronize the data, if the UIO sync-on-write bit is on, and
turn on the sync-done bit to notify the LFS that it was done. Otherwise,
the LFS issues vn_fsync explicitly and the whole operation takes a
little longer.
- Ensure that the operation does not write beyond the process file
size limit. If the starting position is already at or beyond the
limit, the PFS must set the limit-exceeded bit in the UIO and return
with EFBIG. This check is done in the PFS because of the O_APPEND
case, in which it is much more efficient for the PFS to verify the
starting position.
- Return the number of bytes that were transferred.
- Modify the UIO cursor to reflect the file position after the operation.
Serialization: The vn_rdwr and vn_readwritev services
are invoked with an exclusive latch for both reads and writes. This
is to help the PFS implement the POSIX semantics that require atomic
operations and immediate visibility to all other processes.