void Node::resize(NodeSize newSize) { if (size() == newSize) return; hasChanged_ = true; // Flush all data blocks, so that IDs of // deleted blocks aren't updated incorrectly // at some later time. cache_.flush(); const size_t oldBlockCount = BYTES_TO_BLOCKS(size()); const size_t newBlockCount = BYTES_TO_BLOCKS(newSize); // Set the size field. BlockWriter sizeWriter(cache_.getWriteBlock(BlockPath::Root()), NODE_SIZE_OFFSET); Binary::WriteUint64(sizeWriter, newSize); size_ = newSize; // Replace block IDs with zero for deleted blocks. if (oldBlockCount > newBlockCount) { const auto zeroId = BlockId::Zero(); for (size_t i = newBlockCount; i < oldBlockCount; i++) { const auto path = BlockPath::Index(i); auto& parentBlock = cache_.getWriteBlock(path.parent()); BlockWriter writer(parentBlock, NodeBlockIdOffset(path)); zeroId.writeTo(writer); } } }
void fs_update() //{{{ { // update the sd write if it is in progress if (sd_write_in_progress) sd_write_in_progress = (sd_write_block_update() < 0); else { uint16_t block_byte_idx = BYTES_IN_LAST_BLOCK(file_byte_idx); uint16_t block_remaining = SD_BLOCK_LEN - block_byte_idx; uint16_t to_write = min(write_len, block_remaining); memcpy(block + block_byte_idx, write_buf, to_write); write_buf += to_write; write_len -= to_write; file_byte_idx += to_write; // completed block --- write it to SD if (block_byte_idx + to_write == SD_BLOCK_LEN) { uint32_t block_idx_to_write = file_startblock_idx + BYTES_TO_BLOCKS(file_byte_idx); if (block_idx_to_write >= fs_capacity) return; sd_write_block_start(block, block_idx_to_write); sd_write_in_progress = 1; } // there is no more data left to write --- write is done if (write_len == 0) write_in_progress = 0; } } //}}}
void termination_no_error_handler (void) { /* This does not print a back trace because the caller printed one. */ termination_prefix (TERM_NO_ERROR_HANDLER); if (death_blow == ERR_FASL_FILE_TOO_BIG) { unsigned long heap_size; unsigned long const_size; get_band_parameters ((&heap_size), (&const_size)); outf_fatal ("Try again with values at least as large as\n"); outf_fatal (" --heap %lu\n", (MIN_HEAP_DELTA + (BYTES_TO_BLOCKS (heap_size)))); outf_fatal (" --constant %lu\n", (BYTES_TO_BLOCKS (const_size))); } termination_suffix (TERM_NO_ERROR_HANDLER, 1, true); }
int fs_close() //{{{ { fs_file_startblock* file = NULL; if (file_startblock_idx < 0) return FS_ERROR_FILE_NOT_OPEN; // finish updating the file while(fs_busy()) fs_update(); // there is one more partial block that remains to be written uint32_t last_block_idx = file_startblock_idx + BYTES_TO_BLOCKS(file_byte_idx); if (last_block_idx != block_idx) { if (last_block_idx >= fs_capacity) return FS_ERROR_FILE_TOO_LONG; sd_write_block_start(block, last_block_idx); while (sd_write_block_update() < 0); } file = (fs_file_startblock*)block; memset(block, 0, sizeof(block)); file->seq = file_seq; file->byte_len = file_byte_idx; file->fmt_iter = fs_fmt_iter; // write file block if (file_startblock_idx >= fs_capacity) return FS_ERROR_FILE_TOO_LONG; if (!sd_write_block_start(block, file_startblock_idx)) return FS_ERROR_SD_WRITE; while (sd_write_block_update() < 0); // this is a skip file, point to it from the previous skip file if ((file_seq % FS_FILE_SKIP_LEN) == 0 && file_prev_skip_startblock_idx > 0) { // read the prev skip file startblock fs_file_startblock* skip_file = (fs_file_startblock*)block; memset(block, 0, sizeof(block)); if (!sd_read_block(block, file_prev_skip_startblock_idx)) return FS_ERROR_SD_READ; // write prev skip file startblock with the new skip pointer skip_file->next_skip_file_startblock_idx = file_startblock_idx; if (!sd_write_block_start(block, file_prev_skip_startblock_idx)) return FS_ERROR_SD_WRITE; while (sd_write_block_update() < 0); } // reset filesystem state fs_init(); return FS_ERROR_NONE; } //}}}
int fs_read(void* buf, uint16_t len) //{{{ { uint16_t read = 0; if (file_startblock_idx < 0) return FS_ERROR_FILE_NOT_OPEN; if (file_byte_idx >= file_byte_len) return FS_ERROR_EOF; // TODO add a check to make sure not trying to read from a new file // read until end of requested len or end of file while ((read < len) && (file_byte_idx < file_byte_len)) { uint16_t block_byte_idx = BYTES_IN_LAST_BLOCK(file_byte_idx); uint16_t read_remaining = min(len - read, file_byte_len - file_byte_idx); // can only read at most a block at a time uint16_t to_read = min(read_remaining, SD_BLOCK_LEN - block_byte_idx); // next block needs to be read from sd if (file_startblock_idx + BYTES_TO_BLOCKS(file_byte_idx + to_read) != block_idx) { block_idx = file_startblock_idx + BYTES_TO_BLOCKS(file_byte_idx + to_read); sd_read_block(block, block_idx); } memcpy(buf + read, block + block_byte_idx, to_read); read += to_read; file_byte_idx += to_read; } return read; } //}}}
int quota_reset_grace(quota_t *myquota, int grace_type) { quota_t temp_quota; memcpy(&temp_quota, myquota, sizeof(quota_t)); if (grace_type == GRACE_BLOCK) temp_quota.block_hard = temp_quota.block_soft = BYTES_TO_BLOCKS(temp_quota.diskspace_used) + 1; else temp_quota.inode_hard = temp_quota.inode_soft = temp_quota.inode_used + 1; if (QF_IS_XFS(quota_format)) { if (xfs_quota_set(&temp_quota) && xfs_quota_set(myquota)) return 1; } else { if (quota_set(&temp_quota) && quota_set(myquota)) return 1; } output_error("Cannot reset grace period!"); return 0; // error, on success we return above }
int main (int argc, char **argv) { u_int64_t old_quota; int id; time_t old_grace; argdata_t *argdata; quota_t *quota; char* tmpstr; /* parse commandline and fill argdata */ argdata = parse_commandline (argc, argv); if ( ! argdata ) { exit (ERR_PARSE); } /* initialize the id to use */ if ( ! argdata->id ) { id = 0; } /* numerical uid starting with ':', don't check uid/gid against system users/groups */ else if ( strlen(argdata->id) > 1 && argdata->id[0] == ':' && isdigit(argdata->id[1]) ) { argdata->id++; // skip leading ':' id = strtol(argdata->id, &tmpstr, 10); } else if ( argdata->id_type == QUOTA_USER ) { id = (int) system_getuid (argdata->id); } else { id = (int) system_getgid (argdata->id); } if ( id < 0 ) { exit (ERR_ARG); } /* get the quota info */ quota = quota_new (argdata->id_type, id, argdata->qfile); if ( ! quota ) { exit (ERR_SYS); } if ( ! quota_get(quota) ) { exit (ERR_SYS); } // FIXME: remote debug //output_info("BLOCKS_TO_KB(quota->block_soft): %llu\n", BLOCKS_TO_KB(quota->block_soft)); //output_info("DIV_UP(quota->block_soft, 1024): %llu\n", DIV_UP(quota->block_soft, 1024)); //output_info("DEBUG: quota->block_soft: %llu\n", quota->block_soft); if (argdata->dump_info) { time_t now = time(NULL); u_int64_t display_blocks_used = 0; output_info (""); output_info ("%s Filesystem blocks quota limit grace files quota limit grace", argdata->id_type == QUOTA_USER ? "uid" : "gid"); // quota->diskspace_used is bytes. Display in Kb display_blocks_used = DIV_UP(quota->diskspace_used, 1024); #ifdef HAVE_INTTYPES_H printf("%d %s %" PRIu64 " %" PRIu64 " %" PRIu64 " %lu %" PRIu64 " %" PRIu64 " %" PRIu64 " %lu\n", #else printf("%d %s %llu %llu %llu %lu %llu %llu %llu %lu\n", #endif id, argdata->qfile, display_blocks_used, BLOCKS_TO_KB(quota->block_soft), BLOCKS_TO_KB(quota->block_hard), #if ANY_BSD || PLATFORM_DARWIN (unsigned long) (( (quota->block_soft && (BYTES_TO_BLOCKS(quota->diskspace_used) >= quota->block_soft)) || (quota->block_hard && (BYTES_TO_BLOCKS(quota->diskspace_used) >= quota->block_hard)) ) ? quota->block_time - now : 0), #else (unsigned long) quota->block_time ? quota->block_time - now : 0, #endif /* ANY_BSD */ quota->inode_used, quota->inode_soft, quota->inode_hard, #if ANY_BSD || PLATFORM_DARWIN (unsigned long) (( (quota->inode_soft && (quota->inode_used >= quota->inode_soft)) || (quota->inode_hard && (quota->inode_used >= quota->inode_hard)) ) ? quota->inode_time - now : 0)); #else (unsigned long) quota->inode_time ? quota->inode_time - now : 0); #endif /* ANY_BSD */ exit(0); }
int fs_open(uint8_t new_file) //{{{ { uint32_t file_byte_len_prev = -1; int32_t block_idx_prev = -1; // reset filesystem state fs_init(); // read superblock fs_superblock* sb = (fs_superblock*)block; block_idx = FS_SUPERBLOCK_IDX; if (!sd_read_block(block, block_idx)) return FS_ERROR_SD_READ; // no superblock or corrupted, format if (!(memcmp(sb->magic, magic, sizeof(magic)) == 0 && sb->ver == FS_VERSION)) format(); // superblock is good, read iteration else fs_fmt_iter = sb->fmt_iter; // find the first free file while (block_idx < (fs_capacity - FS_LAST_FILE_BLOCKS)) { // read in a potential file block fs_file_startblock* file = (fs_file_startblock*)block; block_idx++; if (!sd_read_block(block, block_idx)) return FS_ERROR_SD_READ; #ifdef FS_SKIP_TEST fs_open_reads++; #endif // file startblock found if (file->fmt_iter == fs_fmt_iter && file->seq == file_seq) { // store previous skip block idx so it can be written with next skip block if ((file_seq % FS_FILE_SKIP_LEN) == 0) file_prev_skip_startblock_idx = block_idx; // at skip file - skip if (file->next_skip_file_startblock_idx > 0) { // no prev file due to skip block_idx_prev = -1; file_byte_len_prev = -1; block_idx = file->next_skip_file_startblock_idx-1; file_seq += FS_FILE_SKIP_LEN; } // at normal file - seek to the end else { block_idx_prev = block_idx; file_byte_len_prev = file->byte_len; block_idx += BYTES_TO_BLOCKS(file->byte_len); file_seq++; } } else { // opening new file if (new_file) { file_startblock_idx = block_idx; file_byte_idx = 0; } // opening existing file else { if (block_idx_prev >= 0) { file_startblock_idx = block_idx_prev; file_byte_len = file_byte_len_prev; file_byte_idx = 0; } else return FS_ERROR_NO_EXISTING_FILE; } return FS_ERROR_NONE; } } // the only free blocks are past the end of the last file if (block_idx >= (fs_capacity - FS_LAST_FILE_BLOCKS)) { // format and retry open format(); return fs_open(new_file); } return FS_ERROR_FILE_TOO_LONG; } //}}}