예제 #1
0
void Unmount(void)
{
/*
 * precondition		: usage ) Unmount(void);
 * postcondition	: 가상 디스크의 파일 시스템을 종료한다.
 * 					  메모리상에 있는 버퍼에 변경된 데이터와 메타데이터를 디스크와
 * 					  동기화 하고 언마운트 한다.
 */
	int i = 0;
	Buf* pBuf = NULL;

	// fileSysInfo 갱신
	pBuf = BufRead(0);
	BufWrite(pBuf, &fileSysInfo, sizeof(fileSysInfo) - sizeof(char*) * 2);
	// fileSysInfo.pInodeBitmap 갱신
	for ( i = fileSysInfo.inodeBitmapStart ; i < fileSysInfo.inodeBitmapStart + inodeBitmapSize ; i++ )
	{
		pBuf = BufRead(i);
		BufWrite(pBuf, fileSysInfo.pInodeBitmap + (i - fileSysInfo.inodeBitmapStart) * BLOCK_SIZE, 512);
	}
	// fileSysInfo.pBlockBitmap 갱신
	for ( i = fileSysInfo.blockBitmapStart ; i < fileSysInfo.blockBitmapStart + blockBitmapSize ; i++ )
	{
		pBuf = BufRead(i);
		BufWrite(pBuf, fileSysInfo.pBlockBitmap + (i - fileSysInfo.blockBitmapStart) * BLOCK_SIZE, 512);
	}
	BufSync();
}
예제 #2
0
void ReadDirBlock(DirBlock* dirBlock, int blockNo)
{
/*
 * precondition		:
 * postcondition	: 인자 blockNo는 block number이다.
 * 					  해당 block number의 block을 디스크에서 읽어 온다.
 */
	Buf* pBuf = NULL;

	pBuf = BufRead(blockNo);
	memcpy(dirBlock, (DirBlock*)pBuf->pMem, sizeof(DirBlock));
}
예제 #3
0
void WriteDirBlock(DirBlock* dirBlock, int blockNo)
{
/*
 * precondition		:
 * postcondition	: 인자 blockNo는 dirBlock의 block number이다.
 * 					  dirBlock을 디스크에 저장한다.
 */
	Buf* pBuf = NULL;

	pBuf = BufRead(blockNo);
	BufWrite(pBuf, dirBlock, sizeof(DirBlock));
}
예제 #4
0
static int __find_dentry_and_remove(tiny_inode* out_inode, 
		tiny_inode *parent_inode, const char *entry_name)
{
	int qid = OpenMQ(5000);
	tiny_dirblk *dirblk;
	tiny_dentry *dentry;
	Buf *buf;
	int i, j;
	int isEmpty = 1;
	int find = 0;
	int dirblkno;
	int parent_inodeno;
	int target_inodeno;

	for (i = 0; i < parent_inode->i_nblk; i++) {
		buf = BufRead(parent_inode->i_block[i]);
		dirblk = __get_dirblk_from_buf(buf);
		dirblkno = parent_inode->i_block[i];

		isEmpty = 1;
		for (j = 0; j < NUM_OF_DIRENT_IN_1BLK; j++) {
			dentry = &dirblk->dirEntries[j];

			if ( i == 0 && j == 0 ) {
				parent_inodeno = dentry[0].inodeNum;
			}

			if (strncmp(entry_name, dentry->name, NAME_LEN_MAX) == 0) {
				ReadInode(out_inode, dentry->inodeNum);
				strncpy(dentry->name, "", NAME_LEN_MAX);
				target_inodeno = dentry->inodeNum;

				find = 1;
			} else if (strncmp(dentry->name, "", NAME_LEN_MAX) != 0) {
				isEmpty = 0;
			}
		}

		if (find) {
			if (isEmpty) {
				SetBlockAllocToFree(dirblkno);
				parent_inode->i_block[i] =
					parent_inode->i_block[--parent_inode->i_nblk];
				WriteInode(parent_inode, parent_inodeno);
			} else {
				WriteDirBlock(dirblk, dirblkno);
			}
			return target_inodeno;
		}
	}

	return -1;
}
예제 #5
0
int ReadFile(int fileDesc, char* pBuffer, int length)
{
/*
 * precondition		: usage) ReadFile(fileDesc, pBuffer, length);
 *					  fileDesc	: file descriptor
 *					  pBuffer	: 저장할 데이터를 포함하는 메모리의 주소
 *					  length	: 저장될 데이터의 길이
 * postcondition	: open된 파일에서 데이터를 읽는다.
 * 					  성공하면 읽은 데이터의 길이 값을 리턴한다. 실패 했을때는 -1을 리턴한다.
 */
	int i = 0, j = 0;
	int	block = fileDescTable.file[fileDesc].offset / BLOCK_SIZE;
	int offset = fileDescTable.file[fileDesc].offset % BLOCK_SIZE;
	int exsist = 0;
	int	wrote = length;
	Buf* pBuf = NULL;
	InodeInfo	inodeInfo;
	DirBlock	dirBlock;

	ReadInode(&inodeInfo, fileDescTable.file[fileDesc].inodeNo);

	// 첫번째 블락에서 data 읽고 pBuffer에 적재
	pBuf = BufRead(inodeInfo.i_block[block]);
	memcpy(pBuffer, (char*)pBuf->pMem + offset, BLOCK_SIZE - offset);
	wrote = length < BLOCK_SIZE - offset ? length : BLOCK_SIZE - offset ;
	fileDescTable.file[fileDesc].offset = wrote;
	if ( length <= 512 )		return wrote;
	// 두번째 블락부터 data 읽고 pBuffer에 적재
	for ( j = block + 1 ; j < (length / BLOCK_SIZE) + block ; j++ )
	{
		if (NUM_OF_INDIRECT_BLOCK == j)
			return  wrote;	// indirect block 12개가 모두 사용중이면 write한 만큼만 리턴
		pBuf = BufRead(inodeInfo.i_block[j]);
		memcpy(pBuffer + BLOCK_SIZE * ((j - (block + 1)) + 1), pBuf->pMem, length - wrote > BLOCK_SIZE ? BLOCK_SIZE : length - wrote);
		wrote = wrote + (length - wrote > BLOCK_SIZE ? BLOCK_SIZE : length - wrote);
		fileDescTable.file[fileDesc].offset = wrote;
		if ( wrote == length )	return wrote;
	}
}
예제 #6
0
void ReadInode(InodeInfo* inodeInfo, int inodeNo)
{
/*
 * precondition		:
 * postcondition	: 인자 inodeNo는 inode number이다.
 * 					  해당 inode number를 가진 inodeInfo를 디스크에서 읽어온다.
 */
	Buf* pBuf = NULL;
	InodeInfo* pMem = NULL;
	int block = fileSysInfo.inodeListStart + inodeNo / NUM_OF_INODE_IN_1BLK;	// inodeNo가 위치한 블럭
	int inode = inodeNo % NUM_OF_INODE_IN_1BLK;	// 해당 block에서 inode가 위치한 순서

	pBuf = BufRead(block);
	pMem = pBuf->pMem;
	pMem = pMem + inode;
	memcpy(inodeInfo, pMem/*(InodeInfo*)pBuf->pMem + inode*/, sizeof(InodeInfo));
}
예제 #7
0
void WriteInode(InodeInfo* inodeInfo, int inodeNo)
{
/*
 * precondition		:
 * postcondition	: 인자 inodeNo는 inodeInfo의 inode number이다.
 * 					  inodeInfo를 디스크에 저장한다.
 */
	Buf* pBuf = NULL;
	void* pMem = malloc(BLOCK_SIZE);
	InodeInfo* pCur = pMem;
	int block = fileSysInfo.inodeListStart + inodeNo / NUM_OF_INODE_IN_1BLK;
	int inode = inodeNo % NUM_OF_INODE_IN_1BLK;

	pBuf = BufRead(block);
	memcpy(pMem, pBuf->pMem, BLOCK_SIZE);
	pCur = pCur + inode;
	memcpy(pCur, inodeInfo, sizeof(InodeInfo));
	BufWrite(pBuf, pMem, BLOCK_SIZE);
	free(pMem);
}
예제 #8
0
파일: hw2.c 프로젝트: dayomi/Homework-1
void BufWrite(int blkno, void* pData)
{
	Buf* pBuf;

	pBuf = BufFind(blkno);
	if( pBuf == NULL )
	{
		char ptr_tmp_data[BLOCK_SIZE];
		BufRead(blkno, ptr_tmp_data);
		pBuf = BufFind(blkno);
	}

	removeClean(blkno);
	if( ! existDirty(blkno) )
	{
		insertDirty(pBuf);
	}
	removeLru(blkno);
	insertLru(pBuf);

	copyBlock((char*)pData, (char*)pBuf->pMem);
}
예제 #9
0
void Mount(MountType type)
{
/*
 * precondition		: usage ) Mount(MT_TYPE_FORMAT);
 * postcondition	: 가상 디스크의 파일 시스템을 초기화 한다.
 * 					  (1) MT_TYPE_FORMAT : 가상 디스크, 즉, 디스크를 에뮬레이션할 파일을 생성하고,
 * 										   그 파일을 파일 시스템이 인식할 수 있도록 organize 함.
 * 										   즉, 디스크 포맷처럼 가상 디스크 역할을 담당하는 파일 내에
 * 										   superblock, inode bitmap, block bitmap, inode list
 * 										   등을 초기화한다. 이때, 생성될 가상디스크의 크기는 10MB로 한다.
 * 					  (2) MT_TYPE_READWRITE : MT_TYPE_FORMAT과 달리 가상 디스크를 포맷하지 않으며,
 * 											  파일 시스템 unmount 되기 이전의 디스크 사용 상태를 유지시키면서
 * 											  파일 시스템을 초기화한다. 이때, 내부적으로 가상 디스크용 파일을
 * 											  리눅스의 “open” system call을 사용하여 파일 열기를 수행하며,
 * 											  file system info, inode bitmap, block bitmap을
 * 											  정의된 in-memory data structure에 load한다.
 */
	int i = 0;
	Buf* pBuf = NULL;
	InodeInfo	inodeInfo;
	DirBlock	dirBlock;

//////////////////////////////////////////////////////////////////////
// 모두 block 단위임
	inodeBitmapSize = (FS_INODE_COUNT / 8/*1byte*/ / BLOCK_SIZE == 0) ? 1 : (int)(ceil((double)FS_INODE_COUNT / (double)8 / (double)BLOCK_SIZE));// FS_INODE_COUNT / 8/*1byte*/ / BLOCK_SIZE + 1;	// block 단위
	inodeListSize = (int)(ceil((double)FS_INODE_COUNT / (double)NUM_OF_INODE_IN_1BLK)); // block 단위
	dataRegionSize = (FS_DISK_CAPACITY / BLOCK_SIZE - 1/*FileSysInfo block*/ /* - 1*//*BlockBitmap block*/
						- (double)inodeBitmapSize - (double)inodeListSize);
	blockBitmapSize = ceil(dataRegionSize / 8/*1byte*/ / BLOCK_SIZE);	// block 단위
	dataRegionSize = dataRegionSize - blockBitmapSize;
//
//////////////////////////////////////////////////////////////////////
	memset(&fileDescTable, NULL, sizeof(FileDescTable));
	Init();			// 버퍼캐시 생성 및 초기화

	switch(type)
	{
	case MT_TYPE_FORMAT:
		DevInit();		// 디스크 초기화
		fileSysInfo.blocks = BLOCK_SIZE;
		fileSysInfo.rootInodeNum = 0; // 수정해야함
		fileSysInfo.diskCapacity = dataRegionSize;	// 수퍼블락을 제외한 순수 data rigion의 블록사이즈
		fileSysInfo.numAllocBlocks = 0;
		fileSysInfo.numFreeBlocks = fileSysInfo.diskCapacity;
		fileSysInfo.numInodes = FS_INODE_COUNT;
		fileSysInfo.numAllocInodes = 0;
		fileSysInfo.numFreeInodes = FS_INODE_COUNT;
		fileSysInfo.inodeBitmapStart = 1; // inode bitmap이 저장된 블록번호
		fileSysInfo.blockBitmapStart = fileSysInfo.inodeBitmapStart + inodeBitmapSize; // block bitmap이 저장된 블록 번호
		fileSysInfo.inodeListStart = fileSysInfo.blockBitmapStart + blockBitmapSize; // inode list를 저장하는 영역의 시작 블록 번호
		fileSysInfo.dataStart = fileSysInfo.inodeListStart + inodeListSize; // data region의 시작 블록 번호
		fileSysInfo.pInodeBitmap = malloc(inodeBitmapSize * BLOCK_SIZE);
		fileSysInfo.pBlockBitmap = malloc((int)blockBitmapSize * BLOCK_SIZE);

		memset(fileSysInfo.pInodeBitmap, 0xFF, inodeBitmapSize * BLOCK_SIZE);
		memset(fileSysInfo.pBlockBitmap, 0xFF, (int)blockBitmapSize * BLOCK_SIZE);
		memset(&inodeInfo, 0x0, sizeof(InodeInfo));
		memset(&dirBlock, 0x0, sizeof(DirBlock));

	////////////////////////////////////////////////////
	// root 생성
	//
		// inode 데이터 대입
		inodeInfo.size = 0;
		inodeInfo.type = FILE_TYPE_DIR;
		inodeInfo.mode = FILE_MODE_READONLY;
		inodeInfo.blocks = 1;
		inodeInfo.i_block[0] = fileSysInfo.dataStart;

		// inode 저장
		pBuf = BufRead(fileSysInfo.inodeListStart);
		BufWrite(pBuf, &inodeInfo, sizeof(InodeInfo));
		// inode 사용현황 변경
		if ( SetInodeFreeToAlloc() == WRONG_VALUE )
			fprintf(stderr, "* SetInodeFreeToAlloc() error!\n");
		// Directory Block 생성
		strncpy(dirBlock.dirEntries[0].name, ".", NAME_LEN_MAX);
		dirBlock.dirEntries[0].inodeNum = 0;
		dirBlock.dirEntries[0].type = FILE_TYPE_DIR;
		// dir block 저장
		pBuf = BufRead(fileSysInfo.dataStart);
		BufWrite(pBuf, &dirBlock, sizeof(DirBlock));
		// block 사용현황 변경
		if ( SetBlockFreeToAlloc() == WRONG_VALUE )
			fprintf(stderr, "* SetBlockFreeToAlloc() error!\n");
	//
	////////////////////////////////////////////////////
		break;

	case MT_TYPE_READWRITE:			// 버퍼캐시 생성 및 초기
		DevLoad();		// 디스크 로
		pBuf = BufRead(0);	/* FileSysInfo */
		memcpy(&fileSysInfo, pBuf->pMem, sizeof(fileSysInfo) - sizeof(char*) * 2 /*포인터변수 2개*/);

		fileSysInfo.pInodeBitmap = malloc(inodeBitmapSize * BLOCK_SIZE);
		fileSysInfo.pBlockBitmap = malloc((int)blockBitmapSize * BLOCK_SIZE);
		memset(fileSysInfo.pInodeBitmap, NULL, inodeBitmapSize * BLOCK_SIZE);
		memset(fileSysInfo.pBlockBitmap, NULL, (int)blockBitmapSize * BLOCK_SIZE);

		// inodeBitmap 로드
		for ( i = fileSysInfo.inodeBitmapStart ; i < fileSysInfo.inodeBitmapStart + inodeBitmapSize ; i++ )
		{
			pBuf = BufRead(i);
			memcpy(fileSysInfo.pInodeBitmap + (i - fileSysInfo.inodeBitmapStart) * BLOCK_SIZE, pBuf->pMem, BLOCK_SIZE);
		}
		// blockBitmap 로드
		for ( i = fileSysInfo.blockBitmapStart ; i < fileSysInfo.blockBitmapStart + blockBitmapSize ; i++ )
		{
			pBuf = BufRead(i);
			memcpy(fileSysInfo.pBlockBitmap + (i - fileSysInfo.blockBitmapStart) * BLOCK_SIZE, pBuf->pMem, BLOCK_SIZE);
		}
		break;
	}
}
예제 #10
0
int WriteFile(int fileDesc, char* pBuffer, int length)
{
/*
 * precondition		: usage) WriteFile(fileDesc, pBuffer, length);
 *					  fileDesc	: file descriptor
 *					  pBuffer	: 저장할 데이터를 포함하는 메모리의 주소
 *					  length	: 저장될 데이터의 길이
 * postcondition	: open된 파일에 데이터를 저장한다.
 * 					  성공하면 저장된 데이터의 길이 값을 리턴한다. 실패 했을때는 -1을 리턴한다.
 */
	int i = 0, j = 0;
	int	block = fileDescTable.file[fileDesc].offset / BLOCK_SIZE;
	int offset = fileDescTable.file[fileDesc].offset % BLOCK_SIZE;
	int exsist = 0;
	int	remain = length;
	char buf[BLOCK_SIZE] = {NULL,};
	Buf* pBuf = NULL;
	InodeInfo	inodeInfo;
	DirBlock	dirBlock;

	if ( fileDescTable.file[fileDesc].valid_bit != 1 )
		return WRONG_VALUE;
	ReadInode(&inodeInfo, fileDescTable.file[fileDesc].inodeNo);

	// lseek 함수가 없기 때문에 inode에 저장된 indirect block 갯수보다
	// 위에서 계산된 block(fd[].offset / BLOCK_SIZE)이 클수가 없음
	// 따라서 예외처리 안해도 됨
	// 첫번째 블락에 pBuffer 쓰기
	pBuf = BufRead(inodeInfo.i_block[block]);
	memcpy(&buf, pBuf->pMem, BLOCK_SIZE);
	memcpy(&buf + offset, pBuffer, (remain + offset >= BLOCK_SIZE) ? BLOCK_SIZE - offset : remain);
	BufWrite(pBuf, &buf, BLOCK_SIZE);
	if ( inodeInfo.size < (remain - offset) )
		inodeInfo.size = remain - offset;
	fileDescTable.file[fileDesc].offset += (remain + offset >= BLOCK_SIZE) ? BLOCK_SIZE - offset : remain;
	remain -= (BLOCK_SIZE - offset);
	if ( remain <= 0 )		return length;
	// 두번째 블락부터 pBuffer 쓰기
	for ( j = block + 1 ; j < (length / BLOCK_SIZE + 1) + block ; j++ )
	{
		// inodeInfo.blocks가 모자르면 새로 할당해줘야함
		if ( j == inodeInfo.blocks && inodeInfo.blocks < NUM_OF_INDIRECT_BLOCK )
		{
			inodeInfo.i_block[inodeInfo.blocks++] = GetFreeBlock();
			SetBlockFreeToAlloc();
		}
		if ( j == NUM_OF_INDIRECT_BLOCK )
		{	// indirect block 부족으로 쓰기 실패
			WriteInode(&inodeInfo, fileDescTable.file[fileDesc].inodeNo);
			return length - remain;
		}
		pBuf = BufRead(inodeInfo.i_block[j]);
		BufWrite(pBuf, pBuffer + BLOCK_SIZE * ((j - (block + 1) + 1)), remain > BLOCK_SIZE ? BLOCK_SIZE : remain);
		fileDescTable.file[fileDesc].offset += (remain > BLOCK_SIZE ? BLOCK_SIZE : remain);
		remain = remain - BLOCK_SIZE;
		if ( remain <= 0 )
		{
			inodeInfo.size += BLOCK_SIZE + remain;
			WriteInode(&inodeInfo, fileDescTable.file[fileDesc].inodeNo);
			return length;
		}
		else
			inodeInfo.size += BLOCK_SIZE;
	}
	return 0;
}
예제 #11
0
int tiny_read(const char *path, char *buf, size_t size,
		off_t offset, struct fuse_file_info *fi)
{
	int qid = OpenMQ(5000);
	int target_inodeno = (int)fi->fh;
	tiny_inode target_inode;
	Buf* pBuf;
	int blkno_start = offset / BLOCK_SIZE;
	int blkno_end = (offset + size) / BLOCK_SIZE;
	int nblk_read = blkno_end - blkno_start + 1;

	int offset_in_blk_start = offset % BLOCK_SIZE;
	int offset_in_blk_end = (offset + size) % BLOCK_SIZE;
	int ntoread = 0;
	int nread = 0;
	int nread_cur = 0;
	int i;

	ReadInode(&target_inode, target_inodeno);

	ntoread = target_inode.i_size - offset;
	ntoread = ntoread > size ? size : ntoread;
	if (ntoread < 0) {
		return -EIO;
	}

	//TODO: read first block
	pBuf = BufRead( target_inode.i_block[blkno_start] );
	nread_cur = BLOCK_SIZE - offset_in_blk_start;
	if (nread_cur > ntoread)
		nread_cur = ntoread;
	memcpy( buf, pBuf->pMem + offset_in_blk_start, nread_cur);
	ntoread -= nread_cur;
	nread += nread_cur;
	if (ntoread == 0)
		goto read_all;

	if (nblk_read > 1) {
		//TODO: read middle blocks
		for (i = blkno_start + 1; i < blkno_end; i++) {
			pBuf = BufRead( target_inode.i_block[i] );
			nread_cur = BLOCK_SIZE;
			if (nread_cur > ntoread)
				nread_cur = ntoread;
			memcpy( buf + nread, pBuf->pMem, nread_cur);
			ntoread -= nread_cur;
			nread += nread_cur;

			if (ntoread == 0)
				goto read_all;
		}

		//TODO: read last block
		pBuf = BufRead( target_inode.i_block[blkno_end] );
		nread_cur = offset_in_blk_end;
		if (nread_cur > ntoread)
			nread_cur = ntoread;
		memcpy( buf + nread, pBuf->pMem, nread_cur);
		ntoread -= nread_cur;
		nread += nread_cur;
	}

read_all:

	if(qid < 0)
	{
		printf("q open fail\n");
		return ;
	}

	SuperBlk_t sb;
	sb.fsi = tiny_superblk;
	if(SendMQ(qid, MSG_SUPER_BLOCK, &sb) < 0)
	{
		printf("superblk send fail\n");
		return ;
	}

	InodeBitmap_t ibm;
	ibm.size = tiny_superblk.s_ninode / 8; /*byte*/
	memcpy(ibm.s_ibitmap_ptr, tiny_superblk.s_ibitmap_ptr, ibm.size);
	if(SendMQ(qid, MSG_INODE_BITMAP, &ibm) < 0)
	{
		printf("ibm send fail\n");
		return ;
	}

	BlockBitmap_t bbm;
	bbm.size = tiny_superblk.s_datablk_size / 8;  /*byte*/
	memcpy(bbm.s_dbitmap_ptr, tiny_superblk.s_dbitmap_ptr, bbm.size);
	if(SendMQ(qid, MSG_BLOCK_BITMAP, &bbm) < 0)
	{
		printf("bbm send fail\n");
		return ;
	}

	FileIO_t fio;
	memcpy(&fio.inode, &target_inode, sizeof(tiny_inode));
	fio.dentry.inodeNum = target_inodeno;
	fio.flag = 'r';
	fio.size = nread;
	if(SendMQ(qid, MSG_FILEIO, &fio) < 0)
	{
		printf("fio send fail\n");
		return ;
	}
	return nread;
}