/*------------------------------------------------------------------------
 * 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;
}
示例#2
0
/*------------------------------------------------------------------------
 * 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;
}