Example #1
0
PUBLIC int search_file(char *path)
{
    /* 获得文件所在目录的 inode */
    char filename[MAX_PATH];
    memset(filename, 0, MAX_FILENAME_LEN);
    struct inode *dir_inode;
    if (strip_path(filename, path, &dir_inode) != 0)
        return 0;

    if (filename[0] == 0)
        return dir_inode->i_num;

    /* 根据这个 inode 找到对应扇区 */
    int dir_blk0_nr = dir_inode->i_start_sect;                             // 目录起始扇区
    int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE - 1) / SECTOR_SIZE; // 占用几个扇区(至少一个)
    int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE;               // 一共有几个条目
    int m = 0;
    struct dir_entry *pde;
    for (int i = 0; i < nr_dir_blks; i++) {
        RD_SECT(dir_inode->i_dev, dir_blk0_nr + i);
        pde = (struct dir_entry *)fsbuf;

        for (int j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++, pde++) {
            if (memcmp(filename, pde->name, MAX_FILENAME_LEN) == 0)
                return pde->inode_nr; // 文件存在
            if (++m > nr_dir_entries)
                break;
        }

        if (m > nr_dir_entries)
            break;
    }

    return 0; // 文件不存在
}
Example #2
0
File: open.c Project: kong123/STUDY
/**
 * Allocate a bit in inode-map.
 *
 * @param dev  In which device the inode-map is located.
 *
 * @return  I-node nr.
 *****************************************************************************/
PRIVATE int alloc_imap_bit(int dev)
{
    int inode_nr = 0;
    int i, j, k;

    int imap_blk0_nr = 1 + 1; /* 1 boot sector & 1 super block */
    struct super_block * sb = get_super_block(dev);

    for (i = 0; i < sb->nr_imap_sects; i++) {
        RD_SECT(dev, imap_blk0_nr + i);

        for (j = 0; j < SECTOR_SIZE; j++) {
            /* skip `11111111' bytes */
            if (fsbuf[j] == 0xFF)
                continue;
            /* skip `1' bits */
            for (k = 0; ((fsbuf[j] >> k) & 1) != 0; k++) {}
            /* i: sector index; j: byte index; k: bit index */
            inode_nr = (i * SECTOR_SIZE + j) * 8 + k;
            fsbuf[j] |= (1 << k);
            /* write the bit to imap */
            WR_SECT(dev, imap_blk0_nr + i);
            break;
        }

        return inode_nr;
    }

    /* no free bit in imap */
    panic("inode-map is probably full.\n");

    return 0;
}
Example #3
0
PRIVATE int alloc_imap_bit(int dev)
{
    int inode_nr = 0;
    int imap_blk0_nr = 1 + 1; // boot sector + super block
    struct super_block *sb = get_super_block(dev);

    for (int i = 0; i < sb->nr_imap_sects; i++) { // 逐扇区遍历 inode map
        RD_SECT(dev, imap_blk0_nr + i);

        for (int j = 0; j < SECTOR_SIZE; j++) { // 逐字节
            /* 跳过已经使用的(1:使用;0:未使用) */
            if (fsbuf[j] == 0xFF)
                continue;

            int k = 0;
            for (k = 0; ((fsbuf[j] >> k) & 1) != 0; k++); // 逐位(一位代表一个 inode)

            inode_nr = (i * SECTOR_SIZE + j) * 8 + k;
            fsbuf[j] |= (1 << k);

            /* 将更新后的 inode map 写入磁盘 */
            WR_SECT(dev, imap_blk0_nr + i);
            break;
        }

        return inode_nr;
    }

    panic("inode-map is probably full.\n");

    return 0;
}
Example #4
0
File: open.c Project: Zach41/OS
PRIVATE int alloc_imap_bit(int dev) {
    int inode_nr = 0;

    int i, j, k;
    int imap_blk0_nr = 2;
    assert(dev == ROOT_DEV);
    struct super_block *sb = get_super_block(dev);

    
    for (i=0; i<sb -> nr_imap_sects; i++) {
	RD_SECT(dev, imap_blk0_nr+i);

	for (j=0; j<SECTOR_SIZE; j++) {
	    if (fsbuf[j] == 0xFF)
		continue;
	    for (k=0; (fsbuf[j] & (1<<k))!=0; k++)
		;
	    inode_nr = (i*SECTOR_SIZE + j)*8 + k;
	    fsbuf[j] |= (1<<k);

	    WR_SECT(dev, imap_blk0_nr+i);

	    return inode_nr;
	}
    }

    panic("Inode map is full.\n");

    return 0;
}
Example #5
0
/**
 * Write a new entry into the directory.
 * 
 * @param dir_inode  I-node of the directory.
 * @param inode_nr   I-node nr of the new file.
 * @param filename   Filename of the new file.
 *****************************************************************************/
PRIVATE void new_dir_entry(struct inode * dir_inode, int inode_nr, char * filename)
{
	/* struct super_block * sb = get_super_block(dir_inode->i_dev); */

	/* write the dir_entry */
	int dir_blk0_nr = dir_inode->i_start_sect;
	/* printl("n_1st_sect:0x%x, dir_blk0_nr:0x%x\n", */
	/*        sb->n_1st_sect, dir_blk0_nr); */
	int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE;
	int nr_dir_entries =
		dir_inode->i_size / DIR_ENTRY_SIZE; /**
						     * including unused slots
						     * (the file has been
						     * deleted but the slot
						     * is still there)
						     */
	int m = 0;
	struct dir_entry * pde;
	struct dir_entry * new_de = 0;

	int i, j;
	for (i = 0; i < nr_dir_blks; i++) {
		RD_SECT(dir_inode->i_dev, dir_blk0_nr + i);

		pde = (struct dir_entry *)fsbuf;
		for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++,pde++) {
			if (++m > nr_dir_entries)
				break;

			if (pde->inode_nr == 0) { /* it's a free slot */
				new_de = pde;
				break;
			}
		}
		if (m > nr_dir_entries ||/* all entries have been iterated or */
		    new_de)              /* free slot is found */
			break;
	}
	/* printm("FS::in create_file: nr_dir_blks:%d, i:%d\n", nr_dir_blks, i); */
	if (!new_de) {		/* reached the end of the dir */
		new_de = pde;
		dir_inode->i_size += DIR_ENTRY_SIZE;
	}
	new_de->inode_nr = inode_nr;
	strcpy(new_de->name, filename);

	/* write dir block -- ROOT dir block */
	WR_SECT(dir_inode->i_dev, dir_blk0_nr + i);

	/* update dir inode */
	sync_inode(dir_inode);
}
Example #6
0
PUBLIC struct inode *get_inode(int dev, int num)
{
    struct inode *q = 0;

    /* 第 0 号 inode 为系统保留 */
    if (num == 0)
        return 0;

    /* 先在内存中的 inode_table 里查找 */
    for (struct inode *p = &inode_table[0]; p < &inode_table[NR_INODE]; p++) {
        if (p->i_cnt) {
            /* 如果找到了就直接返回 */
            if ((p->i_dev == dev) && (p->i_num == num)) {
                p->i_cnt++;
                return p;
            }
        }
        else
            if (!q)
                q = p;
    }

    /* inode_table 已经满员了 */
    if (!q)
        panic("the inode table is full");

    /* 找到第 num 个 inode 所在的扇区 */
    struct super_block *sb = get_super_block(dev);
    int blk_nr = 1 + 1                                     // boot sector + super block
               + sb->nr_imap_sects                         // + inode map
               + sb->nr_smap_sects                         // + sector map
               + ((num - 1) / (SECTOR_SIZE / INODE_SIZE));

    /* 读取这个扇区然后找到第 num 个 inode */
    RD_SECT(dev, blk_nr);
    struct inode *pinode =
        (struct inode *)((u8 *)fsbuf + ((num - 1) % (SECTOR_SIZE / INODE_SIZE)) * INODE_SIZE);

    /* 准备一个新的 inode */
    q->i_mode = pinode->i_mode;
    q->i_size = pinode->i_size;
    q->i_start_sect = pinode->i_start_sect;
    q->i_nr_sects = pinode->i_nr_sects;

    q->i_dev = dev;
    q->i_num = num;
    q->i_cnt = 1;

    return q;
}
Example #7
0
//when inode is changed , write it to disk
void sync_inode(struct inode *p)
{
    struct inode *pinode;
    struct super_block * get_super_block(int dev);
    struct super_block *sb = get_super_block(p->i_dev);
    int blk_nr = 2+sb->nr_imap_sects + sb->nr_smap_sects+ ((p->i_num-1)/(SECTOR_SIZE /INODE_SIZE));//inode_nr==0 is not used
    RD_SECT(p->i_dev, blk_nr);
    pinode = (struct inode *)((t_8*)fsbuf + ((p->i_num-1)%(SECTOR_SIZE/INODE_SIZE)) *INODE_SIZE);

    pinode->i_mode = p->i_mode;
    pinode->i_size = p->i_size;
    pinode->i_start_sect = p->i_start_sect;
    pinode->i_nr_sects = p->i_nr_sects;
    WR_SECT(p->i_dev, blk_nr);
}
Example #8
0
File: open.c Project: kong123/STUDY
/**
 * Allocate a bit in sector-map.
 *
 * @param dev  In which device the sector-map is located.
 * @param nr_sects_to_alloc  How many sectors are allocated.
 *
 * @return  The 1st sector nr allocated.
 *****************************************************************************/
PRIVATE int alloc_smap_bit(int dev, int nr_sects_to_alloc)
{
    /* int nr_sects_to_alloc = NR_DEFAULT_FILE_SECTS; */

    int i; /* sector index */
    int j; /* byte index */
    int k; /* bit index */

    struct super_block * sb = get_super_block(dev);

    int smap_blk0_nr = 1 + 1 + sb->nr_imap_sects;
    int free_sect_nr = 0;

    for (i = 0; i < sb->nr_smap_sects; i++) {
        /* smap_blk0_nr + i :
        					     current sect nr. */
        RD_SECT(dev, smap_blk0_nr + i);

        /* byte offset in current sect */
        for (j = 0; j < SECTOR_SIZE && nr_sects_to_alloc > 0; j++) {
            k = 0;
            if (!free_sect_nr) {
                /* loop until a free bit is found */
                if (fsbuf[j] == 0xFF) continue;
                for (; ((fsbuf[j] >> k) & 1) != 0; k++) {}
                free_sect_nr = (i * SECTOR_SIZE + j) * 8 +
                               k - 1 + sb->n_1st_sect;
            }

            for (; k < 8; k++) { /* repeat till enough bits are set */
                assert(((fsbuf[j] >> k) & 1) == 0);
                fsbuf[j] |= (1 << k);
                if (--nr_sects_to_alloc == 0)
                    break;
            }
        }

        if (free_sect_nr) /* free bit found, write the bits to smap */
            WR_SECT(dev, smap_blk0_nr + i);

        if (nr_sects_to_alloc == 0)
            break;
    }

    assert(nr_sects_to_alloc == 0);

    return free_sect_nr;
}
Example #9
0
/**
 * <Ring 1> Write the inode back to the disk. Commonly invoked as soon as the
 *          inode is changed.
 * 
 * @param p I-node ptr.
 *****************************************************************************/
PUBLIC void sync_inode(struct inode * p)
{
	struct inode * pinode;
	struct super_block * sb = get_super_block(p->i_dev);
	int blk_nr = 1 + 1 + sb->nr_imap_sects + sb->nr_smap_sects +
		((p->i_num - 1) / (SECTOR_SIZE / INODE_SIZE));
	RD_SECT(p->i_dev, blk_nr);
	pinode = (struct inode*)((u8*)fsbuf +
				 (((p->i_num - 1) % (SECTOR_SIZE / INODE_SIZE))
				  * INODE_SIZE));
	pinode->i_mode = p->i_mode;
	pinode->i_size = p->i_size;
	pinode->i_start_sect = p->i_start_sect;
	pinode->i_nr_sects = p->i_nr_sects;
	WR_SECT(p->i_dev, blk_nr);
}
Example #10
0
/**************************************************************************************************
 * 					get_inode
 **************************************************************************************************
 * <Ring 1> Get the inode pointer of given inode nr. A cache 'inode_table[]' is maintained to make
 * things faster. If the inode requested is already there, just return it. Otherwise the inode
 * will be read from the disk.
 *
 * @param dev	Device nr.
 * @param num	Inode nr.
 *
 * @return	The inode pointer requested.
 *************************************************************************************************/
PUBLIC struct inode* get_inode(int dev, int num){
	if(num == 0){
		return 0;
	}

	struct inode* p;
	struct inode* q = 0;
	for(p=&inode_table[0]; p<&inode_table[NR_INODE]; p++){
		if(p->i_cnt){	/* not a free slot */
			if((p->i_dev == dev) && (p->i_num == num)){
				/* this is the inode we want */
				p->i_cnt++;
				return p;
			}
		}else{		/* a free slot */
			if(!q){	/* q hasn't been assigned yet */
				q = p;	/* q <- the 1st free slot */
			}
		}
	}

	if(!q){
		panic("the inode table is full");
	}

	q->i_dev = dev;
	q->i_num = num;
	q->i_cnt = 1;

	struct super_block* sb = get_super_block(dev);
	int nr_blk = 1 + 1 + sb->nr_imap_sects + sb->nr_smap_sects + 
		((num - 1) / (SECTOR_SIZE / INODE_SIZE));

	RD_SECT(dev, nr_blk);

	struct inode* pinode = (struct inode*)
		((u8*)fsbuf + ((num - 1) % (SECTOR_SIZE / INODE_SIZE)) * INODE_SIZE);

	q->i_mode	= pinode->i_mode;
	q->i_size	= pinode->i_size;
	q->i_start_sect	= pinode->i_start_sect;
	q->i_nr_sects	= pinode->i_nr_sects;

	return q;
}
Example #11
0
/**************************************************************************************************
 * 					alloc_smap_bit
 **************************************************************************************************
 * Allocate a bit in sector-map.
 *
 * @param dev			In which device the sector-map is located.
 * @param nr_sects_to_alloc	How many sectors are allocated.
 *
 * @return	The 1st sector nr allocated.
 *************************************************************************************************/
PRIVATE int alloc_smap_bit(int dev, int nr_sects_to_alloc){
	int i, j, k;	/* i: sector index	j: byte index	k: bit index */
	int nr_free_sect	= 0;

	struct super_block* sb	= get_super_block(dev);
	int nr_smap_blk0	= 1 + 1 + sb->nr_imap_sects;

	for(i=0; i<sb->nr_smap_sects; i++){
		RD_SECT(dev, nr_smap_blk0 + i);

		for(j=0; j<SECTOR_SIZE && nr_sects_to_alloc > 0; j++){
			k = 0;
			if(!nr_free_sect){
				/* loop untill a free bit is found. */
				if(fsbuf[j] == 0xff){
					continue;
				}
				for(; ((fsbuf[j] >> k) & 1) != 0; k++){}

				nr_free_sect = (i * SECTOR_SIZE + j) * 8 + k - 1 + sb->n_1st_sect;
			}
			/* repeat till enough bits are set */
			for(; k < 8; k++){
				assert(((fsbuf[j] >> k) & 1) == 0);
				fsbuf[j] |= (1 << k);
				if(--nr_sects_to_alloc == 0){
					break;
				}
			}
		}
		/* free bit was found, write the bit to smap */
		if(nr_free_sect){
			WR_SECT(dev, nr_smap_blk0 + i);
		}

		if(nr_sects_to_alloc == 0){
			break;
		}
	}
	assert(nr_sects_to_alloc == 0);

	return nr_free_sect;
}
Example #12
0
File: open.c Project: Zach41/OS
PRIVATE int alloc_smap_bit(int dev, int nr_sects_to_alloc) {
    int i, j, k;
    assert(dev == ROOT_DEV);
    assert(nr_sects_to_alloc == NR_DEFAULT_FILE_SECTS);
    struct super_block* sb = get_super_block(dev);
    assert(sb -> nr_smap_sects);
    int smap_blk0_nr = 2 + sb -> nr_imap_sects;
    int free_sect_nr = 0;
    
    for (i=0; i<sb -> nr_smap_sects; i++) {
	RD_SECT(dev, smap_blk0_nr + i);

	for (j=0; j<SECTOR_SIZE && nr_sects_to_alloc>0; j++) {
	    k = 0;
	    if(!free_sect_nr) {
		/* 找到第一个空闲的扇区 */
		/* 由于文件最大长度固定,并不需要考虑空洞,找到就可以了 */
		if (fsbuf[j] == 0xFF)
		    continue;
		for(; (fsbuf[j] & (1<<k)) != 0; k++)
		    ;
		free_sect_nr = (i*SECTOR_SIZE + j) * 8 + k - 1 + sb -> n_1st_sect;
	    }

	    for(; k<8; k++) {
		assert(((fsbuf[j] >> k) & 1) == 0);
		fsbuf[j] |= 1<<k;
		if (--nr_sects_to_alloc == 0)
		    break;
	    }
	}
	if (free_sect_nr)
	    WR_SECT(dev, smap_blk0_nr+i);
	if (nr_sects_to_alloc == 0)
	    break;
    }

    if (nr_sects_to_alloc != 0) {
	panic("Don't have enough space.\n");
    }

    return free_sect_nr;
}
Example #13
0
PUBLIC int do_ls()
{
    int i, j;

    /*printl("DO something \n");*/
    /*char pathname[MAX_PATH] = "passwd";*/
    /*int inode_nr = search_file(pathname);*/

    struct inode * dir_inode = root_inode;

    int dir_blk0_nr = dir_inode->i_start_sect;
    int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
    int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE;
    int m = 0;

    struct dir_entry * pde;

    printl("\ninode        filename\n");
    printl("============================\n");

    for (i = 0; i < nr_dir_blks; i++)
    {
        RD_SECT(dir_inode->i_dev, dir_blk0_nr + i);

        pde = (struct dir_entry *)fsbuf;

        for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++, pde++)
        {
            /*struct inode *n = find_inode(pde->inode_nr);*/
            printl("  %2d        %s\n", pde->inode_nr , pde->name);
            if (++m >= nr_dir_entries){
                printl("\n");
                break;
            }
        }
        if (m > nr_dir_entries) //[> all entries have been iterated <]
            break;
    }

    printl("============================\n");

    return 0;
}
Example #14
0
PRIVATE void new_dir_entry(struct inode *dir_inode, int inode_nr, char *filename)
{
    /* write the dir_entry */
    int dir_blk0_nr = dir_inode->i_start_sect;                         // 目录文件的起始扇区
    int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE; // 目录文件所占扇区数
    int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE;           // 目录项数
    int m = 0;
    struct dir_entry *pde;
    struct dir_entry *new_de = 0;

    int i;
    for (i = 0; i < nr_dir_blks; i++) { // 逐扇区
        RD_SECT(dir_inode->i_dev, dir_blk0_nr + i);

        pde = (struct dir_entry *)fsbuf;
        for (int j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++, pde++) { // 逐目录项
            if (++m > nr_dir_entries)
                break;

            if (pde->inode_nr == 0) { /* it's a free slot */
                new_de = pde;
                break;
            }
        }

        if (m > nr_dir_entries || // all entries have been iterated or */
            new_de)               // free slot is found */
            break;
    }
    
    if (!new_de) { /* reached the end of the dir */
        new_de = pde;
        dir_inode->i_size += DIR_ENTRY_SIZE;
    }
    new_de->inode_nr = inode_nr;
    strcpy(new_de->name, filename);

    /* write dir block -- ROOT dir block */
    WR_SECT(dir_inode->i_dev, dir_blk0_nr + i);

    /* update dir inode */
    sync_inode(dir_inode);
}
Example #15
0
/**************************************************************************************************
 * 					new_dir_entry
 **************************************************************************************************
 * Write a new entry into the directory.
 *
 * @param dir_inode	Inode of the directory.
 * @param nr_inode	Inode nr of the new file.
 * @param filename	File name of the new file.
 *************************************************************************************************/
PRIVATE void new_dir_entry(struct inode* dir_inode, int nr_inode, char* filename){
	/* Write the dir_entry */
	int nr_dir_blk0	= dir_inode->i_start_sect;
	int nr_dir_blks	= (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE;
	/* including unused slots (the file has been deleted but the slot is still there) */
	int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE;

	int m = 0;
	int i, j;
	struct dir_entry* pde;
	struct dir_entry* new_de = 0;

	for(i=0; i<nr_dir_blks; i++){
		RD_SECT(dir_inode->i_dev, nr_dir_blk0 + i);

		pde = (struct dir_entry*) fsbuf;
		for(j=0; j<SECTOR_SIZE / DIR_ENTRY_SIZE; j++, pde++){
			if(++m > nr_dir_entries){
				break;
			}
			if(pde->inode_nr == 0){	/* it's a free slot */
				new_de = pde;
				break;
			}
		}
		if(m > nr_dir_entries || new_de){/* all entries have been iterated or */
			break;			/* free slot is found */
		}
	}
	if(!new_de){				/* reached the end of the dir */
		new_de = pde;
		dir_inode->i_size += DIR_ENTRY_SIZE;
	}
	new_de->inode_nr = nr_inode;
	strcpy(new_de->name, filename);

	/* Write dir block -- ROOT dir block */
	WR_SECT(dir_inode->i_dev, nr_dir_blk0 + i);

	/* update dir inode */
	sync_inode(dir_inode);
}
Example #16
0
/**
 * Search the file and return the inode_nr.
 *
 * @param[in] path The full path of the file to search.
 * @return         Ptr to the i-node of the file if successful, otherwise zero.
 * 
 * @see open()
 * @see do_open()
 *****************************************************************************/
PUBLIC int search_file(char * path)
{
	int i, j;

	char filename[MAX_PATH];
	memset(filename, 0, MAX_FILENAME_LEN);
	struct inode * dir_inode;
	if (strip_path(filename, path, &dir_inode) != 0)
		return 0;

	if (filename[0] == 0)	/* path: "/" */
		return dir_inode->i_num;

	/**
	 * Search the dir for the file.
	 */
	int dir_blk0_nr = dir_inode->i_start_sect;
	int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
	int nr_dir_entries =
	  dir_inode->i_size / DIR_ENTRY_SIZE; /**
					       * including unused slots
					       * (the file has been deleted
					       * but the slot is still there)
					       */
	int m = 0;
	struct dir_entry * pde;
	for (i = 0; i < nr_dir_blks; i++) {
		RD_SECT(dir_inode->i_dev, dir_blk0_nr + i);
		pde = (struct dir_entry *)fsbuf;
		for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++,pde++) {
			if (memcmp(filename, pde->name, MAX_FILENAME_LEN) == 0)
				return pde->inode_nr;
			if (++m > nr_dir_entries)
				break;
		}
		if (m > nr_dir_entries) /* all entries have been iterated */
			break;
	}

	/* file not found */
	return 0;
}
Example #17
0
/**
 * <Ring 1> Do some preparation.
 *
 *****************************************************************************/
PRIVATE void init_fs()
{
    int i;

    /* f_desc_table[] */
    for (i = 0; i < NR_FILE_DESC; i++)
        memset(&f_desc_table[i], 0, sizeof(struct file_desc));

    /* inode_table[] */
    for (i = 0; i < NR_INODE; i++)
        memset(&inode_table[i], 0, sizeof(struct inode));

    /* super_block[] */
    struct super_block * sb = super_block;
    for (; sb < &super_block[NR_SUPER_BLOCK]; sb++)
        sb->sb_dev = NO_DEV;

    /* open the device: hard disk */
    MESSAGE driver_msg;
    driver_msg.type = DEV_OPEN;
    driver_msg.DEVICE = MINOR(ROOT_DEV);
    assert(dd_map[MAJOR(ROOT_DEV)].driver_nr != INVALID_DRIVER);
    send_recv(BOTH, dd_map[MAJOR(ROOT_DEV)].driver_nr, &driver_msg);

    /* read the super block of ROOT DEVICE */
    RD_SECT(ROOT_DEV, 1);

    sb = (struct super_block *)fsbuf;
    if (sb->magic != MAGIC_V1) {
        printl("{FS} mkfs\n");
        mkfs(); /* make FS */
    }

    /* load super block of ROOT */
    read_super_block(ROOT_DEV);

    sb = get_super_block(ROOT_DEV);
    assert(sb->magic == MAGIC_V1);

    root_inode = get_inode(ROOT_DEV, ROOT_INODE);

}
Example #18
0
//dev :
//num :the no of inodg
//return :the ptr to the inode
struct inode * get_inode(int dev, int num)
{
//	RD_SECT(dev , 0);
    if(num == 0)
        return 0;
    struct inode *p;
    struct inode *q =0;

    for(p = &inode_table[0]; p< &inode_table[NR_INODE]; p++) {
        if(p->i_cnt) { //we find it in inode table
            if((p->i_dev == dev )&& (p->i_num == num)) {
                p->i_cnt++;
                return p;
            }
        }
        else { //p->i_cnt==0
            if(!q) { //the first cnt=0 inode
                q=p;
            }
        }
    }
    //
    if(!q)
        panic("the inode talbe is full\n");

    q->i_dev = dev;
    q->i_num = num;
    q->i_cnt = 1;
    struct super_block * get_super_block(int dev);
    struct super_block *sb = get_super_block(dev);
    int blk_nr = 2+sb->nr_imap_sects + sb->nr_smap_sects+ ((num-1)/(SECTOR_SIZE /INODE_SIZE));//inode_nr==0 is not used

    RD_SECT(dev, blk_nr);
    struct inode *pinode= (struct inode *)((t_8 *)fsbuf + ((num-1)%(SECTOR_SIZE / INODE_SIZE))*INODE_SIZE );
    q->i_mode = pinode->i_mode;
    q->i_size = pinode->i_size;
    q->i_start_sect = pinode ->i_start_sect;
    q->i_nr_sects = pinode->i_nr_sects;
    return q;

}
Example #19
0
PRIVATE int alloc_smap_bit(int dev, int nr_sects_to_alloc)
{
    struct super_block *sb = get_super_block(dev);
    int smap_blk0_nr = 1 + 1 + sb->nr_imap_sects; // boot sector + super block + inode map
    int free_sect_nr = 0; // 空闲 sector 起始号

    for (int i = 0; i < sb->nr_smap_sects; i++) { // 逐扇区遍历 sector map
        RD_SECT(dev, smap_blk0_nr + i);

        for (int j = 0; j < SECTOR_SIZE && nr_sects_to_alloc > 0; j++) { // 逐字节
            int k = 0;
            if (!free_sect_nr) {
                if (fsbuf[j] == 0xFF)
                    continue;
                for (; ((fsbuf[j] >> k) & 1) != 0; k++); // 逐位(一位代表一个扇区)

                free_sect_nr = (i * SECTOR_SIZE + j) * 8
                             + k - 1 + sb->n_1st_sect;
            }

            for (; k < 8; k++) {
                assert(((fsbuf[j] >> k) & 1) == 0);
                fsbuf[j] |= (1 << k);
                if (--nr_sects_to_alloc == 0)
                    break;
            }
        }

        /* 将更新后的 sector map 扇区写入磁盘 */
        if (free_sect_nr)
            WR_SECT(dev, smap_blk0_nr + i);

        if (nr_sects_to_alloc == 0)
            break;
    }

    assert(nr_sects_to_alloc == 0);

    return free_sect_nr;
}
Example #20
0
File: open.c Project: Zach41/OS
/* dir_inode: root_node */
PRIVATE void new_dir_entry(struct inode* dir_inode, int inode_nr, char* filename) {
    int dir_blk0_nr = dir_inode -> i_start_sect;
    int nr_dir_blks = (dir_inode -> i_size + SECTOR_SIZE) / SECTOR_SIZE;
    int nr_dir_entries = dir_inode -> i_size / DIR_ENTRY_SIZE;

    int i, j;
    int m = 0;
    struct dir_entry* p_dir_entry;
    struct dir_entry* new_entry = 0;

    for(i=0; i<nr_dir_blks; i++) {
	RD_SECT(dir_inode -> i_dev, dir_blk0_nr + i);
	p_dir_entry = (struct dir_entry*)fsbuf;

	for (j = 0; j<SECTOR_SIZE / DIR_ENTRY_SIZE; j++, p_dir_entry++) {
	    if (++m > nr_dir_entries)
		break;

	    if (p_dir_entry -> inode_nr == 0) {
		/* 之前被删除的文件留下来的entry */
		/* 如果文件删除了,dir_inode -> i_size不会改变 */
		new_entry = p_dir_entry;
		break;
	    }
	}
	if (m > nr_dir_entries || new_entry)
	    break;
    }
    if (!new_entry) {
	new_entry = p_dir_entry;
	dir_inode -> i_size += DIR_ENTRY_SIZE;
    }

    new_entry -> inode_nr = inode_nr;
    strcpy(new_entry -> name, filename);

    WR_SECT(dir_inode -> i_dev, dir_blk0_nr+i);

    sync_inode(dir_inode);
}
Example #21
0
/**
 * Allocate a bit in sector-map.
 * 
 * @param dev  In which device the sector-map is located.
 * @param nr_sects_to_alloc  How many sectors are allocated.
 * @param i_zone the zone of the inode
 * 
 * @return  The 1st sector nr allocated.
 *****************************************************************************/
PRIVATE int alloc_bit(int dev)
{
	int i; /* sector index */
	int j; /* byte index */
	int k; /* bit index */

	struct super_block * sb = get_super_block(dev);

	int smap_blk0_nr = 1 + 1 + sb->nr_imap_sects;
	int flag_bit_alloc = 0;
	int bit_alloc = 0;
	for (i = 0; i < sb->nr_smap_sects; i++) { /* smap_blk0_nr + i :
						     current sect nr. */
		RD_SECT(dev, smap_blk0_nr + i);

		/* byte offset in current sect */
		for (j = 0; j < SECTOR_SIZE ; j++) {
			/* loop until a free bit is found */
			if (fsbuf[j] != 0xFF) {
				k = 0;
				for (; ((fsbuf[j] >> k) & 1) != 0; k++) {}

				assert(((fsbuf[j] >> k) & 1) == 0);
				fsbuf[j] |= (1 << k);
				flag_bit_alloc = 1;
				//1 byte = 8 bit ~ stand for 8 sector
				bit_alloc = i * SECTOR_SIZE * 8
							+ j * 8
							+ k - 1
							+ sb->n_1st_sect;
				break;
			}
		}

		if (flag_bit_alloc) {
			/* free bit found, write the bits to smap */
			WR_SECT(dev, smap_blk0_nr + i);
			break;
		}
	}
Example #22
0
//path:the full name of the file
//return:inode num of the file if success, otherwise zero
int search_file(char *path)
{
#ifdef DEBUG_rw
    printl("search_file : path =%s|\n", path );
#endif
    int i,j;
    char filename[MAX_PATH_LEN];
    memset(filename , 0, MAX_FILENAME_LEN);
    struct inode *dir_inode;
    if(strip_path(filename, path, &dir_inode)!=0)
        return 0;
#ifdef DEBUG_rw
    printl("search_file : filename =%s|\n", filename );
#endif
    if(filename[0]== 0)//path '/'
        return dir_inode->i_num;

    //search the dir for the file
    int dir_sects0_index = dir_inode->i_start_sect;
    int nr_dir_sects = (dir_inode->i_size +SECTOR_SIZE -1)/SECTOR_SIZE;
    int nr_dir_dentries = (dir_inode->i_size)/DIR_ENTRY_SIZE;

    int m= 0;
    struct dir_entry *pde;
    for (i = 0; i < nr_dir_sects; ++i) { //里面有空的
        RD_SECT(dir_inode->i_dev, dir_sects0_index +i);
        pde = (struct dir_entry *)fsbuf;
        for(j=0; j<SECTOR_SIZE/DIR_ENTRY_SIZE; j++ , pde++) {
            if(memcmp(filename , pde->name, MAX_FILENAME_LEN) == 0)
                return pde->inode_nr;
            if(++m >nr_dir_dentries)
                break;
        }
        if(m> nr_dir_dentries)
            break;
    }
    return 0;
}
Example #23
0
/**
 * Remove a file.
 *
 * @note We clear the i-node in inode_array[] although it is not really needed.
 *       We don't clear the data bytes so the file is recoverable.
 * 
 * @return On success, zero is returned.  On error, -1 is returned.
 *****************************************************************************/
PUBLIC int do_unlink()
{
	char pathname[MAX_PATH];

	/* get parameters from the message */
	int name_len = fs_msg.NAME_LEN;	/* length of filename */
	int src = fs_msg.source;	/* caller proc nr. */
	assert(name_len < MAX_PATH);
	phys_copy((void*)va2la(TASK_FS, pathname),
		  (void*)va2la(src, fs_msg.PATHNAME),
		  name_len);
	pathname[name_len] = 0;

	if (strcmp(pathname , "/") == 0) {
		printl("FS:do_unlink():: cannot unlink the root\n");
		return -1;
	}

	int inode_nr = search_file(pathname);
	if (inode_nr == INVALID_INODE) {	/* file not found */
		printl("FS::do_unlink():: search_file() returns "
			"invalid inode: %s\n", pathname);
		return -1;
	}

	char filename[MAX_PATH];
	struct inode * dir_inode;
	if (strip_path(filename, pathname, &dir_inode) != 0)
		return -1;

	struct inode * pin = get_inode(dir_inode->i_dev, inode_nr);

	if (pin->i_mode != I_REGULAR) { /* can only remove regular files */
		printl("cannot remove file %s, because "
		       "it is not a regular file.\n",
		       pathname);
		return -1;
	}

	if (pin->i_cnt > 1) {	/* the file was opened */
		printl("cannot remove file %s, because pin->i_cnt is %d.\n",
		       pathname, pin->i_cnt);
		return -1;
	}

	struct super_block * sb = get_super_block(pin->i_dev);

	/*************************/
	/* free the bit in i-map */
	/*************************/
	int byte_idx = inode_nr / 8;
	int bit_idx = inode_nr % 8;
	assert(byte_idx < SECTOR_SIZE);	/* we have only one i-map sector */
	/* read sector 2 (skip bootsect and superblk): */
	RD_SECT(pin->i_dev, 2);
	assert(fsbuf[byte_idx % SECTOR_SIZE] & (1 << bit_idx));
	fsbuf[byte_idx % SECTOR_SIZE] &= ~(1 << bit_idx);
	WR_SECT(pin->i_dev, 2);

	/**************************/
	/* free the bits in s-map */
	/**************************/
	/*
	 *           bit_idx: bit idx in the entire i-map
	 *     ... ____|____
	 *                  \        .-- byte_cnt: how many bytes between
	 *                   \      |              the first and last byte
	 *        +-+-+-+-+-+-+-+-+ V +-+-+-+-+-+-+-+-+
	 *    ... | | | | | |*|*|*|...|*|*|*|*| | | | |
	 *        +-+-+-+-+-+-+-+-+   +-+-+-+-+-+-+-+-+
	 *         0 1 2 3 4 5 6 7     0 1 2 3 4 5 6 7
	 *  ...__/
	 *      byte_idx: byte idx in the entire i-map
	 */
	bit_idx  = pin->i_start_sect - sb->n_1st_sect + 1;
	byte_idx = bit_idx / 8;
	int bits_left = pin->i_nr_sects;
	int byte_cnt = (bits_left - (8 - (bit_idx % 8))) / 8;

	/* current sector nr. */
	int s = 2  /* 2: bootsect + superblk */
		+ sb->nr_imap_sects + byte_idx / SECTOR_SIZE;

	RD_SECT(pin->i_dev, s);

	int i;
	/* clear the first byte */
	for (i = bit_idx % 8; (i < 8) && bits_left; i++,bits_left--) {
		//assert((fsbuf[byte_idx % SECTOR_SIZE] >> i & 1) == 1);
		fsbuf[byte_idx % SECTOR_SIZE] &= ~(1 << i);
	}

	/* clear bytes from the second byte to the second to last */
	int k;
	i = (byte_idx % SECTOR_SIZE) + 1;	/* the second byte */
	for (k = 0; k < byte_cnt; k++,i++,bits_left-=8) {
		if (i == SECTOR_SIZE) {
			i = 0;
			WR_SECT(pin->i_dev, s);
			RD_SECT(pin->i_dev, ++s);
		}
		//assert(fsbuf[i] == 0xFF);
		fsbuf[i] = 0;
	}

	/* clear the last byte */
	if (i == SECTOR_SIZE) {
		i = 0;
		WR_SECT(pin->i_dev, s);
		RD_SECT(pin->i_dev, ++s);
	}
	unsigned char mask = ~((unsigned char)(~0) << bits_left);
	//assert((fsbuf[i] & mask) == mask);
	fsbuf[i] &= (~0) << bits_left;
	WR_SECT(pin->i_dev, s);

	/***************************/
	/* clear the i-node itself */
	/***************************/
	pin->i_mode = 0;
	pin->i_size = 0;
	pin->i_start_sect = 0;
	pin->i_nr_sects = 0;
	sync_inode(pin);
	/* release slot in inode_table[] */
	put_inode(pin);

	/************************************************/
	/* set the inode-nr to 0 in the directory entry */
	/************************************************/
	int dir_blk0_nr = dir_inode->i_start_sect;
	int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE;
	int nr_dir_entries =
		dir_inode->i_size / DIR_ENTRY_SIZE; /* including unused slots
						     * (the file has been
						     * deleted but the slot
						     * is still there)
						     */
	int m = 0;
	struct dir_entry * pde = 0;
	int flg = 0;
	int dir_size = 0;

	for (i = 0; i < nr_dir_blks; i++) {
		RD_SECT(dir_inode->i_dev, dir_blk0_nr + i);

		pde = (struct dir_entry *)fsbuf;
		int j;
		for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++,pde++) {
			if (++m > nr_dir_entries)
				break;

			if (pde->inode_nr == inode_nr) {
				/* pde->inode_nr = 0; */
				memset(pde, 0, DIR_ENTRY_SIZE);
				WR_SECT(dir_inode->i_dev, dir_blk0_nr + i);
				flg = 1;
				break;
			}

			if (pde->inode_nr != INVALID_INODE)
				dir_size += DIR_ENTRY_SIZE;
		}

		if (m > nr_dir_entries || /* all entries have been iterated OR */
		    flg) /* file is found */
			break;
	}
	assert(flg);
	if (m == nr_dir_entries) { /* the file is the last one in the dir */
		dir_inode->i_size = dir_size;
		sync_inode(dir_inode);
	}

	return 0;
}
Example #24
0
/**
 * <Ring 1> Make a available Orange'S FS in the disk. It will
 *          - Write a super block to sector 1.
 *          - Create three special files: dev_tty0, dev_tty1, dev_tty2
 *          - Create a file cmd.tar
 *          - Create the inode map
 *          - Create the sector map
 *          - Create the inodes of the files
 *          - Create `/', the root directory
 *****************************************************************************/
