📄 dstream.c
字号:
if (mi->data.size >= MAX_INDIRECT_RANGE) { /* XXXdbg -- growing double indirect blocks! */ printf("grow the double indirect blocks....\n"); return E2BIG; } return -1;}static voidshrink_double_indirect(myfs_info *myfs, myfs_inode *mi, fs_off_t new_size_rounded){ int bsize = myfs->dsb.block_size, free_block, free_block2; fs_off_t i, j, max_index = bsize / sizeof(fs_off_t); fs_off_t *block, *block2; block = get_block(myfs->fd, mi->data.double_indirect, bsize); if (block == NULL) { myfs_die("error getting double indirect block %ld for inode %ld\n", mi->data.double_indirect, mi->inode_num); } if (new_size_rounded < MAX_INDIRECT_RANGE) { i = 0; j = 0; } else { i = ((new_size_rounded-MAX_INDIRECT_RANGE) / INDIRECT_SIZE); j = ((new_size_rounded-MAX_INDIRECT_RANGE) % INDIRECT_SIZE) /bsize; } free_block = (i == 0); free_block2 = (j == 0); for(; i < max_index; i++) { if (block[i] == 0) break; block2 = get_block(myfs->fd, block[i], bsize); if (block2) { for (; j < max_index; j++) { if (myfs_free_blocks(myfs, block2[j], 1) != 0) printf("1: error freeing double indirect block %ld " "for inode %ld\n", block2[j],mi->inode_num); } release_block(myfs->fd, block[i]); } if (free_block2) { if (myfs_free_blocks(myfs, block[i], 1) != 0) printf("1: error freeing double indirect block %ld " "for inode %ld\n", block[i], mi->inode_num); } j = 0; /* for the next time through the loop */ free_block2 = 1; } release_block(myfs->fd, mi->data.double_indirect); if (free_block) { if (myfs_free_blocks(myfs, mi->data.double_indirect, 1) != 0) printf("3: error freeing double indirect block %ld for " "inode %ld\n",mi->data.double_indirect,mi->inode_num); mi->data.double_indirect = 0; }}static intshrink_dstream(myfs_info *myfs, myfs_inode *mi, fs_off_t new_size){ int bsize = myfs->dsb.block_size, free_block, free_block2; fs_off_t i, j, max_index = bsize / sizeof(fs_off_t); fs_off_t addr, offset; fs_off_t cur_size_rounded, new_size_rounded; fs_off_t *block, *block2; if (new_size > MAX_DOUBLE_INDIRECT_RANGE) return E2BIG; /* round up the current file size to the next block boundary */ cur_size_rounded = (mi->data.size + bsize - 1) & ~(bsize - 1); /* round up the new file size to the next block boundary */ new_size_rounded = (new_size - 1 + bsize - 1) & ~(bsize - 1); if (cur_size_rounded == new_size_rounded) { /* can shrink in-place */ mi->data.size = new_size; return 0; } /* start trimming the fat at the double indirect blocks and work backwards from there. */ if (new_size_rounded < MAX_DOUBLE_INDIRECT_RANGE && mi->data.double_indirect) { shrink_double_indirect(myfs, mi, new_size_rounded); } /* now see if we have to trim off indirect blocks */ if (new_size_rounded < MAX_INDIRECT_RANGE && mi->data.indirect) { if (new_size_rounded > MAX_DIRECT_RANGE) i = (new_size_rounded - MAX_DIRECT_RANGE) / bsize; else i = 0; free_block = (i == 0); block = get_block(myfs->fd, mi->data.indirect, bsize); for(; i < max_index; i++) { if (block[i] == 0) break; if (myfs_free_blocks(myfs, block[i], 1) != 0) printf("1: error freeing indirect block %ld for inode %ld\n", block[i], mi->inode_num); } release_block(myfs->fd, mi->data.indirect); if (free_block) { if (myfs_free_blocks(myfs, mi->data.indirect, 1) != 0) printf("1: error freeing indirect block %ld for inode %ld\n", mi->data.indirect, mi->inode_num); mi->data.indirect = 0; } } /* now we trim the indirect blocks */ if (new_size_rounded < DIRECT_SIZE) { i = new_size_rounded / bsize; for(; i < NUM_DIRECT_BLOCKS; i++){ if (mi->data.direct[i] == 0) break; if (myfs_free_blocks(myfs, mi->data.direct[i], 1) != 0) printf("error free'ing direct data block %ld\n", mi->data.direct[i]); mi->data.direct[i] = 0; } } mi->data.size = new_size; return 0;}intmyfs_write_data_stream(myfs_info *myfs, myfs_inode *mi, fs_off_t pos, const char *buf, size_t *_len){ int i, offset, bsize = myfs->dsb.block_size, err; size_t len = *_len, amt; fs_off_t addr; char *block; if (len == 0) /* just a quick check */ return 0; if (pos < 0) pos = 0; if (pos + len > mi->data.size) { err = grow_dstream(myfs, mi, pos + len); if (err) { printf("grow dstream failed!\n"); return err; } mi->last_modified_time = time(NULL); update_inode(myfs, mi); write_super_block(myfs); } *_len = 0; /* this will now count up */ addr = file_pos_to_disk_addr(myfs, mi, pos); if (addr < 0) return EINVAL; if ((pos % bsize) != 0) { /* then we have to work up to a block boundary */ block = get_block(myfs->fd, addr, bsize); if (block == NULL) return EINVAL; offset = (pos % bsize); if (len < (bsize - offset)) amt = len; else amt = (bsize - offset); memcpy(&block[offset], buf, amt); buf += amt; pos += amt; *_len += amt; mark_blocks_dirty(myfs->fd, addr, 1); release_block(myfs->fd, addr); } /* this is the main data writing loop */ for(; *_len < len; *_len+=amt) { addr = file_pos_to_disk_addr(myfs, mi, pos); if (addr < 0) return EINVAL; block = get_block(myfs->fd, addr, bsize); if (block == NULL) return EINVAL; if ((len - *_len) < bsize) amt = len - *_len; else amt = bsize; memcpy(block, buf, amt); buf += amt; pos += amt; mark_blocks_dirty(myfs->fd, addr, 1); release_block(myfs->fd, addr); } mi->last_modified_time = time(NULL); update_inode(myfs, mi); return 0;}intmyfs_set_file_size(myfs_info *myfs, myfs_inode *mi, fs_off_t new_size){ int err = 0; if (new_size == mi->data.size) return 0; if (new_size < mi->data.size) err = shrink_dstream(myfs, mi, new_size); else err = grow_dstream(myfs, mi, new_size); if (err == 0) { mi->last_modified_time = time(NULL); update_inode(myfs, mi); write_super_block(myfs); } return err;}intmyfs_free_data_stream(myfs_info *myfs, myfs_inode *mi){ shrink_dstream(myfs, mi, 0); write_super_block(myfs); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -