ZDSFS

From OSDev Wiki
Jump to navigation Jump to search
Filesystems
Virtual Filesystems

VFS

Disk Filesystems
CD/DVD Filesystems
Network Filesystems
Flash Filesystems

ZDSFS is the normal filesystem used on virtually all DASD disks.

VTOC

The filesystem uses DSCBs to hold the information of all files in the VTOC table (Volume's Table Of Contents). This table is found after the DASD's IPL which usually means the VTOC is at record 3, cylinder 0 and head 0.

To find the sequence of format 1 entries the OS has to read 0, 0, 3. Place the first 20 bytes into a buffer then obtain the location of the format 1 DSCBs:

void GetCHRFromVTOC(void *buffer) {
    uint16_t cyl, head;
    uint8_t rec;

    memcpy(&cyl, buffer + 15, 2); /* 15-16 */
    memcpy(&head, buffer + 17, 2); /* 17-18 */
    memcpy(&rec, buffer + 19, 1); /* 19-19 */
    return;
}

Format 1 DSCB

Name Size Usage
DS1NAM 44 Name of dataset
DS1FMTID 1 Format Id
UNUSED 80
EXT_TYPE 1
SEQUENCE_NUMBER
1
START_CC 2 Starting cylinder
START_HH 2 Starting head
END_CC 2 Ending cylinder
END_HH 2 Ending head

This entry describes a dataset (file) general information, including location and name. This is generally what most people will search for.

The entries are ordered in a chain-like structure, where a formatId=0 entry denotes the end of said chain.

// NOTE: This code assumes EBCDIC is being used
void CheckDSCB(struct DSCB1 *dscb, const char *name) {
    if(dscb1.ds1fmtid == '1') {
        dscb1.ds1fmtid = ' ';
        if(!memcmp(&dscb1.ds1dsnam, name, strlen(name))) {
            // Dataset found
            cyl = dscb1.start_cc;
            head = dscb1.start_hh;
            rec = 1;

            kprintf("DATASET %s @ CYL=%i,HEAD=%i,RECORD=%i\n", name, (int)cyl, (int)head, (int)rec);

            // The kernel now should use Cyl, Head and the Rec locations provided to read the dataset
            kpanic("TODO: Use cyl, head and rec to read the file\n");
        }
    } else if(dscb1.ds1dsnam[0] == '\0') {
        // Not found
        kpanic("Could not find file %s!", name);
    }
}

Finding the files is just a matter of reading records until reaching the end of the head, then incrementing heads and after reading the last head in the cylinder, incrementing cylinders. This also has to be done for reading files.

This is mostly specific to DASD devices but it's provided for clarity.

// NOTE: This code assumes EBCDIC is being used
void FindFile(const char *name) {
    while(errcnt < 4) {
        r = DasdReadCHR(hdl, &cyl, &head, &rec, &dscb1, sizeof(dscb1));
        if(r < 0) {
            ++errcnt;
            if(errcnt == 1) {
                // If we have an error reading this record skip to the next
                ++rec;
            } else if(errcnt == 2) {
                // Next record failed?, now we need to change heads
                rec = 1;
                ++head;
            } else if(errcnt == 3) {
                // Switch cylinders if we can't read new heads either
                rec = 1;
                head = 0;
                ++cyl;
            }
            continue;
        }

        errcnt = 0;
        if(r >= (int)sizeof(dscb1)) {
            CheckDSCB(&dscb1, name);
        }

        // Go to next record
        ++rec;
    }
}

See also

Source code

External links