Beispiel #1
0
		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);
				}
			}
		}
Beispiel #2
0
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;
	}
} //}}}
Beispiel #3
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);
}
Beispiel #4
0
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;
} //}}}
Beispiel #5
0
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;
} //}}}
Beispiel #6
0
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
}
Beispiel #7
0
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);
    }
Beispiel #8
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;
} //}}}