[SW정글 88일차] pintos p4 part1-2. file growth

rg.log·2022년 12월 15일
0

SW 사관학교 JUNGLE

목록 보기
23/31

우리의 3시간짜리 작은 똥 자랑을 해보려 한다..💩 사실 똥인줄 알았지만 보기보다 중요한 부분이었다.

inode_write_at

off_t
inode_write_at (struct inode *inode, const void *buffer_, off_t size,
		off_t offset) {
        
        ...
        
		/* 만약 섹터가 우리가 쓰고 있는 청크의 앞이나 뒤에 데이터를 포함하고 있다면, 우리는 먼저 섹터에서 읽을 필요가 있다.
		   그렇지 않으면 모든 0의 섹터로 시작 */
		if (sector_ofs > 0 || chunk_size < sector_left) // 섹터내 우리가 적으려는 위치가 > 0 거나, 적고 싶은 크기 < 섹터의 남은 부분이면
			disk_read (filesys_disk, sector_idx, bounce); // disk 해당 sector 1개를 통째로 bounce에 읽어와
		else
			memset (bounce, 0, DISK_SECTOR_SIZE); // bounce를 섹터 1개 크기만큼 0으로 채워
		memcpy (bounce + sector_ofs, buffer + bytes_written, chunk_size); // bounce의 섹터내 우리가 적으려했던 위치에, 우리가 적고 싶은 사이즈만큼 적고 싶었던 내용을 써
		disk_write (filesys_disk, sector_idx, bounce);  // 섹터 단위로 밖에 쓸 수 없어서 ^^
            
  ...       
  
 }

해당 함수는 버퍼에서 INODE로 오프셋부터 SIZE 바이트 쓰고 실제로 쓴 바이트 수를 반환하는 함수이다. 이미 핀토스 스켈레톤으로 구현되어있던 함수지만, 현재는 파일의 확장이 구현되어있지 않아 우리가 해야했다.

팀원들과 이해되지 않았던 부분은 왜 if문부터 disk_write까지의 효율적이지 않은 방법으로 진행할까였다. 처음에는 섹터내에 이미 데이터가 적혀있다면 disk_read를 통해 bounce라는 버퍼에 읽어와서 따로 저장을 해주거나 처리를 해주려하나? 하는 생각으로 시작했고, 하나하나 뜯어볼 수록 이미 적혀있던 데이터를 따로 저장하거나 처리해주는 내용이 없었다. 그렇다면 굳이 그냥 덮어쓰면 되지 왜 따로 bounce buffer로 1 sector를 읽어왔다가 그곳에 우리가 적으려는 내용으로 덮어쓰고 다시 해당 sector위치에 적을까? 바쁘고 힘든 대학원생의 오류인가 까지 갔다가 돌아온 내용을 공유하고자 한다..

이는 disk_write는 섹터 단위로 밖에 쓸 수 없기 때문이다.
마치 이미 과장님이 적어서 뽑아놓은 기획안에 내가 추가 사항을 그냥 손글씨로 덧붙이는 것이 아니라 다시 그 내용을 추가사항과 함께 한글 파일로 정리 후에 뽑아서 붙여넣는 것과 같은 원리랄까.

if (sector_ofs > 0 || chunk_size < sector_left) // 섹터내 우리가 적으려는 위치가 > 0 거나, 적고 싶은 크기 < 섹터의 남은 부분이면
	disk_read (filesys_disk, sector_idx, bounce);

if 문에 해당하는 상황은 아래 3가지로, sector의 크기보다 작게 write 하기 때문에 이전에 sector에 저장되어있던 데이터를 날리게 된다.

  • chunk_size : 한 섹터 내 적고 싶은 크기
  • sector_ofs : 한 섹터 내 적고 싶은 위치
  • sector_left : 한 섹터 내 sector_ofs 이후로 남은 크기

그 중 첫번째 case만 예시로 들어본다면,
(before) sector에 이미 하얗게 저장되어 있는 데이터가 있을 때
1. bounce 버퍼를 sector 크기만큼 할당 받는다.
2. bounce 버퍼에 sector 안의 내용을 적는다.
3. bounce 버퍼에 sector_offset 이후에 적고 싶었던 chunk size만큼 적는다.
4. 해당 bounce 버퍼를 sector에 통째로 적는다.

inode_write_at 함수는 버퍼에서 INODE로 오프셋부터 SIZE 바이트 쓰는 함수로 file growth를 구현하여 아래와 같이 수정하였다.

off_t inode_write_at(struct inode *inode, const void *buffer_, off_t size,
                     off_t offset)
{
    const uint8_t *buffer = buffer_;
    off_t bytes_written = 0;
    uint8_t *bounce = NULL;
    off_t origin_offset = offset; // offset이 while문 돌며 변경되니 초기 offset 저장
    
    if (inode->deny_write_cnt)
        return 0;

    while (size > 0) { 
        disk_sector_t sector_idx = byte_to_sector(inode, offset); // 오프셋에 해당하는 sector_idx 가져옴
        int sector_ofs = offset % DISK_SECTOR_SIZE; // 한섹터 안에서의 오프셋
        int sector_left = DISK_SECTOR_SIZE - sector_ofs; // 한 섹터 내 sector_ofs 이후로 남은 크기

        /* 실제 sector에 적을 byte 수 */
        int chunk_size = size < sector_left ? size : sector_left;

		if (chunk_size <= 0)
            break;

        if (sector_ofs == 0 && chunk_size == DISK_SECTOR_SIZE){
            disk_write(filesys_disk, sector_idx, buffer + bytes_written);
        } else {
            if (bounce == NULL) {
                bounce = malloc(DISK_SECTOR_SIZE);
                if (bounce == NULL)
                    break;
            }

            /* 만약 섹터가 우리가 쓰고 있는 청크의 앞이나 뒤에 데이터를 포함하고 있다면, 우리는 먼저 섹터에서 읽을 필요가 있다. */
            if (sector_ofs > 0 || chunk_size < sector_left)
                disk_read(filesys_disk, sector_idx, bounce);
            else
                memset(bounce, 0, DISK_SECTOR_SIZE);
            memcpy(bounce + sector_ofs, buffer + bytes_written, chunk_size);
            disk_write(filesys_disk, sector_idx, bounce);
        }

        /* Advance. */
        size -= chunk_size;
        offset += chunk_size;
        bytes_written += chunk_size;
    }
    free(bounce);

    off_t changed_length = origin_offset + bytes_written; // 원래 offset에 적은 byte를 더한 것이 변경된 길이
    if (inode->data.length < changed_length) // 이전 파일의 length가 변경된 length보다 짧으면 
        inode->data.length = changed_length; // 늘려줌

    return bytes_written; // 실제로 쓴 바이트 수를 반환
}

오늘의 나는

다행히 의문이 가서 팠던 코드의 이해가 우리가 구현해야할 코드와 맞물렸다.
겨울되고 강의실이 건조해서 목이 칼칼하니 물 많이 마시고 스트레칭 자주 해주기!

0개의 댓글