RT-11 stores files under assigned file names on file-structured volumes. RT-11 volumes that are file-structured include all disks, diskettes, and magtapes.
Disks and diskettes are directory-structured volumes; they have a series of directory segments at the beginning of the volume. The directory segments contain entries describing the names, lengths, and creation dates of files on the volume. Because the directory is at the beginning of the volume, you can access any file, no matter where it is located, without reading any other files. For this reason, directory-structured volumes are sometimes called random-access or block-replaceable volumes.
Magtapes are file-structured volumes that do not have a directory at the beginning of the volume. While they do store some directory information at the beginning of each file, you must read the entire volume to obtain all the information about all the files. Because you must read the files in order, one after the other, magtapes are also called sequential-access volumes.
This chapter shows how RT-11 stores files on both random-access and sequential-access volumes. It also describes the contents of a volume directory and shows how to recover information from a random-access volume whose directory is corrupted.
A random-access volume consists of a series of 25610-word blocks where blocks 0 through 5 are reserved for system use and cannot be used for data storage. The volume directory begins at block 6. Figure 1 shows the format of a random-access volume.
Figure 1. Random-Access Volume
Block 1 of a random-access volume, called the home block, contains information about the volume and its owner. Figure 2 and Table 1 show the home block format and contents.
Figure 2. Home Block Format
Field | Location | Contents | Default |
---|---|---|---|
a | 000-201 | Bad block replacement table | |
b | 204-251 | INITIALIZE/RESTORE data area | |
c | 252-273 | BUP information area | If BUP volume: "BUQ" and 9 spaces; binary volume number in byte 266 |
d | 700-701 | (Reserved for Digital) | 000000 |
e | 702-703 | (Reserved for Digital) | 000000 |
f | 722-723 | Pack cluster size | 000001 |
g | 724-725 | Block number of first directory segment | 000006 |
h | 726-727 | System version | Radix-50 "V3A" |
i | 730-743 | Volume Identification | "RT11A" and seven spaces |
j | 744-757 | Owner name | 1210 spaces |
k | 760-773 | System Identification | "DECRT11A" and four spaces |
l | 776-777 | Checksum |
The checksum computation conforms to the
The contents of all other areas in the home block are undefined and
reserved for future use by Digital.
In general, you
require more segments if you need to store many small files on a large
volume. However, the minimal number of segments reduces the
size of the directory area and you obtain more space to store large files
on a smaller volume. The default number of directory segments is a
compromise.
Each directory segment consists of a five-word header plus a number of
entries containing file information. Each segment ends with an
end-of-segment marker.
Figure 3 shows the general format of a volume directory segment.
Figure 3. Volume Directory Segment Format
Table 2. Directory Segment Header Words
Figure 4. Directory Entry Format
The first word of each directory entry is the status word, which describes
the condition of the file identified by that directory entry. The high-order
byte of the status word contains information on the current state
of file. The low-order byte can identify a file class.
Figure 5 shows the format of the status word and
Table 3 describes the contents.
Figure 5. Directory Entry Status Word Format
RT-11 uses three kinds of directory entries to describe the type of
file:
You can think of the three types of entry as describing areas that are
categorized as temporary data, available space on the volume, or permanent
data. The volume directory contains at all times sufficient entries to
describe the entire volume.
A tentative fileis a file that is in the process of
being created. When a program issues the .ENTER programmed request,
for example, it creates a tentative file. The program must issue a
.CLOSE programmed request to make the tentative file permanent. If you
do not eventually close a tentative file, the system deletes it. The
DIR utility program lists tentative files that appear in directories
as UNUSED files.
An empty entry defines an area of the volume that is
available for use. Thus, when you delete a file, you obtain an empty
area. DIR lists an empty area as UNUSED,
followed by its length.
A permanent fileis a tentative file that has been
closed with the .CLOSE programmed request. Permanent files are unique
- that is, only one file can exist with a specific name and file type
on a volume. If another file exists with the same name and type when
the program closes the current tentative file, the monitor deletes the
first file as part of the .CLOSE routine, thus replacing the old file
with the new file. DIR lists permanent files that appear in
directories by their file names, file types, sizes, and creation
dates.
The file class information in the low byte of the status word either
marks a file as having particular characteristics or identifies the
file as a member of a particular group of files. At present, only
one bit is used; the rest are reserved for future use by Digital.
The prefix block bit indicates that the file contains
at least one prefix block. Prefix blocks are optional information
blocks that precede a file's information blocks and begin at logical
block 0 of a file. The utility or application using the prefix blocks
must set bit E.PRE in the status word, create the prefix blocks, and
maintain them. RT-11 provides no special support for prefix blocks.
Any utility that needs to store information about a file with the file
can use prefix blocks. All previous and
current utilities and applications can continue to read and write
files without regard for prefix block functionality. Prefix block
functionality need not concern you unless you write an application
that uses it.
The structure of prefix blocks reserved for use by RT-11 and
the recommended structure for user applications is as follows:
The high bit of the high byte indicates whether the prefix blocks were
created by distributed RT-11 software of a user application. If the
high bit is clear
Table 3
lists the valid values for the bytes of the status word and their
meanings. All undefined bits in the directory entry status word remain
reserved for Digital.
Table 3. Directory Entry Status Word Values
The second, third, and fourth words in a directory entry contain the
file name and file type in Radix-50. For empty area,
RT-11 normally ignores these words. However, the DIR /Q
option (or the
monitor DIRECTORY command with the /DELETED
option) lists the names and file types of deleted files.
The fifth word in a directory entry contains the total file length, which
consists of the number of blocks the file occupies on the volume. Attempts
to read or write outside the limits of the file result in an end-of-file
error.
The sixth word in a directory entry contains the channel number and
sometimes the job number as well. RT-11 uses this information only for
tentative files. A tentative file is associated with a job in one of two
ways, depending on which RT-11 monitor is running.
In the SJ environment, the low byte of the sixth word of the entry holds
the channel number on which the file is open. This number enables the
monitor to locate the correct tentative file for the channel when a program
issues the .CLOSE programmed request.
The low byte of the sixth word
of the directory entry contains the channel number. The high
byte of the sixth word contains the number of the job that is opening the
file. The job number is required to identify the correct tentative file
during the .CLOSE operation. It is also necessary
because several jobs can have files open using the same channel number.
The seventh word of a directory entry contains the
file's creation date. When a program creates a tentative
file by issuing the .ENTER programmed request, the system moves the
system date word into the creation date slot for the entry. The date
word is 0 if you did not enter a date with the DATE monitor command.
User programs can take advantage of the Age bits (bits 14
and 15) to extend the directory date by 3210 year
increments. Support for Age bits is not available in any RT-11
monitor or utility, but is included in the DATE/DATE4Y, IDATE, IDCOMP,
and IGTDIR subroutines and functions. The base year for calculation is
incremented by the Age bit values (0-3) and is 1972, 2004, 2036, and
2068, respectively.
Figure 6 shows the format of the date word.
Figure 6. Date Word Format
Figure 7. Directory Listings
Figure 8 shows the contents of segment 1 of the diskette directory,
obtained by dumping absolute block number 6 of the volume.
Figure 8.RT-11 Directory Segment
To find the starting block of a particular file, first find the directory
segment containing the entry for that file. Then, take the starting block
number in the fifth word of that directory segment and add the length
of each permanent, tentative, and empty entry in the directory before your
file. For example, in Figure 8
the permanent file RT11XM.SYS begins at
block number 518 on the volume; word 5 shows
168 and the previous entry, SWAP.SYS, is
338 blocks long.
When data is stored in contiguous blocks, I/O is more efficient. Transfers
to large buffers are handled directly by the hardware for certain disks;
seeks between blocks and program interrupts between blocks are eliminated.
File data is processed simply and efficiently since the data is not
encumbered by link words in each block. Routines to maintain the directory
are relatively small because the directory structure is simple. File
operations, such as open, delete, and close, are performed quickly with few
disk accesses, because only the directory must be accessed, and not
additional bitmaps or retrieval pointers.
One disadvantage of this method of storing data is that a volume can
become fragmented, requiring a squeeze operation to consolidate its free
space. Another is that once a file is closed, a running program cannot
easily increase its size. Only a small number of output files can be opened
simultaneously, even on a large volume, unless the limits of the file sizes
are known in advance. Finally, this scheme precludes the use of multiple
and hierarchical directories.
Figure 9
shows a simplified diagram of a random-access volume that
has a total of 2508 blocks of space available for files after bloc
through 5 and the directory are accounted for. The volume in the
figure has two permanent files and one empty area stored on it.
Figure 9. Random-Access Volume with Two Permanent Files
When you create a file, your program must specify a size for the file
in the .ENTER programmed request. If you know the exact number of
blocks required, you can use that number in the request. RT-11
will use a best-fit algorithm and attempt to put the file in a free
space that
exactly matches the size requested or, failing that, in the free space
that most closely matches the size requested.
If you do not know the actual size, as is
often the case, the space you specify should be large enough to
accommodate all the data possible. Two special cases for the .ENTER
programmed request let you do this easily. In the first case, a
length argument of 0 allocates for the file either one-half the largest
space available, or the second largest space, whichever is bigger; in the
second case, a length argument of -1 allocates the largest space possible
on the volume.
The monitor creates a tentative file on the volume with the length you
specified. The tentative file must always be followed by an empty area to
enable the system to recover unused space if less data is written to the
file than you originally estimated.
Figure 10 shows an example of a
tentative file whose allocated size is 1008 blocks.
Note that the total
amount of space on the volume, 2508 blocks in this case,
remains constant.
Figure 10. Random-Access Volume with One Tentative File
Suppose, for example, that while the file is being created by one program,
another program enters a new file, allocating 258 blocks for
it. The volume would appear as shown in Figure 11.
Remember that every tentative file must be followed by an empty area.
Figure 11. Random-Access Volume with Two Tentative Files
When a program finishes writing data to the volume, it closes the tentative
file with the .CLOSE programmed request. RT-11 then makes the tentative
file permanent. The length of the file is the actual size of the data that
was written. The size of the empty area is its original size plus any
unused space from the tentative file.
Figure 12
shows the same volume after both tentative files are
closed. The first file's actual length is 758 blocks, and
the second file's length is 108 blocks.
Figure 12. Random-Access Volume with Four Permanent Files
Because of this method of storing files, it is impossible in RT-11 to
extend the size of an existing file from within a running program. To make
an existing file appear to be bigger, you can read the existing file;
allocate a new, larger tentative file; and write both the old and the new
data to the new file. You can then delete the old file.
The CREATE/EXTENSION command (DUP /T option) is
an easy way to extend
the size of an existing file. However, to use this option, you must have an
empty file with sufficient space in it immediately following the data file.
The maximum number of directory segments on any RT-11 volume is
3110. Use the following formula to calculate the
theoretical maximum
number of directory entries, and thus, the maximum number of files.
N represents the number of extra information words per directory entry. If
N is 0, the maximum number of files you can store on the volume is
224210.
Note that all divisions are integer and the remainder should be discarded.
If you store files sequentially (that is, one immediately after another)
without deleting any files, roughly one-half of the theoretical maximum
number of files will fit on the volume before a directory overflow occurs.
This situation results from the way RT-11 handles filled directory
segments.
When a directory segment becomes full and it is necessary to open a new
segment, the monitor moves approximately one-half of the directory entries
of the filled segment to the new segment. Thus, when the final segment is
full, all previous segments have approximately one-half of their total
capacity. See Splitting a Directory Segment
for a detailed explanation of how RT-11 splits a directory segment.
If you add files continually to a volume without issuing the
SQUEEZE
monitor command, you can use the following formula to compute the maximum
number of entries, and thus, the maximum number of files.
M represents the maximum number of segments.
S can be computed from the following formula:
N represents the number of extra information words per entry.
You can realize the theoretical total of directory entries (see the first
formula, above) by compressing the volume (using the DUP
/S option or the monitor
SQUEEZE command) when the directory fills up. DUP packs the
directory segments as well as the physical volume.
Figure 13. Storing a New File
This procedure works properly as long as the empty entry and the entries
following it can move downward. However, if the segment is full, the
monitor must split the segment, if possible, to store the new
entry.
Figure 14 illustrates a directory segment that is full.
Figure 14. Full Directory Segment
First, the monitor checks the header for the number of segments available.
If there are none, a directory full error results
and the monitor cannot
store the new file. You can squeeze the volume at this point to pack the
directory segments and try the operation again.
If there is another directory segment available, the monitor divides the
current segment by first finding a permanent or tentative entry near the
middle of the segment and saving its first word. In place of the first
word, the monitor puts an end-of-segment marker. It then saves the
current link information, links the current segment to the next available
segment, and writes the current segment back to the volume.
Next, the monitor restores the first word of the middle entry to the copy
of the segment that is still in memory, and restores the link information.
It slides the middle entry and all the entries following it to the top of
the segment. Then, the monitor writes this segment to the volume as the next
available segment. Finally, the monitor reads segment 1 into memory and
updates the information in its header. At this point, control passes to the
top of the .ENTER routine, and the monitor begins its
search again for a suitable empty entry to accommodate the new file.
Figures 15 and 16
summarize the process of splitting a directory segment. In this
example, segment 1 was the only segment in use. It contained an empty
entry but did not have room for a tentative entry in addition to the
empty one. After the split, segments 1 and 2 are both about half full.
Figure 15. Directory Before Splitting
Figure 16. Directory After Splitting
After a directory segment splits, the monitor can store the new file in
either the new segment or the old one, depending on which segment now
contains the empty area. In
Figure 16
the empty area is in segment 2.
Thus far, the link words seem superfluous since the segments are always in
numerical order. However, consider a situation in which four segments are
available: segment 1 fills and overflows into segment 2; segment 2 fills
and overflows into segment 3; segments 1, 2, and 3 are half full, and they
are linked in the order in which they are located on the volume (blocks 6,
10, and 12). The picture changes if you delete a large file from segment 2,
leaving a large empty entry, and add a lot of small files to the volume.
Segment 2 now fills up and overflows into the next free segment, segment 4,
so that the links become visibly significant: segment 1 links to 2, segment
2 links to 4, and segment 4 links to 3 because segment 2 previously linked
to 3.
Figure 17 illustrates this example.
Figure 17. Directory Links
The process of splitting a directory segment in half when it is full may
seem unnecessarily complicated. In fact, if many files are simply copied to
a disk, a
Refer back to Figure 15.
Assume the empty entry between PERMANENT-5 and
PERMANENT-6 represents 1008 blocks
of free disk space and that directory splitting is not done. If a
program makes a directory entry for a new 258-block file,
the directory entry for the file PERMANENT-7 must be moved
to directory segment 2 to make room in segment 1 for the entry for
PERMANENT-5A and an empty entry of 758
blocks. If the program makes another directory entry for another
258-block file, the file PERMANENT-6 must be
moved to segment 2 to make room for the entry PERMANENT-5B
and an empty entry of 508 blocks. In other words, each
time a new directory entry occurs in segment 1, segment 2 must be
updated as well, requiring an extra disk read and write.
If a directory segment is split when full, however, this problem does
not occur as readily. Consider Figure 16 and observe
what has happened. When a program creates the new
258-block file PERMANENT-5A,
only directory segment 2 must be updated. No directory shuffling is
required. If the file PERMANENT-4
is deleted and replaced with two or more files, directory
segment 1 has room to accommodate the new file entries. Because directory
splitting moves several directory entries from one segment to another at
one time, any given directory operation is far less likely to require
access to more than one directory segment. Directory splitting reduces
dramatically the number of disk accesses required, on average, and improves
overall directory efficiency.
MOV Header_address,R0
CLR R1
MOV #255.,R2
10$: ADD (R0)+,R1
SOB R2,10$
MOV R1,@R0
Directory Structure
The directory consists of a series of two-block segments. Each segment is
51210 words long and contains information about files such as
name, length, and creation date. A directory can have from 1 to
3110 segments. You can display the default number of
directory segments on an initialized volume by issuing the
DIRECTORY/SUMMARY command.
You can change the size of the directory
area during volume initialization by specifying the number of
directory segments. Use the INITIALIZE/SEGMENTS:n
command, or DUP with the /Z/N:n options.
(See the System User's Guide for more information on the
INITIALIZE command. See the
Instalation Guide for a patch
that changes the default number of segments.)
Directory Segment Header Format
Each directory segment contains a five-word header, which leaves the
remaining 50710 words of the two-block segment for directory
entries. Table 2 describes the contents of the header words.
Word Contents 1 The total number of segments in this directory. The valid
range is from 1 through 3110. If you do not specify the number
of segments you require when you initialize the volume, DUP uses the
default number of segments for that volume. 2 The segment number of the next logical directory segment.
The directory is a linked list of segments and this word is the link
between the current segment and the next logical segment. If this word
is 0, there are no more segments in the list. 3 The number of the highest segment currently in use. RT-11
increments this counter each time it opens a new segment. Note that
the system maintains this counter in word 3 of the header only for the
first directory segment. It completely ignores the third word of the
header of the other segments. 4 The number of extra bytes per directory entry, always an
unsigned, even octal number. See Directory Entry Format below
for more information. 5 The block number on the volume where the actual stored
data identified by this segment begins. Directory Entry Format
The remainder of the directory segment consists of one or more directory
entries followed by an end-of-segment marker.
Figure 4
shows the format of a directory entry.
Value Mnemonic Meaning High Byte Values, Expressed as a Word 000400 E.TENT Tentative file. 001000 E.MPTY Empty area. RT-11 does not use the name, file type, or
data fields in the directory entry for an empty area. 002000 E.PERM Permanent file. 004000 E.EOS End-of-segment marker. RT-11
uses this marker to
determine when it has reached the end of the directory segment during
a directory search. Note that an end-of-segment marker can appear as
the last word of a segment. It does not have to be followed by a name,
file type, or other entry information. 040000 E.READ Protected by monitor from
write operations from .WRITE request; not protected from any special
function operations or deletions. 100000 E.PROT Protected permanent file (see
File Protection. Only a permanent file can be protected. Low Byte Values, Expressed as a Word 000020 E.PRE Prefix block indicator. Indicates the presence of at
least one prefix block in this file. File Protection
RT-11 provides a mechanism to prevent a file from being deleted. A file is
protected when the high bit of its status word is set. Only permanent files
can be protected. You can protect and unprotect files by using the PIP /R
option or the monitor RENAME command. Note that a protected file is
not protected against modification, only against deletion.
For more information, see the System User's Guide.
Sample Directory Segment
The directory listing shown in Figure 7 describes an RX50 diskette with 10 files.
DIRECTORY/FULL DU0:
12-Jul-88
SWAP .SYS 27 03-Sep-86 RT11XM.SYS 107 03-Sep-86
< UNUSED > 93 DUX .SYS 5 03-Sep-86
PIP .SAV 30 03-Sep-86 DUP .SAV 49 03-Sep-86
DIR .SAV 19 03-Sep-86 KED .SAV 58 03-Sep-86
MACRO .SAV 63 13-Nov-87 LINK .SAV 49 03-Sep-86
CREF .SAV 6 13-Nov-87 < UNUSED > 280
10 Files, 413 Blocks
373 Free blocks
DIRECTORY/SUMMARY DU0:
11-Jul-88
10 Files in segment 1
4 Available segments, 1 in use
10 Files, 413 blocks
373 Free blocks
File Storage on Random-Access Volumes
RT-11 uses the three types of directory entry mentioned previously to
completely describe the contents of a random-access volume. All files
reside on contiguous blocks. There are advantages
and disadvantages to this method of storing data.
Size and Number of Files
The number of files you can store on an RT-11 volume depends on the
number of segments in the volume's directory and the
number of extra words per entry. If you use no extra words, each
segment can contain 7210 entries. However, the maximum number of
entries
includes three that are reserved by the operating system and not
available to the user. These three entries in each segment are for
end-of-segment, empty (but reserved), and a reserved entry for use
when creating a tentative file. Therefore, the maximum number of
usable entries per directory segment is 6910.
512 - 5
31 * ------- - 3
7 + N
S
(M - 1) * - + S
2
512 - 5
S = ------- - 3
7 + N
Splitting a Directory Segment
Whenever RT-11 stores a new file on a volume, it searches through the
directory for an empty area that is large enough to accommodate the new
tentative file. When it finds a suitable empty area, it creates the new
file as a tentative file followed by an empty area, sliding the rest of the
directory entries down to make room for the new entry.
Figure 13 shows how RT-11 stores a new file as a tentative file followed by an empty
area.