Disk and Tape Formats

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.

Random-Access Volumes

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

a000-201Bad block replacement table
b204-251INITIALIZE/RESTORE data area
c252-273BUP information areaIf BUP volume: "BUQ" and 9 spaces; binary volume number in byte 266
d700-701(Reserved for Digital)000000
e702-703(Reserved for Digital)000000
f722-723Pack cluster size000001
g724-725Block number of first directory segment000006
h726-727System versionRadix-50 "V3A"
i730-743Volume Identification"RT11A" and seven spaces
j744-757Owner name1210 spaces
k760-773System Identification"DECRT11A" and four spaces

The checksum computation conforms to the (FILES-11 On-Disk Structure Specification). It is a simple additive checksum of all the other words in the home block and is computed according to the following algorithm:

        MOV     Header_address,R0
        CLR     R1
        MOV     #255.,R2
10$:    ADD     (R0)+,R1
        SOB     R2,10$
        MOV     R1,@R0

The contents of all other areas in the home block are undefined and reserved for future use by Digital.

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.)

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

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.

1The 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.
2The 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.
3The 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.
4The number of extra bytes per directory entry, always an unsigned, even octal number. See Directory Entry Format below for more information.
5The block number on the volume where the actual stored data identified by this segment begins.

Table 2. Directory Segment Header Words

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.

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:

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.

High Byte Values, Expressed as a Word
000400E.TENTTentative file.
001000E.MPTYEmpty area. RT-11 does not use the name, file type, or data fields in the directory entry for an empty area.
002000E.PERMPermanent file.
004000E.EOSEnd-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.
040000E.READProtected by monitor from write operations from .WRITE request; not protected from any special function operations or deletions.
100000E.PROTProtected permanent file (see File Protection. Only a permanent file can be protected.
Low Byte Values, Expressed as a Word
000020E.PREPrefix block indicator. Indicates the presence of at least one prefix block in this file.

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. ()RT-11 uses the sixth word (job number and channel number word) only when the file is tentative. Once the file becomes permanent, RT-11 no longer uses the word. The function of the sixth word while the file is permanent is reserved for future use by Digital.

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

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.


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



    10 Files in segment 1

     4 Available segments, 1 in use

 10 Files, 413 blocks
 373 Free blocks

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.

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.

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.

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.

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.

     512 - 5
31 * -------  - 3
      7 + N

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 - 1) * - + S

M represents the maximum number of segments.

S can be computed from the following formula:

    512 - 5
S = ------- - 3
     7 + N

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.

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.

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 (directory full) error will occur when the directory is only half full. A squeeze will be required to consolidate the half-full directory segments before more files can be copied to the disk. However, splitting a directory segment reduces the amount of directory entry shuffling that occurs as files are added and deleted on a volume, thereby improving overall efficiency.

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.