PRIVATE void mkfs()
{
	MESSAGE driver_msg;
	int i, j;

	/************************/
	/*      super block     */
	/************************/
	/* get the geometry of ROOTDEV */
	struct part_info geo;
	driver_msg.type		= DEV_IOCTL;
	driver_msg.DEVICE	= MINOR(ROOT_DEV);
	driver_msg.REQUEST	= DIOCTL_GET_GEO;
	driver_msg.BUF		= &geo;
	driver_msg.PROC_NR	= TASK_FS;
	assert(dd_map[MAJOR(ROOT_DEV)].driver_nr != INVALID_DRIVER);
	send_recv(BOTH, dd_map[MAJOR(ROOT_DEV)].driver_nr, &driver_msg);

	printl("{FS} dev size: 0x%x sectors\n", geo.size);

	int bits_per_sect = SECTOR_SIZE * 8; /* 8 bits per byte */
	/* generate a super block */
	struct super_block sb;
	sb.magic	  = MAGIC_V1; /* 0x111 */
	sb.nr_inodes	  = bits_per_sect;
	sb.nr_inode_sects = sb.nr_inodes * INODE_SIZE / SECTOR_SIZE;
	sb.nr_sects	  = geo.size; /* partition size in sector */
	sb.nr_imap_sects  = 1;
	sb.nr_smap_sects  = sb.nr_sects / bits_per_sect + 1;
	sb.n_1st_sect	  = 1 + 1 +   /* boot sector & super block */
		sb.nr_imap_sects + sb.nr_smap_sects + sb.nr_inode_sects;
	sb.root_inode	  = ROOT_INODE;
	sb.inode_size	  = INODE_SIZE;
	struct inode x;
	sb.inode_isize_off= (int)&x.i_size - (int)&x;
	sb.inode_start_off= (int)&x.i_start_sect - (int)&x;
	sb.dir_ent_size	  = DIR_ENTRY_SIZE;
	struct dir_entry de;
	sb.dir_ent_inode_off = (int)&de.inode_nr - (int)&de;
	sb.dir_ent_fname_off = (int)&de.name - (int)&de;

	memset(fsbuf, 0x90, SECTOR_SIZE);
	memcpy(fsbuf, &sb, SUPER_BLOCK_SIZE);

	/* write the super block */
	WR_SECT(ROOT_DEV, 1);

	printl("{FS} devbase:0x%x00, sb:0x%x00, imap:0x%x00, smap:0x%x00\n"
	       "        inodes:0x%x00, 1st_sector:0x%x00\n", 
	       geo.base * 2,
	       (geo.base + 1) * 2,
	       (geo.base + 1 + 1) * 2,
	       (geo.base + 1 + 1 + sb.nr_imap_sects) * 2,
	       (geo.base + 1 + 1 + sb.nr_imap_sects + sb.nr_smap_sects) * 2,
	       (geo.base + sb.n_1st_sect) * 2);

	/************************/
	/*       inode map      */
	/************************/
	memset(fsbuf, 0, SECTOR_SIZE);
	for (i = 0; i < (NR_CONSOLES + 3); i++)
		fsbuf[0] |= 1 << i;

	assert(fsbuf[0] == 0x3F);/* 0011 1111 :
				  *   || ||||
				  *   || |||`--- bit 0 : reserved
				  *   || ||`---- bit 1 : the first inode,
				  *   || ||              which indicates `/'
				  *   || |`----- bit 2 : /dev_tty0
				  *   || `------ bit 3 : /dev_tty1
				  *   |`-------- bit 4 : /dev_tty2
				  *   `--------- bit 5 : /cmd.tar
				  */
	WR_SECT(ROOT_DEV, 2);

	/************************/
	/*      secter map      */
	/************************/
	memset(fsbuf, 0, SECTOR_SIZE);
	int nr_sects = NR_DEFAULT_FILE_SECTS + 1;
	/*             ~~~~~~~~~~~~~~~~~~~|~   |
	 *                                |    `--- bit 0 is reserved
	 *                                `-------- for `/'
	 */
	for (i = 0; i < nr_sects / 8; i++)
		fsbuf[i] = 0xFF;

	for (j = 0; j < nr_sects % 8; j++)
		fsbuf[i] |= (1 << j);

	WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects);

	/* zeromemory the rest sector-map */
	memset(fsbuf, 0, SECTOR_SIZE);
	for (i = 1; i < sb.nr_smap_sects; i++)
		WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + i);

	/* cmd.tar */
	/* make sure it'll not be overwritten by the disk log */
	assert(INSTALL_START_SECT + INSTALL_NR_SECTS < 
	       sb.nr_sects - NR_SECTS_FOR_LOG);
	int bit_offset = INSTALL_START_SECT -
		sb.n_1st_sect + 1; /* sect M <-> bit (M - sb.n_1stsect + 1) */
	int bit_off_in_sect = bit_offset % (SECTOR_SIZE * 8);
	int bit_left = INSTALL_NR_SECTS;
	int cur_sect = bit_offset / (SECTOR_SIZE * 8);
	RD_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);
	while (bit_left) {
		int byte_off = bit_off_in_sect / 8;
		/* this line is ineffecient in a loop, but I don't care */
		fsbuf[byte_off] |= 1 << (bit_off_in_sect % 8);
		bit_left--;
		bit_off_in_sect++;
		if (bit_off_in_sect == (SECTOR_SIZE * 8)) {
			WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);
			cur_sect++;
			RD_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);
			bit_off_in_sect = 0;
		}
	}
	WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);

	/************************/
	/*       inodes         */
	/************************/
	/* inode of `/' */
	memset(fsbuf, 0, SECTOR_SIZE);
	struct inode * pi = (struct inode*)fsbuf;
	pi->i_mode = I_DIRECTORY;
	pi->i_size = DIR_ENTRY_SIZE * 5; /* 5 files:
					  * `.',
					  * `dev_tty0', `dev_tty1', `dev_tty2',
					  * `cmd.tar'
					  */
	pi->i_start_sect = sb.n_1st_sect;
	pi->i_nr_sects = NR_DEFAULT_FILE_SECTS;
	/* inode of `/dev_tty0~2' */
	for (i = 0; i < NR_CONSOLES; i++) {
		pi = (struct inode*)(fsbuf + (INODE_SIZE * (i + 1)));
		pi->i_mode = I_CHAR_SPECIAL;
		pi->i_size = 0;
		pi->i_start_sect = MAKE_DEV(DEV_CHAR_TTY, i);
		pi->i_nr_sects = 0;
	}
	/* inode of `/cmd.tar' */
	pi = (struct inode*)(fsbuf + (INODE_SIZE * (NR_CONSOLES + 1)));
	pi->i_mode = I_REGULAR;
	pi->i_size = INSTALL_NR_SECTS * SECTOR_SIZE;
	pi->i_start_sect = INSTALL_START_SECT;
	pi->i_nr_sects = INSTALL_NR_SECTS;
	WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + sb.nr_smap_sects);

	/************************/
	/*          `/'         */
	/************************/
	memset(fsbuf, 0, SECTOR_SIZE);
	struct dir_entry * pde = (struct dir_entry *)fsbuf;

	pde->inode_nr = 1;
	strcpy(pde->name, ".");

	/* dir entries of `/dev_tty0~2' */
	for (i = 0; i < NR_CONSOLES; i++) {
		pde++;
		pde->inode_nr = i + 2; /* dev_tty0's inode_nr is 2 */
		sprintf(pde->name, "dev_tty%d", i);
	}
	(++pde)->inode_nr = NR_CONSOLES + 2;
	sprintf(pde->name, "cmd.tar", i);
	WR_SECT(ROOT_DEV, sb.n_1st_sect);
}
Example #25
0
PRIVATE void mkfs()
{
    MESSAGE driver_msg;
    int bits_per_sect = SECTOR_SIZE * 8;

    struct part_info geo;
    driver_msg.type = DEV_IOCTL;
    driver_msg.DEVICE = MINOR(ROOT_DEV);
    driver_msg.REQUEST = DIOCTL_GET_GEO;
    driver_msg.BUF = &geo;
    driver_msg.PROC_NR = TASK_FS;
    assert(dd_map[MAJOR(ROOT_DEV)].driver_nr != INVALID_DRIVER);
    send_recv(BOTH, dd_map[MAJOR(ROOT_DEV)].driver_nr, &driver_msg);

    printl("dev base: 0x%x, dev size: 0x%x sectors\n", geo.base, geo.size);

    /***********************/
    /*     super block     */
    /***********************/
    struct super_block sb;
    sb.magic = MAGIC_V1;
    sb.nr_inodes = bits_per_sect;
    sb.nr_sects = geo.size;
    sb.nr_imap_sects = 1;
    sb.nr_smap_sects = sb.nr_sects / bits_per_sect + 1;
    sb.nr_inode_sects = sb.nr_inodes * INODE_SIZE / SECTOR_SIZE;
    sb.n_1st_sect = 1 + 1 + sb.nr_imap_sects + sb.nr_smap_sects + sb.nr_inode_sects;
    sb.root_inode = ROOT_INODE;
    sb.inode_size = INODE_SIZE;
    sb.inode_isize_off = offsetof(struct inode, i_size);
    sb.inode_start_off = offsetof(struct inode, i_start_sect);
    sb.dir_ent_size = DIR_ENTRY_SIZE;
    sb.dir_ent_inode_off = offsetof(struct dir_entry, inode_nr);
    sb.dir_ent_fname_off = offsetof(struct dir_entry, name);

    memset(fsbuf, 0x90, SECTOR_SIZE);
    memcpy(fsbuf, &sb, SUPER_BLOCK_SIZE);

    WR_SECT(ROOT_DEV, 1); // write the super block

    printl(
        "devbase: 0x%x00, sb: 0x%x00, imap: 0x%x00, smap: 0x%x00\n"
        "     inodes: 0x%x00, 1st_sector: 0x%x00\n", 
        geo.base * 2,
        (geo.base + 1) * 2,
        (geo.base + 1 + 1) * 2,
        (geo.base + 1 + 1 + sb.nr_imap_sects) * 2,
        (geo.base + 1 + 1 + sb.nr_imap_sects + sb.nr_smap_sects) * 2,
        (geo.base + sb.n_1st_sect) * 2
    );

    /***********************/
    /*      inode Map      */
    /***********************/
    memset(fsbuf, 0x0, SECTOR_SIZE);
    for (int i = 0; i < (NR_CONSOLES + 3); i++)
        fsbuf[0] |= 1 << i;

    assert(fsbuf[0] == 0x3F); /* 0011 1111
                               *   || |||`- bit 0 : reserved
                               *   || ||`-- bit 1 : the frist inode which indicates '/'
                               *   || |`--- bit 2 : /dev_tty0
                               *   || `---- bit 3 : /dev_tty1
                               *   |`------ bit 4 : /dev_tty2
                               *   `------- bit 5 : /cmd.tar
                               */
    WR_SECT(ROOT_DEV, 2);

    /***********************/
    /*      sector Map     */
    /***********************/
    memset(fsbuf, 0x0, SECTOR_SIZE);
    int nr_sects = NR_DEFAULT_FILE_SECTS + 1;

    int i;
    for (i = 0; i < nr_sects / 8; i++)
        fsbuf[i] = 0xFF;

    for (int j = 0; j < nr_sects % 8; j++)
        fsbuf[i] |= (1 << i);

    WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects);

    memset(fsbuf, 0x0, SECTOR_SIZE);
    for (int i = 1; i < sb.nr_smap_sects; i++)
        WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + i);

    /* cmd.tar */
    int bit_offset = INSTALL_START_SECT - sb.n_1st_sect + 1; // sect M <-> bit (M - sb.n_1stsect + 1)
    int bit_off_in_sect = bit_offset % (SECTOR_SIZE * 8);
    int bit_left = INSTALL_NR_SECTS;
    int cur_sect = bit_offset / (SECTOR_SIZE * 8);
    RD_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);
    while (bit_left) {
        int byte_off = bit_off_in_sect / 8;
        /* this line is ineffecient in a loop, but I don't care */
        fsbuf[byte_off] |= 1 << (bit_off_in_sect % 8);
        bit_left--;
        bit_off_in_sect++;
        if (bit_off_in_sect == (SECTOR_SIZE * 8)) {
            WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);
            cur_sect++;
            RD_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);
            bit_off_in_sect = 0;
        }
    }
    WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect);

    /***********************/
    /*        inodes       */
    /***********************/
    memset(fsbuf, 0x0, SECTOR_SIZE);
    struct inode *pi = (struct inode *)fsbuf;
    pi->i_mode = I_DIRECTORY;
    pi->i_size = DIR_ENTRY_SIZE * 5; // 5 files
    pi->i_start_sect = sb.n_1st_sect;
    pi->i_nr_sects = NR_DEFAULT_FILE_SECTS;
    
    for (int i = 0; i < NR_CONSOLES; i++) {
        pi = (struct inode *)(fsbuf + (INODE_SIZE * (i + 1)));
        pi->i_mode = I_CHAR_SPECIAL;
        pi->i_size = 0;
        pi->i_start_sect = MAKE_DEV(DEV_CHAR_TTY, i);
        pi->i_nr_sects = 0;
    }
    /* inode of `/cmd.tar' */
    pi = (struct inode*)(fsbuf + (INODE_SIZE * (NR_CONSOLES + 1)));
    pi->i_mode = I_REGULAR;
    pi->i_size = INSTALL_NR_SECTS * SECTOR_SIZE;
    pi->i_start_sect = INSTALL_START_SECT;
    pi->i_nr_sects = INSTALL_NR_SECTS;
    WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + sb.nr_smap_sects);

    /***********************/
    /*         '/'         */
    /***********************/
    memset(fsbuf, 0x0, SECTOR_SIZE);
    struct dir_entry *pde = (struct dir_entry *)fsbuf;

    pde->inode_nr = 1;
    strcpy(pde->name, ".");

    for (int i = 0; i < NR_CONSOLES; i++) {
        pde++;
        pde->inode_nr = i + 2;
        sprintf(pde->name, "dev_tty%d", i);
    }
    (++pde)->inode_nr = NR_CONSOLES + 2;
    strcpy(pde->name, "cmd.tar");
    WR_SECT(ROOT_DEV, sb.n_1st_sect);
}
Example #26
0
/**
 * Allocate a bit in sector-map.
 * 
 * @param dev  In which device the sector-map is located.
 * @param nr_sects_to_alloc  How many sectors are allocated.
 * 
 * @return  The 1st sector nr allocated.
 *****************************************************************************/
