※ 이 글은 Project 4를 구현중인 불확실과 추론의 영역입니다.
특히 이부분은 다른 곳을 구현하면서 수정할 여지가 높은 곳입니다.
착한 어린이들은 따라하지 마세요.
우선 inode_create부터 만들어보자. 이 함수는 인자로 받은 sector에 찾아가 inode_disk를 sector에 넣고 연속적으로 실제 데이터를 넣을 sector를 확보해놓는 것이다.
여기서 바꿀 곳은 free-map (bitmap)으로 빈 sector를 찾던 것을 FAT free block list로 바꾸고, 실제 data도 비연속할당으로 넣는 것이다.
/* Initializes an inode with LENGTH bytes of data and
* writes the new inode to sector SECTOR on the file system
* disk.
* Returns true if successful.
* Returns false if memory or disk allocation fails. */
bool inode_create(disk_sector_t sector, off_t length)
{
#ifdef EFILESYS
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
struct inode_disk *disk_inode = NULL;
bool success = false;
ASSERT(length >= 0);
/* If this assertion fails, the inode structure is not exactly
* one sector in size, and you should fix that. */
ASSERT(sizeof *disk_inode == DISK_SECTOR_SIZE);
disk_inode = calloc(1, sizeof *disk_inode);
if (disk_inode != NULL)
{
size_t sectors = bytes_to_sectors(length);
disk_inode->length = length;
disk_inode->magic = INODE_MAGIC;
// 남은 자유 블륵이 sectors보다 많은가
if (ctrl_free_blocks_EA(0) >= sectors)
{
disk_write(filesys_disk, sector, disk_inode);
if (sectors > 0)
{
static char zeros[DISK_SECTOR_SIZE];
size_t i;
// chain을 만든다.
disk_inode->start = fat_create_chain(0);
// 3.5 추가 >>
disk_write(filesys_disk, sector, disk_inode);
// << 3.5 추가
disk_sector_t prev = disk_inode->start;
for (i = 1; i < sectors; i++)
{
// 섹터가 2개 이상이면 chain으로 이어준다.
disk_sector_t sector_idx = fat_create_chain(prev);
disk_write(filesys_disk, sector_idx, zeros);
prev = sector_idx;
}
}
success = true;
}
free(disk_inode);
}
return success;
/* ---------------------------- << Project.4 FAT << ---------------------------- */
데이터의 계산은 메타데이터 (inode)를 뺀 실제 데이터인 것 같다. 그리고, inode_disk는 인자sector에 넣고, 따로 데이터를 넣을 공간을 할당받는다. length도 실질 데이터의 크기일 것이다.
sectors로 필요한 sector 갯수를 가져오고 fat_create_chain()으로 chain을 만들어준다.
사실 이건 disk_sector_t랑 cluster_t 같기 때문에 사용 가능하지, 아니라면 cluster_to_sector를 써야할 것이다.
하지만 나는 추잡한 사람이니 이렇게하겠다.
+++ 3/5 수정사항 +++
실 data의 첫 sector를 할당받고, 그 정보 (disk_inode->start) 를 inode에 써줘야한다.
inode_open()을 구현해보자.
우선 이 함수는 inode_disk를 꺼내서 inode를 하나 만든다. inode_disk가 들어있는 sector를 인자로 준다. 그리고 open_inode_list 안에 있으면 reopen을 한다.
그리고 inode_disk의 정보로 inode.data에 기입하는건데...
여기는 고칠 것이 없어보인다. 일단 패스
inode_reopen()도 마찬가지
inode_close()는 고칠게 많아 보인다. 시작해보자!
/* Closes INODE and writes it to disk.
* If this was the last reference to INODE, frees its memory.
* If INODE was also a removed inode, frees its blocks. */
void inode_close(struct inode *inode)
{
#ifdef EFILESYS
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
/* Ignore null pointer. */
if (inode == NULL)
return;
/* Release resources if this was the last opener. */
if (--inode->open_cnt == 0)
{
/* Remove from inode list and release lock. */
list_remove(&inode->elem);
/* Deallocate blocks if removed. */
if (inode->removed)
{
fat_remove_chain(inode->sector, 0);
fat_remove_chain(inode->data.start, 0);
}
free(inode);
}
/* ---------------------------- << Project.4 FAT << ---------------------------- */
우선 이 함수는 inode를 닫고, 만약 file이 삭제된다면 (inode->removed == true 라면)
inode_disk가 들어있는 곳과 실 data가 들어있는 곳을 지운다.
일단 inode->sector (inode_disk가 있는 곳) 을 fat_remove_chain(inode->sector, 0) 으로 지우고
그다음은 fat_remove_chain(inode->data.start, 0)
그런데 불안하다.
이렇게 간단하게 함수로 구현이 되나?
지금으로선 생각나는게 이것밖에 없으니 일단 넘어가자.
다음은 inode_read_at()이다.
딱봐도 힘들 것 같긴 하다.
에혀... 언제 고치냐
/* Reads SIZE bytes from INODE into BUFFER, starting at position OFFSET.
* Returns the number of bytes actually read, which may be less
* than SIZE if an error occurs or end of file is reached. */
off_t inode_read_at(struct inode *inode, void *buffer_, off_t size, off_t offset)
{
#ifdef EFILESYS
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
uint8_t *buffer = buffer_;
off_t bytes_read = 0;
uint8_t *bounce = NULL;
while (size > 0)
{
/* Disk sector to read, starting byte offset within sector. */
disk_sector_t sector_idx = byte_to_sector(inode, offset);
int sector_ofs = offset % DISK_SECTOR_SIZE;
/* Bytes left in inode, bytes left in sector, lesser of the two. */
off_t inode_left = inode_length(inode) - offset;
int sector_left = DISK_SECTOR_SIZE - sector_ofs;
int min_left = inode_left < sector_left ? inode_left : sector_left;
/* Number of bytes to actually copy out of this sector. */
int chunk_size = size < min_left ? size : min_left;
if (chunk_size <= 0)
break;
if (sector_ofs == 0 && chunk_size == DISK_SECTOR_SIZE)
{
/* Read full sector directly into caller's buffer. */
disk_read(filesys_disk, sector_idx, buffer + bytes_read);
}
else
{
/* Read sector into bounce buffer, then partially copy
* into caller's buffer. */
if (bounce == NULL)
{
bounce = malloc(DISK_SECTOR_SIZE);
if (bounce == NULL)
break;
}
disk_read(filesys_disk, sector_idx, bounce);
memcpy(buffer + bytes_read, bounce + sector_ofs, chunk_size);
}
/* Advance. */
size -= chunk_size;
offset += chunk_size;
bytes_read += chunk_size;
}
free(bounce);
return bytes_read;
/* ---------------------------- << Project.4 FAT << ---------------------------- */
우선, 함수를 파악해보자. 우선 offset이 어느 sector안에 있는가 파악하는데, 이는 byte_to_sector()로 수행한다.
그런데 byte_to_sector()는 연속할당기준이므로 이를 바꿔야한다.
/* Returns the disk sector that contains byte offset POS within
* INODE.
* Returns -1 if INODE does not contain data for a byte at offset
* POS. */
static disk_sector_t
byte_to_sector(const struct inode *inode, off_t pos)
{
#ifdef EFILESYS
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
ASSERT(inode != NULL);
if (pos < inode->data.length)
{
cluster_t cur = inode->data.start;
uint32_t cnt = pos / DISK_SECTOR_SIZE;
int i = 0;
for (i ; i < cnt ; i++)
{
cur = fat_get(cur);
}
return cur;
}
else
return -1;
/* ---------------------------- << Project.4 FAT << ---------------------------- */
이런 식으로 pos가 속한 sector를 반환한다. ← 중요!!!
그런데 쓱 보니깐, 이것만 바꾸면 더이상 바꿀 것이 없는 것 같은데?
그래도 하나씩 자세히 보자.
/* Reads SIZE bytes from INODE into BUFFER, starting at position OFFSET.
* Returns the number of bytes actually read, which may be less
* than SIZE if an error occurs or end of file is reached. */
off_t inode_read_at(struct inode *inode, void *buffer_, off_t size, off_t offset)
{
#ifdef EFILESYS
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
uint8_t *buffer = buffer_;
off_t bytes_read = 0;
uint8_t *bounce = NULL;
while (size > 0)
{
/* Disk sector to read, starting byte offset within sector. */
disk_sector_t sector_idx = byte_to_sector(inode, offset);
int sector_ofs = offset % DISK_SECTOR_SIZE;
/* Bytes left in inode, bytes left in sector, lesser of the two. */
off_t inode_left = inode_length(inode) - offset;
int sector_left = DISK_SECTOR_SIZE - sector_ofs;
int min_left = inode_left < sector_left ? inode_left : sector_left;
/* Number of bytes to actually copy out of this sector. */
int chunk_size = size < min_left ? size : min_left;
if (chunk_size <= 0)
break;
if (sector_ofs == 0 && chunk_size == DISK_SECTOR_SIZE)
{
/* Read full sector directly into caller's buffer. */
disk_read(filesys_disk, sector_idx, buffer + bytes_read);
}
else
{
/* Read sector into bounce buffer, then partially copy
* into caller's buffer. */
if (bounce == NULL)
{
bounce = malloc(DISK_SECTOR_SIZE);
if (bounce == NULL)
break;
}
disk_read(filesys_disk, sector_idx, bounce);
memcpy(buffer + bytes_read, bounce + sector_ofs, chunk_size);
}
/* Advance. */
size -= chunk_size;
offset += chunk_size;
bytes_read += chunk_size;
}
free(bounce);
return bytes_read;
/* ---------------------------- << Project.4 FAT << ---------------------------- */
while 문을 돌면서 size가 0 보다 많으면 반복한다. 아마 size는 while 한번 돌면 읽은만큼 감소시킬 것이다.
offset이 속한 sector를 sector_idx에 저장하고, sector 안의 offset을 sector_ofs로 저장한다. 이는 맨 처음의 시작위치이며, 첫번째 섹터 후에는 쭉 0이 될 것이다.
inode_left는 offset으로부터 끝까지의 크기.
sector_left는 sector 내에서 현 위치에서 섹터 끝까지의 크기
min_lieft 는 둘중에 작은 것을 내놓는다. (작은 것이 진짜 남은 데이터의 크기이다.)
그리고 disk_read를 수행한다. 이는 FAT_open()과 유사하니 패스
음.. 나머지는 안바꿔도 되겠는데?
inode_write_at() 도 똑같은 것 같은데.
일단 inode.c는 여기에서 종료하고 나중에 바꿀게 있으면 이 밑에 추가하도록 하겠다.
'Pintos Project > Project 4' 카테고리의 다른 글
[PintOS, Project 4] Directory.c 공부 (0) | 2021.03.05 |
---|---|
[PintOS, Project 4] Filesys.c 구현 (0) | 2021.03.04 |
[PintOS, Project 4] fat.c 구현 (0) | 2021.03.04 |
[PintOS, Project 4] inode.c 공부 (2) | 2021.03.04 |
[PintOS, Project 4] fat.c 공부 (2) | 2021.03.03 |
댓글