/*------------------------------------------------------------------------ * lfsetup - Set a file's index block and data block for the current * file position (assumes file mutex held) *------------------------------------------------------------------------ */ status lfsetup ( struct lflcblk *lfptr /* Pointer to slave file device */ ) { dbid32 dnum; /* Data block to fetch */ ibid32 ibnum; /* I-block number during search */ struct ldentry *ldptr; /* Ptr to file entry in dir. */ struct lfiblk *ibptr; /* Ptr to in-memory index block */ uint32 newoffset; /* Computed data offset for */ /* next index block */ int32 dindex; /* Index into array in an index */ /* block */ /* Obtain exclusive access to the directory */ wait(Lf_data.lf_mutex); /* Get pointers to in-memory directory, file's entry in the */ /* directory, and the in-memory index block */ ldptr = lfptr->lfdirptr; ibptr = &lfptr->lfiblock; /* If existing index block or data block changed, write to disk */ if (lfptr->lfibdirty || lfptr->lfdbdirty) { lfflush(lfptr); } ibnum = lfptr->lfinum; /* Get ID of curr. index block */ /* If there is no index block in memory (e.g., because the file */ /* was just opened), either load the first index block of */ /* the file or allocate a new first index block */ if (ibnum == LF_INULL) { /* Check directory entry to see if index block exists */ ibnum = ldptr->ld_ilist; if (ibnum == LF_INULL) { /* Empty file - get new i-block*/ ibnum = lfiballoc(); lfibclear(ibptr, 0); ldptr->ld_ilist = ibnum; lfptr->lfibdirty = TRUE; } else { /* Nonempty - read first i-block*/ lfibget(Lf_data.lf_dskdev, ibnum, ibptr); } lfptr->lfinum = ibnum; /* Otherwise, if current file position has been moved to an */ /* offset before the current index block, start at the */ /* beginning of the index list for the file */ } else if (lfptr->lfpos < ibptr->ib_offset) { /* Load initial index block for the file (we know that */ /* at least one index block exists) */ ibnum = ldptr->ld_ilist; lfibget(Lf_data.lf_dskdev, ibnum, ibptr); lfptr->lfinum = ibnum; } /* At this point, an index block is in memory, but may cover */ /* an offset less than the current file position. Loop until */ /* the index block covers the current file position. */ while ((lfptr->lfpos & ~LF_IMASK) > ibptr->ib_offset ) { ibnum = ibptr->ib_next; if (ibnum == LF_INULL) { /* Allocate new index block to extend file */ ibnum = lfiballoc(); ibptr->ib_next = ibnum; lfibput(Lf_data.lf_dskdev, lfptr->lfinum, ibptr); lfptr->lfinum = ibnum; newoffset = ibptr->ib_offset + LF_IDATA; lfibclear(ibptr, newoffset); lfptr->lfibdirty = TRUE; } else { lfibget(Lf_data.lf_dskdev, ibnum, ibptr); lfptr->lfinum = ibnum; } lfptr->lfdnum = LF_DNULL; /* Invalidate old data block */ } /* At this point, the index block in lfiblock covers the */ /* current file position (i.e., position lfptr->lfpos). The */ /* next step consists of loading the correct data block. */ dindex = (lfptr->lfpos & LF_IMASK) >> 9; /* If data block index does not match current data block, read */ /* the correct data block from disk */ dnum = lfptr->lfiblock.ib_dba[dindex]; if (dnum == LF_DNULL) { /* Allocate new data block */ dnum = lfdballoc((struct lfdbfree *)&lfptr->lfdblock); lfptr->lfiblock.ib_dba[dindex] = dnum; lfptr->lfibdirty = TRUE; } else if ( dnum != lfptr->lfdnum) { read(Lf_data.lf_dskdev, (char *)lfptr->lfdblock, dnum); lfptr->lfdbdirty = FALSE; } lfptr->lfdnum = dnum; /* Use current file offset to set the pointer to the next byte */ /* within the data block */ lfptr->lfbyte = &lfptr->lfdblock[lfptr->lfpos & LF_DMASK]; signal(Lf_data.lf_mutex); return OK; }
/*------------------------------------------------------------------------ * lfscreate -- Create an initially-empty file system on a disk *------------------------------------------------------------------------ */ status lfscreate ( did32 disk, /* ID of an open disk device */ ibid32 lfiblks, /* num. of index blocks on disk */ uint32 dsiz /* total size of disk in bytes */ ) { uint32 sectors; /* number of sectors to use */ uint32 ibsectors; /* number of sectors of i-blocks*/ uint32 ibpersector; /* number of i-blocks per sector*/ struct lfdir dir; /* Buffer to hold the directory */ uint32 dblks; /* total free data blocks */ struct lfiblk iblock; /* space for one i-block */ struct lfdbfree dblock; /* data block on the free list */ dbid32 dbindex; /* index for data blocks */ int32 retval; /* return value from func call */ int32 i; /* loop index */ //ibid32 nextib; //dbid32 nextdb; //int32 lfiblks_free; /* total free index blocks */ /* Compute total sectors on disk */ sectors = dsiz / LF_BLKSIZ; /* truncate to full sector */ /* Compute number of sectors comprising i-blocks */ ibpersector = LF_BLKSIZ / sizeof(struct lfiblk); ibsectors = (lfiblks+(ibpersector-1)) / ibpersector; /* round up*/ lfiblks = ibsectors * ibpersector; if (ibsectors > sectors/2) { /* invalid arguments */ //kprintf("ibsectors > sectors/2 - invalid arguments\r\n"); return SYSERR; } /* Create an initial sector 0 */ memset((char *)&dir, NULLCH, sizeof(struct lfdir)); //dir.lfd_nfiles = 0; dbindex= (dbid32)(ibsectors + 1); dir.lfd_ifree = 1; dir.lfd_dfree = dbindex + 1; dblks = sectors - ibsectors - 1; /* Initialize root directory entry */ (dir.root_entry).ld_size = 0; (dir.root_entry).ld_ilist = 0; (dir.root_entry).ld_name[0] = '/'; (dir.root_entry).ld_name[1] = NULLCH; (dir.root_entry).ld_type = LF_TYPE_DIR; retval = write(disk,(char *)&dir, LF_AREA_DIR); if (retval == SYSERR) { //kprintf("cannot create an initial directory\r\n"); return SYSERR; } /* Create an initial root directory index block 0 */ memset((char *)&iblock, NULLCH, sizeof(struct lfiblk)); lfibclear(&iblock, 0); iblock.ib_next = LF_INULL; iblock.ib_dba[0] = dbindex; /* point to first data blk */ for(i =1; i < LF_IBLEN; i++) { iblock.ib_dba[i] = LF_DNULL; } lfibput(disk, 0, &iblock); /* Create list of free i-blocks on disk from i-bloack 1 */ lfibclear(&iblock, 0); for (i=1; i<lfiblks-1; i++) { iblock.ib_next = (ibid32)(i + 1); lfibput(disk, i, &iblock); } iblock.ib_next = LF_INULL; lfibput(disk, i, &iblock); /* Create an initial root directory data block 0 */ memset((char *)&dblock, NULLCH, LF_BLKSIZ); write(disk, (char *)&dblock, dbindex); /* Create list of free data blocks on disk */ memset((char*)&dblock, NULLCH, LF_BLKSIZ); for (i=1; i<dblks-1; i++) { dblock.lf_nextdb = dbindex + 2; retval = write(disk, (char *)&dblock, dbindex+1); if (retval == SYSERR) { //kprintf("cannot create list of free data blocks on disk\r\n"); return SYSERR; } dbindex++; } dblock.lf_nextdb = LF_DNULL; retval = write(disk, (char *)&dblock, dbindex+1); if (retval == SYSERR) { //kprintf("cannot create list of free data blocks on disk\r\n"); return SYSERR; } //close(disk); /* //kprintf("lfscreate Done\r\n"); retval = read(disk,(char *)&dir, LF_AREA_DIR); lfiblks_free = 0; nextib = dir.lfd_ifree; //kprintf("initial index block is %d\n\r", nextib); while (nextib != LF_INULL) { lfiblks_free++; lfibget(disk, nextib, &iblock); nextib = iblock.ib_next; } ibsectors = (lfiblks_free + 6) /7; //kprintf("Found %d index blocks (%d sectors)\n\r", lfiblks_free, ibsectors); */ /* Follow data block list */ /* dblks = 0; nextdb = dir.lfd_dfree; //kprintf("initial data block is %d\n\r", nextdb); while (nextdb != LF_DNULL) { dblks++; read(disk, (char *)&dblock, nextdb); nextdb = dblock.lf_nextdb; } //kprintf("Found %d data blocks\n\r", dblks);*/ return OK; }
/*------------------------------------------------------------------------ * lfscreate - Create an initially-empty file system on a disk *------------------------------------------------------------------------ */ status lfscreate ( did32 disk, /* ID of an open disk device */ ibid32 lfiblks, /* Num. of index blocks on disk */ uint32 dsiz /* Total size of disk in bytes */ ) { uint32 sectors; /* Number of sectors to use */ uint32 ibsectors; /* Number of sectors of i-blocks*/ uint32 ibpersector; /* Number of i-blocks per sector*/ struct lfdir dir; /* Buffer to hold the directory */ uint32 dblks; /* Total free data blocks */ struct lfiblk iblock; /* Space for one i-block */ struct lfdbfree dblock; /* Data block on the free list */ dbid32 dbindex; /* Index for data blocks */ int32 retval; /* Return value from func call */ int32 i; /* Loop index */ /* Compute total sectors on disk */ sectors = dsiz / LF_BLKSIZ; /* Truncate to full sector */ /* Compute number of sectors comprising i-blocks */ ibpersector = LF_BLKSIZ / sizeof(struct lfiblk); ibsectors = (lfiblks+(ibpersector-1)) / ibpersector;/* Round up */ lfiblks = ibsectors * ibpersector; if (ibsectors > sectors/2) { /* Invalid arguments */ return SYSERR; } /* Create an initial directory */ memset((char *)&dir, NULLCH, sizeof(struct lfdir)); dir.lfd_nfiles = 0; dbindex= (dbid32)(ibsectors + 1); dir.lfd_dfree = dbindex; dblks = sectors - ibsectors - 1; retval = write(disk,(char *)&dir, LF_AREA_DIR); if (retval == SYSERR) { return SYSERR; } /* Create list of free i-blocks on disk */ lfibclear(&iblock, 0); for (i=0; i<lfiblks-1; i++) { iblock.ib_next = (ibid32)(i + 1); lfibput(disk, i, &iblock); } iblock.ib_next = LF_INULL; lfibput(disk, i, &iblock); /* Create list of free data blocks on disk */ memset((char*)&dblock, NULLCH, LF_BLKSIZ); for (i=0; i<dblks-1; i++) { dblock.lf_nextdb = dbindex + 1; write(disk, (char *)&dblock, dbindex); dbindex++; } dblock.lf_nextdb = LF_DNULL; write(disk, (char *)&dblock, dbindex); close(disk); return OK; }