PRIVATE int alloc_smap_bit(int dev, int nr_sects_to_alloc)
{
	/* int nr_sects_to_alloc = NR_DEFAULT_FILE_SECTS; */

	int i; /* sector index */
	int j; /* byte index */
	int k; /* bit index */

	struct super_block * sb = get_super_block(dev);

	int smap_blk0_nr = 1 + 1 + sb->nr_imap_sects;
	int free_sect_nr = 0;

	for (i = 0; i < sb->nr_smap_sects; i++) { /* smap_blk0_nr + i :
						     current sect nr. */
		RD_SECT(dev, smap_blk0_nr + i);

		/* byte offset in current sect */
		for (j = 0; j < SECTOR_SIZE && nr_sects_to_alloc > 0; j++) {
			k = 0;
			if (!free_sect_nr) {
				/* loop until a free bit is found */
				if (fsbuf[j] == 0xFF) continue;
				for (; ((fsbuf[j] >> k) & 1) != 0; k++) {}
				free_sect_nr = (i * SECTOR_SIZE + j) * 8 + k - 1 + sb->n_1st_sect;
				if (free_sect_nr + nr_sects_to_alloc > sb->nr_sects) {
					/* FIXME: instead of halting the system,
					 *        telling the caller to handle this
					 *        will be better
					 */
					panic("disk is full");
				}
			}

			for (; k < 8; k++) { /* repeat till enough bits are set */
				assert(nr_sects_to_alloc > 0);

				/*
				 * this assert will fail if the disk is full
				 * (we would be overwriting "cmd.tar" to
				 *  create the new file)
				 *
				 * for example, if we have a 80MB hard disk,
				 * we may not be able to create more than 14
				 * regulare files
				 *
				 * @see doc/README::"cmd.tar" for details
				 */
				assert(((fsbuf[j] >> k) & 1) == 0);

				fsbuf[j] |= (1 << k);
				if (--nr_sects_to_alloc == 0)
					break;
			}
		}

		if (free_sect_nr) /* free bit found, write the bits to smap */
			WR_SECT(dev, smap_blk0_nr + i);

		if (nr_sects_to_alloc == 0)
			break;
	}

	assert(nr_sects_to_alloc == 0);

	return free_sect_nr;
}
Example #27
0
/**
 * <Ring 1> This routine handles the DEV_LOG message.
 * 
 * @param p  Ptr to the MESSAGE.
 *****************************************************************************/
