示例#1
0
文件: lfflush.c 项目: BridgeNY/purdue
/*------------------------------------------------------------------------
 * lfflush  -  flush data block and index blocks for an open file
 *			(assumes file mutex is held)
 *------------------------------------------------------------------------
 */
status	lfflush (
	  struct lflcblk  *lfptr	/* ptr to file pseudo device	*/
	)
{
	if (lfptr->lfstate == LF_FREE) {
		return SYSERR;
	}

	/* Write data block if it has changed */

	if (lfptr->lfdbdirty) {
		write(Lf_data.lf_dskdev, lfptr->lfdblock, lfptr->lfdnum);
		lfptr->lfdbdirty = FALSE;
	}

	/* Write i-block if it has changed */

	if (lfptr->lfibdirty) {
		lfibput(Lf_data.lf_dskdev, lfptr->lfinum, &lfptr->lfiblock);
		lfptr->lfibdirty = FALSE;
	}
	
	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;
}
/*------------------------------------------------------------------------
 * 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;
}
示例#4
0
/*------------------------------------------------------------------------
 * lftruncate  -  truncate a file by freeing its index and data blocks
 *			(assumes directory mutex held)
 *------------------------------------------------------------------------
 */
status	lftruncate (
	  struct lflcblk *lfptr		/* ptr to file's cntl blk entry	*/
	)
{
	//struct	ldentry	*ldptr;		/* pointer to file's dir. entry	*/
	struct	lfiblk	iblock;		/* buffer for one index block	*/
	ibid32	ifree;			/* start of index blk free list	*/
	ibid32	firstib;		/* first index blk of the file	*/
	ibid32	nextib;			/* walks down list of the	*/
					/*   file's index blocks	*/
	dbid32	nextdb;			/* next data block to free	*/
	int32	i;			/* moves through data blocks in	*/
					/*   a given index block	*/

	//ldptr = lfptr->lfdirptr;	/* Get pointer to dir. entry	*/
	if (lfptr->lfsize == 0) {	/* file is already empty */
		return OK;
	}

	/* Clean up the open local file first */

	if ( (lfptr->lfibdirty) || (lfptr->lfdbdirty) ) {
		lfflush(lfptr);
	}
	lfptr->lfpos = 0;
	lfptr->lfinum = LF_INULL;
	lfptr->lfdnum = LF_DNULL;
	lfptr->lfbyte = &lfptr->lfdblock[LF_BLKSIZ];

	/* Obtain ID of first index block on free list */

	ifree = Lf_data.lf_dir.lfd_ifree;

	/* Record file's first i-block and clear directory entry */

	firstib = lfptr->lffirstib;
	lfptr->lffirstib= LF_INULL;
	lfptr->lfsize = 0;
	Lf_data.lf_dirdirty = TRUE;

	/* Walk along index block list, disposing of each data block	*/
	/*  and clearing the corresponding pointer.  A note on loop	*/
	/*  termination: last pointer is set to ifree below.		*/

	for (nextib=firstib; nextib!=ifree; nextib=iblock.ib_next) {

		/* Obtain a copy of current index block from disk	*/

		lfibget(Lf_data.lf_dskdev, nextib, &iblock);

		/* Free each data block in the index block		*/

		for (i=0; i<LF_IBLEN; i++) {	/* for each d-block	*/

			/* Free the data block */

			nextdb = iblock.ib_dba[i];
			if (nextdb != LF_DNULL) {
				lfdbfree(Lf_data.lf_dskdev, nextdb);
			}

			/* Clear entry in i-block for this d-block	*/

				iblock.ib_dba[i] = LF_DNULL;
		}

		/* Clear offset (just to make debugging easier)		*/

		iblock.ib_offset = 0;

		/* For the last index block on the list, make it point	*/
		/*	to the current free list			*/

		if (iblock.ib_next == LF_INULL) {
			iblock.ib_next = ifree;
		}

		/* Write cleared i-block back to disk */

		lfibput(Lf_data.lf_dskdev, nextib, &iblock);
	}

	/* Last index block on the file list now points to first node	*/
	/*   on the current free list.  Once we make the free list	*/
	/*   point to the first index block on the file list, the	*/
	/*   entire set of index blocks will be on the free list	*/

	Lf_data.lf_dir.lfd_ifree = firstib;

	/* Indicate that directory has changed and return */

	Lf_data.lf_dirdirty = TRUE;
	
	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;
}
示例#6
0
/*------------------------------------------------------------------------
 * lfstruncate  -  truncate a file by freeing its index and data blocks
 *			(assumes directory mutex held)
 *------------------------------------------------------------------------
 */
status	lfstruncate (
    char *name				/* file name to truncate		*/
)
{
    char	*nam, *cmp;			/* ptrs used during comparison	*/
    int32	i;					/* general loop index			*/
    struct	lflcblk	*lfptr;		/* ptr to open file table entry	*/
    struct	lfdir	*dirptr;	/* ptr to in-memory directory	*/
    bool8	found;				/* was the name found?			*/
    int32	retval;				/* value returned from function	*/
    struct	ldentry	*ldptr;		/* ptr to an entry in directory	*/
    ibid32	ifree;				/* start of index blk free list	*/
    ibid32	firstib;			/* first index blk of the file	*/
    ibid32	nextib;				/* 	 walks down list of the		*/
    /*    file's index blocks		*/
    dbid32	nextdb;				/* next data block to free		*/
    struct	lfiblk	iblock;		/* buffer for one index block	*/

    /* Check length of name file (leaving space for NULLCH 	*/
    nam = name;
    for (i=0; i< LF_NAME_LEN; i++) {
        if (*nam++ == NULLCH) {
            break;
        }
    }
    if (i >= LF_NAME_LEN) {		/* name is too long */
        //kprintf("Name is too long\r\n");
        return SYSERR;
    }

    /* Check if named file is open */
    for (i=0; i<Nlfl; i++) {	/* search file pseudo-devices	*/
        lfptr = &lfltab[i];
        if (lfptr->lfstate == LF_USED) {
            /* Compare requested name to name of open file 		*/
            nam = name;
            cmp = lfptr->lfname;
            while(*nam != NULLCH) {
                if (*nam != *cmp) {
                    break;
                }
                nam++;
                cmp++;
            }
            /* if named file is open, call lftruncate directly	*/
            if ( (*nam==NULLCH) && (*cmp == NULLCH) ) {
                //kprintf("file to truncate is open\r\n");
                wait(lfptr->lfmutex);
                retval = lftruncate(lfptr);
                signal(lfptr->lfmutex);
                //kprintf("truncated the open file\r\n");
                return retval;
            }
        }
    }

    /* Named file is not open	*/
    /* Obtain copy of directory if not already present in memory	*/
    dirptr = &Lf_data.lf_dir;
    if (! Lf_data.lf_dirpresent) {
        retval = read(Lf_data.lf_dskdev,(char *)dirptr,LF_AREA_DIR);
        if (retval == SYSERR ) {
            //kprintf("Cannot not read directory into memory\r\n");
            return SYSERR;
        }
        Lf_data.lf_dirpresent = TRUE;
    }

    /* Search directory to see if file exists */
    found = FALSE;
    for (i=0; i<dirptr->lfd_nfiles; i++) {
        ldptr = &dirptr->lfd_files[i];
        nam = name;
        cmp = ldptr->ld_name;
        while(*nam != NULLCH) {
            if (*nam != *cmp) {
                break;
            }
            nam++;
            cmp++;
        }
        if ( (*nam==NULLCH) && (*cmp==NULLCH) ) { /* name found	*/
            found = TRUE;
            break;
        }
    }

    /* if file does not exist, return SYSERR	*/
    if (! found) {
        signal(Lf_data.lf_mutex);
        //kprintf("Named file to truncate does not exist\r\n");
        return SYSERR;
    }
    /* if file is in directory, free its index and data blocks	*/
    else {
        if (ldptr->ld_size == 0) {	/* file is already empty */
            return OK;
        }
        /* Obtain ID of first index block on free list */
        ifree = Lf_data.lf_dir.lfd_ifree;

        /* Record file's first i-block and clear directory entry */
        firstib = ldptr->ld_ilist;
        ldptr->ld_ilist = LF_INULL;
        ldptr->ld_size = 0;
        Lf_data.lf_dirdirty = TRUE;

        /* Walk along index block list, disposing of each data block*/
        /*  and clearing the corresponding pointer.  A note on loop	*/
        /*  termination: last pointer is set to ifree below.		*/
        for (nextib=firstib; nextib!=ifree; nextib=iblock.ib_next) {

            /* Obtain a copy of current index block from disk	*/
            lfibget(Lf_data.lf_dskdev, nextib, &iblock);

            /* Free each data block in the index block		*/
            for (i=0; i<LF_IBLEN; i++) {	/* for each d-block	*/
                /* Free the data block */
                nextdb = iblock.ib_dba[i];
                if (nextdb != LF_DNULL) {
                    lfdbfree(Lf_data.lf_dskdev, nextdb);
                }

                /* Clear entry in i-block for this d-block	*/
                iblock.ib_dba[i] = LF_DNULL;
            }

            /* Clear offset (just to make debugging easier)		*/
            iblock.ib_offset = 0;

            /* For the last index block on the list, make it point	*/
            /*	to the current free list			*/
            if (iblock.ib_next == LF_INULL) {
                iblock.ib_next = ifree;
            }

            /* Write cleared i-block back to disk */
            lfibput(Lf_data.lf_dskdev, nextib, &iblock);
        }
        /* Last index block on the file list now points to first node	*/
        /*   on the current free list.  Once we make the free list	*/
        /*   point to the first index block on the file list, the	*/
        /*   entire set of index blocks will be on the free list	*/
        Lf_data.lf_dir.lfd_ifree = firstib;

        /* Indicate that directory has changed and return */
        Lf_data.lf_dirdirty = TRUE;

        return OK;
    }
}