PUBLIC int disklog(char * logstr)
{
	int device = root_inode->i_dev;
	struct super_block * sb = get_super_block(device);
	int nr_log_blk0_nr = sb->nr_sects - NR_SECTS_FOR_LOG; /* 0x9D41-0x800=0x9541 */

	static int pos = 0;
	if (!pos) { /* first time invoking this routine */

#ifdef SET_LOG_SECT_SMAP_AT_STARTUP
		/*
		 * set sector-map so that other files cannot use the log sectors
		 */

		int bits_per_sect = SECTOR_SIZE * 8; /* 4096 */

		int smap_blk0_nr = 1 + 1 + sb->nr_imap_sects; /* 3 */
		int sect_nr  = smap_blk0_nr + nr_log_blk0_nr / bits_per_sect; /* 3+9=12 */
		int byte_off = (nr_log_blk0_nr % bits_per_sect) / 8; /* 168 */
		int bit_off  = (nr_log_blk0_nr % bits_per_sect) % 8; /* 1 */
		int sect_cnt = NR_SECTS_FOR_LOG / bits_per_sect + 2; /* 1 */
		int bits_left= NR_SECTS_FOR_LOG; /* 2048 */

		int i;
		for (i = 0; i < sect_cnt; i++) {
			RD_SECT(device, sect_nr + i); /* RD_SECT(?, 12) */

			for (; byte_off < SECTOR_SIZE && bits_left > 0; byte_off++) {
				for (; bit_off < 8; bit_off++) { /* repeat till enough bits are set */
					assert(((fsbuf[byte_off] >> bit_off) & 1) == 0);
					fsbuf[byte_off] |= (1 << bit_off);
					if (--bits_left  == 0)
						break;
				}
				bit_off = 0;
			}
			byte_off = 0;
			bit_off = 0;

			WR_SECT(device, sect_nr + i);

			if (bits_left == 0)
				break;
		}
		assert(bits_left == 0);
#endif /* SET_LOG_SECT_SMAP_AT_STARTUP */

		pos = 0x40;

#ifdef MEMSET_LOG_SECTS
		/* write padding stuff to log sectors */
		int chunk = min(MAX_IO_BYTES, FSBUF_SIZE >> SECTOR_SIZE_SHIFT);
		assert(chunk == 256);
		int sects_left = NR_SECTS_FOR_LOG;
		for (i = nr_log_blk0_nr;
		     i < nr_log_blk0_nr + NR_SECTS_FOR_LOG;
		     i += chunk) {
			memset(fsbuf, 0x20, chunk*SECTOR_SIZE);
			rw_sector(DEV_WRITE,
				  device,
				  i * SECTOR_SIZE,
				  chunk * SECTOR_SIZE,
				  TASK_FS,
				  fsbuf);
			sects_left -= chunk;
		}
		if (sects_left != 0)
			panic("sects_left should be 0, current: %d.", sects_left);
#endif /* MEMSET_LOG_SECTS */
	}
Example #28
0
/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  alloc_zone
 *  Description:  alloc zone
 *  @param dev :  In which device the sector-map is located.
 *  @param alloc_start: the start sect of the buf
 *  @param alloc_nr:	the amount of the sect of the buf
 *  @param i_zone: the	zone of the inode
 *	@return:			the amount of allocated zones
 * =====================================================================================
 */
PRIVATE	int
alloc_zone (int dev, int alloc_start, int alloc_nr, zone_t * i_zone)
{
	int i;
	int flag_no_zone = 0;
	int nr_sect = alloc_start + alloc_nr;

	if (alloc_start < NR_DIRECT_ZONE) {
		//the sectors are only in the direct zone
		int flag_direct_zone = 1;

		//asumpt the amount of the sect is less than direct zone
		int direct_alloc_nr = alloc_nr;
		if (nr_sect > NR_DIRECT_ZONE) {
			//the amount of sects is less than the direct zone
			flag_direct_zone = 0;
			direct_alloc_nr = NR_DIRECT_ZONE - alloc_start;
			alloc_nr -= direct_alloc_nr;
		}
		for (i = 0; i < direct_alloc_nr; i++) {
			if (NO_ZONE == i_zone[alloc_start + i]) {
				alloc_sect(dev, &i_zone[alloc_start + i]);
			}
		}
		if (flag_direct_zone) {
			return nr_sect - alloc_start;
		}
	}

	//the first level indirect zone
	zone_t sectors[NR_ZONE_PER_SECT];

	if (alloc_start < NR_SECOND_LEVEL_ZONE) {
		int second_level_start = NR_DIRECT_ZONE;
		if (alloc_start > second_level_start) {
			second_level_start = alloc_start;
		}

		//the sectors are only reach the second level
		int flag_second_level = 1;
		int second_alloc_nr = alloc_nr;
		if (nr_sect > NR_SECOND_LEVEL_ZONE) {
			//the amount of sects is less than the second level zone
			flag_second_level = 0;
			second_alloc_nr = NR_SECOND_LEVEL_ZONE - second_level_start;
			alloc_nr -= second_alloc_nr;
		}

		//get the begin and end in second level zone
		second_level_start -= NR_DIRECT_ZONE;

		//if the inode has second level zone
		flag_no_zone = 0;
		if (NO_ZONE == i_zone[SECOND_LEVEL_ZONE]) {
			//the second level zone is not available yet
			alloc_sect(dev, &i_zone[SECOND_LEVEL_ZONE]);
			flag_no_zone = 1;
		}

		RD_SECT(dev, i_zone[SECOND_LEVEL_ZONE]);
		memcpy((void *)sectors,
				(void *)fsbuf,
				NR_SECT_PER_SECOND_LEVEL_ZONE * sizeof(int) );

		if (flag_no_zone) {
			for (i = 0; i < NR_SECT_PER_SECOND_LEVEL_ZONE; i++) {
				sectors[i] = NO_ZONE;
			}
		}

		for (i = 0; i < second_alloc_nr; i++) {
			if (NO_ZONE == sectors[second_level_start + i]) {
				alloc_sect(dev, &sectors[second_level_start + i]);
			}
		}

		//sync to disk
		memcpy((void *)fsbuf,
				(void *)sectors,
				NR_SECT_PER_SECOND_LEVEL_ZONE * sizeof(int) );
		WR_SECT(dev, i_zone[SECOND_LEVEL_ZONE]);

		//if the zones only reach second level
		if (flag_second_level) {
			return nr_sect - alloc_start;
		}
	} 

	if (alloc_start < NR_THIRD_LEVEL_ZONE) {
		//less than the third level indirect zone
		int third_level_start = NR_SECOND_LEVEL_ZONE;
		if (alloc_start > third_level_start) {
			third_level_start = alloc_start;
		}
		//the sectors are only reach the third level
		int flag_third_level = 1;
		int third_alloc_nr = alloc_nr;
		if (nr_sect > NR_THIRD_LEVEL_ZONE) {
			//the amount of sects is less than the third level zone
			flag_third_level = 0;
			third_alloc_nr = NR_THIRD_LEVEL_ZONE - third_level_start;
			alloc_nr -= third_alloc_nr;
		}

		//get the start and end in third level zone
		third_level_start -= NR_SECOND_LEVEL_ZONE;

		//if the inode has third level zone
		flag_no_zone = 0;
		if (NO_ZONE == i_zone[THIRD_LEVEL_ZONE]) {
			//the third level zone is not available yet
			alloc_sect(dev, &i_zone[THIRD_LEVEL_ZONE]);
			flag_no_zone = 1;
		}

		RD_SECT(dev, i_zone[THIRD_LEVEL_ZONE]);
		memcpy((void *)sectors,
				(void *)fsbuf,
				NR_ZONE_PER_SECT * sizeof(int) );

		if (flag_no_zone) {
			for (i = 0; i < NR_ZONE_PER_SECT; i++) {
				sectors[i] = NO_ZONE;
			}
		}

		int current_second_level_zone = NO_ZONE;
		zone_t current_zones[NR_ZONE_PER_SECT];
		for (i = 0; i < third_alloc_nr; i++) {
			int second_level_index	=
				(third_level_start + i) /
				NR_SECT_PER_SECOND_LEVEL_ZONE;
			int third_level_index = 
				(third_level_start + i) % 
				NR_SECT_PER_SECOND_LEVEL_ZONE;

			if (NO_ZONE == current_second_level_zone
					|| current_second_level_zone != second_level_index){

				if (NO_ZONE != current_second_level_zone) {
					//the previous zone is done for writing
					//sync to disk
					memcpy((void *)fsbuf,
							(void *)current_zones,
							NR_ZONE_PER_SECT * sizeof(int) );
					WR_SECT(dev, current_second_level_zone);
				}

				//the second level zone is a slot
				flag_no_zone = 0;
				if (NO_ZONE == sectors[second_level_index]) {
					flag_no_zone = 1;
					alloc_sect(dev, &sectors[second_level_index]);
				}
				current_second_level_zone = sectors[second_level_index];

				RD_SECT(dev, sectors[second_level_index]);
				memcpy((void *)current_zones,
						(void *)fsbuf,
						NR_ZONE_PER_SECT * sizeof(int) );

				//if the second level zone is a slot, get to init
				if (flag_no_zone) {
					for (i = 0; i < NR_ZONE_PER_SECT; i++) {
						current_zones[i] = NO_ZONE;
					}
				}
			}
			if (NO_ZONE == current_zones[third_level_index]) {
				alloc_sect(dev, &current_zones[third_level_index]);
			}
		}

		//sync the rest second level zone to disk
		if (NO_ZONE != current_second_level_zone) {
			//the previous zone is done for writing
			//sync to disk
			memcpy((void *)fsbuf,
					(void *)current_zones,
					NR_ZONE_PER_SECT * sizeof(int) );
			WR_SECT(dev, current_second_level_zone);
		}

		//sync to disk
		memcpy((void *)fsbuf,
				(void *)sectors,
				NR_ZONE_PER_SECT * sizeof(int) );
		WR_SECT(dev, i_zone[THIRD_LEVEL_ZONE]);

		//if the zones only reach third level
		if (flag_third_level) {
			return nr_sect - alloc_start;
		}
		
	}

	if (nr_sect > NR_THIRD_LEVEL_ZONE) {
		//do not support zones larger than third level
		panic("file is too large");
	}

	return -1;
}		/* -----  end of function alloc_zone  ----- */
Example #29
0
/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  rdwt_zones
 *  Description:  read of write the buf to the zones
 *  @param pos:	  the current position in the file
 *  @param buf_len:		the length of the buf
 *  @param src:			the source of the buf
 *  @param buf:			the buf should be read or written
 *  @param i_nr_sects:	the current amount of the sects of the file
 *  @param i_zone:		the i_zone of this inode
 *  @param mode:		READ or WRITE
 *  @return :			how many bytes writed or read
 * =====================================================================================
 */
PRIVATE int
rdwt_zones ( int pos, int len, int src, char * buf, struct inode * pin, int mode)
{
	//check if the mode is right
	assert(WRITE == mode || READ == mode);

	int i;
	int align = 0;
	int pos_end = pos + len;

	//larger than file in read mode
	if (READ == mode) {
		if (pos > pin->i_size) {
			//read start is larger than the file, get nothing
			return 0;
		} else if (pos_end > pin->i_size) {
			//read end is larger than the file, just end at the EOF
			len -= (pos_end - pin->i_size);
			pos_end = pin->i_size;
		}
	}

	//how many sects does the buf need to take
	int nr_sect_start = pos >> SECTOR_SIZE_SHIFT;
	int nr_rw_sect = len >> SECTOR_SIZE_SHIFT;
	int off = pos_end % SECTOR_SIZE;

	//if the buf is not n * SECTOR_SIZE, just give one more sector
	if (off > 0) {
		nr_rw_sect ++;
	}

	int nr_sect = nr_sect_start + nr_rw_sect;

	//if the sects in the file is not enough
	if (nr_sect > pin->i_nr_sects) {
		//allocate the sectors that needed
		assert(WRITE == mode);
		u32 zone_amount = alloc_zone(pin->i_dev, pin->i_nr_sects, nr_sect - pin->i_nr_sects, pin->i_zone);
		assert(nr_sect - pin->i_nr_sects == zone_amount);
		pin->i_nr_sects += zone_amount;
	}

	if (nr_sect_start < NR_DIRECT_ZONE) {
		//the sectors are only in the direct zone
		int flag_direct_zone = 1;

		//asumpt the amount of the sect is less than direct zone
		int direct_nr_rw_sect = nr_rw_sect;
		if (nr_sect > NR_DIRECT_ZONE) {
			//the amount of sects is more than the direct zone
			flag_direct_zone = 0;
			direct_nr_rw_sect = NR_DIRECT_ZONE - nr_sect_start;
			nr_rw_sect -= direct_nr_rw_sect;
		}
		for (i = 0; i < direct_nr_rw_sect; i++, align++) {
			if (WRITE == mode) {
  				phys_copy((void*)va2la(TASK_FS, fsbuf),
						(void*)va2la(src, buf + align * SECTOR_SIZE),
						SECTOR_SIZE);
				WR_SECT(pin->i_dev, pin->i_zone[nr_sect_start + i]);
			} else if (READ == mode) {
				RD_SECT(pin->i_dev, pin->i_zone[nr_sect_start + i]);
				phys_copy((void*)va2la(src, buf + align * SECTOR_SIZE),
						(void*)va2la(TASK_FS, fsbuf),
						SECTOR_SIZE);
			}
		}
		if (flag_direct_zone) {
			return len;
		}
	}

	//the first level indirect zone
	zone_t sectors[NR_ZONE_PER_SECT];

	if (nr_sect_start < NR_SECOND_LEVEL_ZONE) {
		int second_level_start = NR_DIRECT_ZONE;
		if (nr_sect_start > second_level_start) {
			second_level_start = nr_sect_start;
		}
		//the sectors are only reach the second level
		int flag_second_level = 1;
		int second_nr_rw_sect = nr_rw_sect;
		if (nr_sect > NR_SECOND_LEVEL_ZONE) {
			//the amount of sects is more than the second level zone
			flag_second_level = 0;
			second_nr_rw_sect = NR_SECOND_LEVEL_ZONE - second_level_start;
			nr_rw_sect -= second_nr_rw_sect;
		}

		//get the begin and end in second level zone
		second_level_start -= NR_DIRECT_ZONE;

		RD_SECT(pin->i_dev, pin->i_zone[SECOND_LEVEL_ZONE]);
		memcpy((void *)sectors,
				(void *)fsbuf,
				NR_ZONE_PER_SECT * sizeof(int) );

		for (i = 0; i < second_nr_rw_sect; i++, align++) {
            if (WRITE == mode) {
                phys_copy((void*)va2la(TASK_FS, fsbuf),
                        (void*)va2la(src, buf + align * SECTOR_SIZE),
                        SECTOR_SIZE);
                WR_SECT(pin->i_dev, sectors[second_level_start + i]);
            } else if(READ == mode) {
                RD_SECT(pin->i_dev, sectors[second_level_start + i]);
                phys_copy((void*)va2la(src, buf + align * SECTOR_SIZE),
                        (void*)va2la(TASK_FS, fsbuf),
                        SECTOR_SIZE);
            }

		}

		//if the zones only reach second level
		if (flag_second_level) {
			return len;
		}
	} 

	if (nr_sect_start < NR_THIRD_LEVEL_ZONE) {
		//less than the third level indirect zone
		int third_level_start = NR_SECOND_LEVEL_ZONE;
		if (nr_sect_start > third_level_start) {
			third_level_start = nr_sect_start;
		}
		//the sectors are only reach the third level
		int flag_third_level = 1;
		int third_nr_rw_sect = nr_rw_sect;
		if (nr_sect > NR_THIRD_LEVEL_ZONE) {
			//the amount of sects is more than the third level zone
			flag_third_level = 0;
			third_nr_rw_sect = NR_THIRD_LEVEL_ZONE - third_level_start;
			nr_rw_sect -= third_nr_rw_sect;
		}

		//get the start and end in third level zone
		third_level_start -= NR_SECOND_LEVEL_ZONE;

		RD_SECT(pin->i_dev, pin->i_zone[THIRD_LEVEL_ZONE]);
		memcpy((void *)sectors,
				(void *)fsbuf,
				NR_ZONE_PER_SECT * sizeof(int) );

		int current_second_level_zone = NO_ZONE;
		zone_t current_zones[NR_ZONE_PER_SECT];
		for (i = 0; i < third_nr_rw_sect; i++, align++) {
			int second_level_index	=
				(third_level_start + i) /
				NR_SECT_PER_SECOND_LEVEL_ZONE;
			int third_level_index = 
				(third_level_start + i) %
				NR_SECT_PER_SECOND_LEVEL_ZONE;

			if (NO_ZONE == current_second_level_zone
					|| current_second_level_zone != sectors[second_level_index]){
				RD_SECT(pin->i_dev, sectors[second_level_index]);
				memcpy((void *)current_zones,
						(void *)fsbuf,
						NR_ZONE_PER_SECT * sizeof(int) );
			}

			//record the current second level zone for compare in next time
			//to comfirm if that the current second level zone is finished
			current_second_level_zone = sectors[second_level_index];

            if (WRITE == mode) {
                phys_copy((void*)va2la(TASK_FS, fsbuf),
                        (void*)va2la(src, buf + align * SECTOR_SIZE),
                        SECTOR_SIZE);
                WR_SECT(pin->i_dev, current_zones[third_level_index]);
            } else if(READ == mode) {
                RD_SECT(pin->i_dev, current_zones[third_level_index]);
                phys_copy((void*)va2la(src, buf + align * SECTOR_SIZE),
                        (void*)va2la(TASK_FS, fsbuf),
                        SECTOR_SIZE);
            }

		}

		//if the zones only reach third level
		if (flag_third_level) {
			return len;
		}
	}

	if (nr_sect > NR_THIRD_LEVEL_ZONE) {
		//do not support zones larger than third level
		panic("buf is too large");
	}

	return -1;
}		/* -----  end of function rdwt_zones  ----- */