Пример #1
0
int fs_rename(char* a, char* b) {
    
    unsigned int a_inode_index = FS_MAXFILEBLOCKS;
    unsigned int b_inode_index = FS_MAXFILEBLOCKS;
    unsigned int a_dir_index = FS_DIRENTRIES;
    fs_direntry dir_block[FS_DIRENTRIES];
    fs_direntry dir_a[FS_DIRENTRIES];
    fs_direntry dir_b[FS_DIRENTRIES];

    for ( int i = 0; i < dir_inode.size / FS_BLOCKSIZE; i++ ) {
        disk_readblock(dir_inode.blocks[i], dir_block);
        for ( int j = 0; j < FS_DIRENTRIES; j++ ) {
            if ( dir_block[j].inode_block != 0 ) {
                if ( strcmp(dir_block[j].name, a) ) {
                    a_inode_index = i;
                    a_dir_index = j;
                    memcpy(dir_a, dir_block, FS_BLOCKSIZE);
                    strcpy(dir_a[j].name, b);
                }
                if ( strcmp(dir_block[j].name, b) ) {
                    b_inode_index = i;
                    memcpy(dir_b, dir_block, FS_BLOCKSIZE);
                    mark_all_file_blocks_free(dir_b[j].inode_block);
                    dir_b[j].inode_block = 0;
                }
            }
        }
        if ( a_inode_index != FS_MAXFILEBLOCKS && b_inode_index != FS_MAXFILEBLOCKS 
            && a_inode_index == b_inode_index ) {
            strcpy(dir_b[a_dir_index].name, b);
            disk_writeblock(dir_inode.blocks[b_inode_index], dir_b);
            return 0;
        }
    }

    if ( a_inode_index == FS_MAXFILEBLOCKS ) {
        return -1;
    }
    if ( b_inode_index == FS_MAXFILEBLOCKS ) {
        disk_writeblock(dir_inode.blocks[a_inode_index], dir_a);
        return 0;
    }
    
    unsigned int old_a_dir_block = dir_inode.blocks[a_inode_index];
    unsigned int old_b_dir_block = dir_inode.blocks[b_inode_index];
    unsigned int new_a_dir_block = get_free_block();
    unsigned int new_b_dir_block = get_free_block();
    dir_inode.blocks[a_inode_index] = new_a_dir_block;
    dir_inode.blocks[b_inode_index] = new_b_dir_block;
    disk_writeblock(new_a_dir_block, dir_a);
    disk_writeblock(new_b_dir_block, dir_b);
    disk_writeblock(dir_inode, 0);
    mark_block_free(old_a_dir_block);
    mark_block_free(old_b_dir_block);

    return 0;

}
Пример #2
0
static void make_bad_inode(void)
{
	struct minix1_inode *inode = &INODE_BUF1[MINIX_BAD_INO];
	int i, j, zone;
	int ind = 0, dind = 0;
	/* moved to globals to reduce stack usage
	unsigned short ind_block[BLOCK_SIZE >> 1];
	unsigned short dind_block[BLOCK_SIZE >> 1];
	*/
#define ind_block (G.ind_block1)
#define dind_block (G.dind_block1)

#define NEXT_BAD (zone = next(zone))

	if (!G.badblocks)
		return;
	mark_inode(MINIX_BAD_INO);
	inode->i_nlinks = 1;
	/* BTW, setting this makes all images different */
	/* it's harder to check for bugs then - diff isn't helpful :(... */
	inode->i_time = CUR_TIME;
	inode->i_mode = S_IFREG + 0000;
	inode->i_size = G.badblocks * BLOCK_SIZE;
	zone = next(0);
	for (i = 0; i < 7; i++) {
		inode->i_zone[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[7] = ind = get_free_block();
	memset(ind_block, 0, BLOCK_SIZE);
	for (i = 0; i < 512; i++) {
		ind_block[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[8] = dind = get_free_block();
	memset(dind_block, 0, BLOCK_SIZE);
	for (i = 0; i < 512; i++) {
		write_block(ind, (char *) ind_block);
		dind_block[i] = ind = get_free_block();
		memset(ind_block, 0, BLOCK_SIZE);
		for (j = 0; j < 512; j++) {
			ind_block[j] = zone;
			if (!NEXT_BAD)
				goto end_bad;
		}
	}
	bb_error_msg_and_die("too many bad blocks");
 end_bad:
	if (ind)
		write_block(ind, (char *) ind_block);
	if (dind)
		write_block(dind, (char *) dind_block);
#undef ind_block
#undef dind_block
}
Пример #3
0
static void make_bad_inode2(void)
{
	struct minix2_inode *inode = &INODE_BUF2[MINIX_BAD_INO];
	int i, j, zone;
	int ind = 0, dind = 0;
	/* moved to globals to reduce stack usage
	unsigned long ind_block[BLOCK_SIZE >> 2];
	unsigned long dind_block[BLOCK_SIZE >> 2];
	*/
#define ind_block (G.ind_block2)
#define dind_block (G.dind_block2)

	if (!G.badblocks)
		return;
	mark_inode(MINIX_BAD_INO);
	inode->i_nlinks = 1;
	inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
	inode->i_mode = S_IFREG + 0000;
	inode->i_size = G.badblocks * BLOCK_SIZE;
	zone = next(0);
	for (i = 0; i < 7; i++) {
		inode->i_zone[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[7] = ind = get_free_block();
	memset(ind_block, 0, BLOCK_SIZE);
	for (i = 0; i < 256; i++) {
		ind_block[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[8] = dind = get_free_block();
	memset(dind_block, 0, BLOCK_SIZE);
	for (i = 0; i < 256; i++) {
		write_block(ind, (char *) ind_block);
		dind_block[i] = ind = get_free_block();
		memset(ind_block, 0, BLOCK_SIZE);
		for (j = 0; j < 256; j++) {
			ind_block[j] = zone;
			if (!NEXT_BAD)
				goto end_bad;
		}
	}
	/* Could make triple indirect block here */
	bb_error_msg_and_die("too many bad blocks");
 end_bad:
	if (ind)
		write_block(ind, (char *) ind_block);
	if (dind)
		write_block(dind, (char *) dind_block);
#undef ind_block
#undef dind_block
}
Пример #4
0
static void make_bad_inode_v1(struct fs_control *ctl)
{
	struct minix_inode * inode = &Inode[MINIX_BAD_INO];
	int i,j,zone;
	int ind=0,dind=0;
	unsigned short ind_block[MINIX_BLOCK_SIZE>>1];
	unsigned short dind_block[MINIX_BLOCK_SIZE>>1];

#define NEXT_BAD (zone = next(zone))

	if (!ctl->fs_bad_blocks)
		return;
	mark_inode(MINIX_BAD_INO);
	inode->i_nlinks = 1;
	inode->i_time = mkfs_minix_time(NULL);
	inode->i_mode = S_IFREG + 0000;
	inode->i_size = ctl->fs_bad_blocks * MINIX_BLOCK_SIZE;
	zone = next(0);
	for (i=0 ; i<7 ; i++) {
		inode->i_zone[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[7] = ind = get_free_block(ctl);
	memset(ind_block,0,MINIX_BLOCK_SIZE);
	for (i=0 ; i<512 ; i++) {
		ind_block[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[8] = dind = get_free_block(ctl);
	memset(dind_block,0,MINIX_BLOCK_SIZE);
	for (i=0 ; i<512 ; i++) {
		write_block(ctl, ind,(char *) ind_block);
		dind_block[i] = ind = get_free_block(ctl);
		memset(ind_block,0,MINIX_BLOCK_SIZE);
		for (j=0 ; j<512 ; j++) {
			ind_block[j] = zone;
			if (!NEXT_BAD)
				goto end_bad;
		}
	}
	errx(MKFS_EX_ERROR, _("%s: too many bad blocks"), ctl->device_name);
end_bad:
	if (ind)
		write_block(ctl, ind, (char *) ind_block);
	if (dind)
		write_block(ctl, dind, (char *) dind_block);
}
Пример #5
0
static void
make_bad_inode(void) {
	struct minix_inode * inode = &Inode[MINIX_BAD_INO];
	int i,j,zone;
	int ind=0,dind=0;
	unsigned short ind_block[BLOCK_SIZE>>1];
	unsigned short dind_block[BLOCK_SIZE>>1];

#define NEXT_BAD (zone = next(zone))

	if (!badblocks)
		return;
	mark_inode(MINIX_BAD_INO);
	inode->i_nlinks = 1;
	inode->i_time = time(NULL);
	inode->i_mode = S_IFREG + 0000;
	inode->i_size = badblocks*BLOCK_SIZE;
	zone = next(0);
	for (i=0 ; i<7 ; i++) {
		inode->i_zone[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[7] = ind = get_free_block();
	memset(ind_block,0,BLOCK_SIZE);
	for (i=0 ; i<512 ; i++) {
		ind_block[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[8] = dind = get_free_block();
	memset(dind_block,0,BLOCK_SIZE);
	for (i=0 ; i<512 ; i++) {
		write_block(ind,(char *) ind_block);
		dind_block[i] = ind = get_free_block();
		memset(ind_block,0,BLOCK_SIZE);
		for (j=0 ; j<512 ; j++) {
			ind_block[j] = zone;
			if (!NEXT_BAD)
				goto end_bad;
		}
	}
	die(_("too many bad blocks"));
end_bad:
	if (ind)
		write_block(ind, (char *) ind_block);
	if (dind)
		write_block(dind, (char *) dind_block);
}
Пример #6
0
static void make_bad_inode_v2_v3 (struct fs_control *ctl)
{
	struct minix2_inode *inode = &Inode2[MINIX_BAD_INO];
	int i, j, zone;
	int ind = 0, dind = 0;
	unsigned long ind_block[MINIX_BLOCK_SIZE >> 2];
	unsigned long dind_block[MINIX_BLOCK_SIZE >> 2];

	if (!ctl->fs_bad_blocks)
		return;
	mark_inode (MINIX_BAD_INO);
	inode->i_nlinks = 1;
	inode->i_atime = inode->i_mtime = inode->i_ctime = mkfs_minix_time(NULL);
	inode->i_mode = S_IFREG + 0000;
	inode->i_size = ctl->fs_bad_blocks * MINIX_BLOCK_SIZE;
	zone = next (0);
	for (i = 0; i < 7; i++) {
		inode->i_zone[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[7] = ind = get_free_block (ctl);
	memset (ind_block, 0, MINIX_BLOCK_SIZE);
	for (i = 0; i < 256; i++) {
		ind_block[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[8] = dind = get_free_block (ctl);
	memset (dind_block, 0, MINIX_BLOCK_SIZE);
	for (i = 0; i < 256; i++) {
		write_block (ctl, ind, (char *) ind_block);
		dind_block[i] = ind = get_free_block (ctl);
		memset (ind_block, 0, MINIX_BLOCK_SIZE);
		for (j = 0; j < 256; j++) {
			ind_block[j] = zone;
			if (!NEXT_BAD)
				goto end_bad;
		}
	}
	/* Could make triple indirect block here */
	errx(MKFS_EX_ERROR, _("%s: too many bad blocks"), ctl->device_name);
 end_bad:
	if (ind)
		write_block (ctl, ind, (char *) ind_block);
	if (dind)
		write_block (ctl, dind, (char *) dind_block);
}
Пример #7
0
static void
make_bad_inode2 (void) {
	struct minix2_inode *inode = &Inode2[MINIX_BAD_INO];
	int i, j, zone;
	int ind = 0, dind = 0;
	unsigned long ind_block[BLOCK_SIZE >> 2];
	unsigned long dind_block[BLOCK_SIZE >> 2];

	if (!badblocks)
		return;
	mark_inode (MINIX_BAD_INO);
	inode->i_nlinks = 1;
	inode->i_atime = inode->i_mtime = inode->i_ctime = time (NULL);
	inode->i_mode = S_IFREG + 0000;
	inode->i_size = badblocks * BLOCK_SIZE;
	zone = next (0);
	for (i = 0; i < 7; i++) {
		inode->i_zone[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[7] = ind = get_free_block ();
	memset (ind_block, 0, BLOCK_SIZE);
	for (i = 0; i < 256; i++) {
		ind_block[i] = zone;
		if (!NEXT_BAD)
			goto end_bad;
	}
	inode->i_zone[8] = dind = get_free_block ();
	memset (dind_block, 0, BLOCK_SIZE);
	for (i = 0; i < 256; i++) {
		write_block (ind, (char *) ind_block);
		dind_block[i] = ind = get_free_block ();
		memset (ind_block, 0, BLOCK_SIZE);
		for (j = 0; j < 256; j++) {
			ind_block[j] = zone;
			if (!NEXT_BAD)
				goto end_bad;
		}
	}
	/* Could make triple indirect block here */
	die (_("too many bad blocks"));
 end_bad:
	if (ind)
		write_block (ind, (char *) ind_block);
	if (dind)
		write_block (dind, (char *) dind_block);
}
Пример #8
0
void* seg_pool::malloc_one()
{
    pool_block* ba=get_free_block();
    if(!ba){
        malloc_block();
        ba=get_free_block();
        if(!ba)
            return NULL;
    }
    void* p=ba->malloc_one();

    if(ba->full()){
        ba->erase_from_list();
        reg_full_block(ba);
    }
    return p;
}
Пример #9
0
void make_root_inode(void)
{
	struct minix_inode * inode = &Inode[MINIX_ROOT_INO];

	mark_inode(MINIX_ROOT_INO);
	inode->i_zone[0] = get_free_block();
	inode->i_nlinks = 2;
	inode->i_time = time(NULL);
	root_block[2*dirsize] = '\0';
	root_block[2*dirsize+1] = '\0';
	inode->i_size = 2*dirsize;
	inode->i_mode = S_IFDIR + 0755;
	write_block(inode->i_zone[0],root_block);
}
Пример #10
0
void make_root_inode(void) {

	struct minix_inode *inode = &Inode[MINIX_ROOT_INO];

	mark_inode(MINIX_ROOT_INO);
	inode->i_zone[0] = get_free_block();
	inode->i_nlinks = 2;
	inode->i_time = time(NULL);
	if (badblocks)
		inode->i_size = 48;
	else
		inode->i_size = 32;
	inode->i_mode = S_IFDIR + 0755;
	write_block(inode->i_zone[0],root_block);
}
int split_rec(int current_list, int list_size, int current_size, int required_size) {
    if(current_list < 0) {
        return 0;
    }
    if(heap[current_list] == -1 && !split_rec((current_list - 1)/2, list_size / 2, current_size*2, required_size)) {
        return 0;
    }
    if(required_size == current_size && heap[current_list] != -1) {
        return 1;
    }
    int temp = get_free_block(current_list,list_size);
    add_to_list(2*current_list+1, temp + current_size/2);
    add_to_list(2*current_list+1, temp);
    return 1;
}
Пример #12
0
/* Create file with given id in the file system. If file exists already, 
	abort and return FALSE. Otherwise, return TRUE. */
BOOLEAN FileSystem::CreateFile(int _file_id) {
	if(this->dir[_file_id].start_block != 0)
		return FALSE;
	unsigned long free_block;
	if(get_free_block(&free_block, 0)) {
		struct dir_node x;
		x.start_block = free_block;
		x.size = 0;
		memcpy(&this->dir[_file_id], &x, sizeof(struct dir_node));
		
		//TODO:write dir to disk
		this->write_dir_to_disk();
		return TRUE;
	}
	return FALSE;
}
Пример #13
0
//initializes the ramdisk, 1 if sucessful, -1 if failed
int init_ramdisk(){
	disk = malloc(RAMDISK_SIZE);
	if(disk == NULL){
		printf("ramdisk allocation failed\n");
		return -1;
	}
	s_block = disk;
	inode_array = getblockoffset(1, disk);
	block_bitmap = getblockoffset(257, disk);
	free_block_addr = getblockoffset(260, disk);

	s_block->free_blocks = (RAMDISK_SIZE-256-64-256*4)/256;
	s_block->free_inodes = (65536/64)-1;//number of inodes

	//probably not necessary since there's already globals for block_bitmap and free_blocks
	s_block->bitmap = block_bitmap;
	s_block->free_block_addr = free_block_addr;

	//initialize the block_bitmap
	int i; //set everything to zero
	for(i = 0; i < 1024; i++){
		*block_bitmap = 0;
		block_bitmap++;
	}

	//initialize the inode_array
	for(i = 0; i < INDEX_NODE_COUNT; i++){
		inode_array[i].id = i;
		inode_array[i].allocated = 0;
		inode_array[i].type = 0;
		inode_array[i].size = 0;
		int j;
		for(j = 0; j < 10; j++){
			inode_array[i].block_pointer[j] = NULL;
		}
		inode_array[i].bp_count = 0;
	}

	//need a notion of a root directory:
	inode_array[0].allocated = 1;
	inode_array[0].type = 1;
	inode_array[0].block_pointer[0] = get_free_block();
	inode_array[0].bp_count = 1;
	return 1;
}
Пример #14
0
static void make_root_inode_v1(struct fs_control *ctl) {
	struct minix_inode * inode = &Inode[MINIX_ROOT_INO];

	mark_inode(MINIX_ROOT_INO);
	inode->i_zone[0] = get_free_block(ctl);
	inode->i_nlinks = 2;
	inode->i_time = mkfs_minix_time(NULL);
	if (ctl->fs_bad_blocks)
		inode->i_size = 3 * ctl->fs_dirsize;
	else {
		memset(&root_block[2 * ctl->fs_dirsize], 0, ctl->fs_dirsize);
		inode->i_size = 2 * ctl->fs_dirsize;
	}
	inode->i_mode = S_IFDIR + 0755;
	inode->i_uid = getuid();
	if (inode->i_uid)
		inode->i_gid = getgid();
	write_block(ctl, inode->i_zone[0],root_block);
}
Пример #15
0
static void make_root_inode_v1(void) {
	struct minix_inode * inode = &Inode[MINIX_ROOT_INO];

	mark_inode(MINIX_ROOT_INO);
	inode->i_zone[0] = get_free_block();
	inode->i_nlinks = 2;
	inode->i_time = time(NULL);
	if (badblocks)
		inode->i_size = 3*dirsize;
	else {
		root_block[2*dirsize] = '\0';
		root_block[2*dirsize+1] = '\0';
		inode->i_size = 2*dirsize;
	}
	inode->i_mode = S_IFDIR + 0755;
	inode->i_uid = getuid();
	if (inode->i_uid)
		inode->i_gid = getgid();
	write_block(inode->i_zone[0],root_block);
}
Пример #16
0
static void make_root_inode2(void)
{
	struct minix2_inode *inode = &INODE_BUF2[MINIX_ROOT_INO];

	mark_inode(MINIX_ROOT_INO);
	inode->i_zone[0] = get_free_block();
	inode->i_nlinks = 2;
	inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
	if (G.badblocks)
		inode->i_size = 3 * G.dirsize;
	else {
		G.root_block[2 * G.dirsize] = '\0';
		G.root_block[2 * G.dirsize + 1] = '\0';
		inode->i_size = 2 * G.dirsize;
	}
	inode->i_mode = S_IFDIR + 0755;
	inode->i_uid = GETUID;
	if (inode->i_uid)
		inode->i_gid = GETGID;
	write_block(inode->i_zone[0], G.root_block);
}
Пример #17
0
void* malloc(size_t size) {
    size_t total_size;
    void *block;
    struct header_t *header;
    if (!size) return NULL;
    if (header = get_free_block(size)) {
        header->is_free = 0;
        // malloc false
        return NULL;/* FIXME */
    }

    total_size = sizeof(struct header_t) + size;
    if ((block = sbrk(total_size)) == (void *) -1)
        return NULL;

    header = block;
    header->size = size;
    header->is_free = 0;
    header->next = NULL;
    /* FIXME */
    /*DO something*/
    return header;/* FIXME */
}
Пример #18
0
void *malloc(size_t size) {
  metadata_t *block;
  // TODO: align size?
  if (unlikely(size <= 0)) {
    return 0;
  }
  if (unlikely(!base)) { // first
    pthread_mutex_init(&list_lock, NULL);
    pthread_mutex_lock(&list_lock);
    block = get_space(0, size);
    if (unlikely(!block)) {
      pthread_mutex_unlock(&list_lock);
      return 0;
    }
    base = block;
//    pthread_mutex_unlock(&list_lock);
  } else {
    pthread_mutex_lock(&list_lock);
    metadata_t *last = base;
    block = get_free_block(&last, size);
    if (!block) {
      block = get_space(last, size);
      if (unlikely(!block)) {
        pthread_mutex_unlock(&list_lock);
        return 0;
      }
    } else {
      // TODO: split
      block->free = 0;
      block->magic1 = MAGIC_USED;
      block->magic2 = MAGIC_USED;
    }
  }
  alloc_count++;
  pthread_mutex_unlock(&list_lock);
  return (block+1);
}
Пример #19
0
int main(int argc, char **argv) {

    if (argc != 4)
    {
        fprintf(stderr, "Usage: readimg <image file name> filepath \n");
        exit(1);
    }
    
    // open source file
    int fd_src = open(argv[2], O_RDONLY);
    if (fd_src < 0){
        fprintf(stderr, "No such file exists in the native file system \n");
        exit(ENOENT);
    }

    int filesize_src = lseek(fd_src, 0, SEEK_END);
    // mmap cannot map size 0 file.
    if (filesize_src <= 0){
        fprintf(stderr, "The source file is empty \n");
        exit(ENOENT);
    }

    int req_block_num = (filesize_src - 1) / EXT2_BLOCK_SIZE + 1;

    // open the image
    int fd = open(argv[1], O_RDWR);
    if (fd < 0){
        fprintf(stderr, "No such virtual disk exists \n");
        exit(ENOENT);   
    }

    // map the virtual disk and source file on memory
    ptr_disk = mmap(NULL, BLOCK_NUM * BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    unsigned char* ptr_disk_src = mmap(NULL, filesize_src, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_src, 0);
    if (ptr_disk == MAP_FAILED || ptr_disk_src == MAP_FAILED)
    {
       perror("mmap");
       exit(1);
    }

    struct ext2_group_desc *ptr_group_desc = (struct ext2_group_desc *)(ptr_disk + EXT2_SB_OFFSET + EXT2_BLOCK_SIZE);
    // get the inode table
    struct ext2_inode *ptr_inode = (struct ext2_inode *)(ptr_disk + EXT2_BLOCK_SIZE * ptr_group_desc->bg_inode_table);
    unsigned char *bm_inode = (ptr_disk + (ptr_group_desc -> bg_inode_bitmap) * BLOCK_SIZE);
    unsigned char *bm_block = (ptr_disk + (ptr_group_desc -> bg_block_bitmap) * BLOCK_SIZE);
    struct ext2_super_block *ptr_super_block = (struct ext2_super_block *)(ptr_disk + EXT2_SB_OFFSET);
    char *ptr_path_src = strdup(argv[2]);
    char *ptr_path_dest = strdup(argv[3]);
    char *table_path_src[10];
    char *table_path_dest[10];
    int count_path_src = get_path_table(table_path_src, ptr_path_src);
    int count_path_dest = get_path_table(table_path_dest, ptr_path_dest);

    // Find the destination directory in the virtual disk
    struct ext2_dir_entry_2 *ptr_dir_dest = recurse_inode(ptr_inode + 1, table_path_dest, count_path_dest, 0, ptr_group_desc->bg_inode_table);

    if(ptr_dir_dest == 0)
    {
        printf("No such directory exists on virtual disk\n");
        return -1;
    }

    int table_new_block[req_block_num];
    int copy_flag = 0;

    int i = 0;
    while(i < req_block_num)
    {
        int free_block = get_free_block(bm_block, ptr_super_block);
        SETBIT(bm_block, free_block);
        table_new_block[i] = free_block;

        if(filesize_src - copy_flag <= BLOCK_SIZE)
        {
            memcpy(ptr_disk + EXT2_BLOCK_SIZE * (free_block + 1), ptr_disk_src + BLOCK_SIZE * i, filesize_src - copy_flag - 1);
        }
        else
        {
            memcpy(ptr_disk + EXT2_BLOCK_SIZE * (free_block + 1), ptr_disk_src + BLOCK_SIZE * i, EXT2_BLOCK_SIZE);
            copy_flag += BLOCK_SIZE;
        }
        i++;
    }

    int block_id_inderect;
    if(req_block_num > 11)
    {
        block_id_inderect = get_free_block(bm_block, ptr_super_block);
        int *indirect_block = (int *)(ptr_disk + EXT2_BLOCK_SIZE * (block_id_inderect + 1));
        SETBIT(bm_block, block_id_inderect);
        for(i = 12; i < req_block_num; i++)
        {
            *indirect_block = table_new_block[i];
            indirect_block++;
        }
    }

    int fr_inode = get_free_inode(bm_inode, ptr_super_block);
    struct ext2_inode *node_new = ptr_inode + (fr_inode);
    SETBIT(bm_inode, fr_inode);
    node_new->i_links_count = 1;
    node_new->i_mode = EXT2_S_IFREG;
    node_new->i_size = filesize_src;
    node_new->i_blocks = req_block_num * 2;

    i = 0;
    while (i < 11 && req_block_num != i)
    {
        node_new->i_block[i] = table_new_block[i];
        i++;
    }

    if(req_block_num > 11)
    {
        node_new -> i_block[12] = block_id_inderect;
    }

    struct ext2_inode *in_src = (struct ext2_inode *)(ptr_disk + EXT2_BLOCK_SIZE * ptr_group_desc->bg_inode_table);
    struct ext2_inode *in_cur = (struct ext2_inode *)(ptr_disk + EXT2_BLOCK_SIZE * ptr_group_desc->bg_inode_table);
    in_src = in_src + ptr_dir_dest -> inode - 1;
    in_cur = in_cur + ptr_dir_dest -> inode - 1;
    in_cur->i_links_count++;

    int len_req = strlen(table_path_src[count_path_src - 1]) + 8;
    struct ext2_dir_entry_2 *ptr_dir = get_free_space(in_cur, len_req);

    if(ptr_dir == 0)
    {
        int free_block_new = get_free_block(bm_block, ptr_super_block);
        ptr_dir = (void*)ptr_disk + EXT2_BLOCK_SIZE * (free_block_new + 1);
        ptr_dir -> inode = fr_inode + 1;
        ptr_dir -> name_len = strlen(table_path_dest[count_path_dest - 1]);
        ptr_dir -> file_type = EXT2_FT_DIR;
        strcpy(ptr_dir -> name, table_path_dest[count_path_dest - 1]);
        ptr_dir -> rec_len = BLOCK_SIZE;
        
        in_src -> i_blocks += 2;
        in_src ->i_block[in_src -> i_size / BLOCK_SIZE] = free_block_new + 1;
        in_src -> i_size += BLOCK_SIZE;
    }
    else
    {
        int new_rec_len = ptr_dir -> rec_len - (4 * (ptr_dir -> name_len) + 8);
        ptr_dir -> rec_len = 4 * (ptr_dir -> name_len) + 8;
        ptr_dir = (void*)ptr_dir + ptr_dir -> rec_len;
        ptr_dir -> rec_len = new_rec_len;
        ptr_dir -> inode = fr_inode + 1;
        ptr_dir -> name_len = strlen(table_path_dest[count_path_dest - 1]);
        ptr_dir -> file_type = EXT2_FT_REG_FILE;
        strcpy(ptr_dir -> name, table_path_dest[count_path_dest - 1]);
    }
    ptr_group_desc->bg_used_dirs_count++;
    return 0;
}
Пример #20
0
int main(int argc,char *argv[]) {
  int error = -1;
  int i;
  int flc;
  int index;
  int free_FLC;
  struct fileinfo info;
  int new_flc;
  int new_index; 
  int status;
  int num;
  char *last;
  char buffer[260];
  char buffer1[260];
  char file_name[10];
  char name[10];
  char ext[4];
  char* etmp;

  /*Checks number of arguments*/
  if(argc != 2) {
    printf("Please specify one directory.\n");
    return error;
  }
  /*Right number of arguments*/
  else {
    init_util();
    status = parse_path(argv[1],&flc,&index);
    
    /*Checks if directory exists*/
    if(status != E_NOTEXIST) {
      printf("Directory already exists.\n");
      return error;
    }
    /*Directory does not exist, make a new one!*/
    else {
      last = rindex(argv[1],'/');

      /*Check if path is relative*/
      if(last == 0) {
	get_abs_path(buffer1,argv[1]);
	last = rindex(buffer1,'/');
	num = (int)(last-buffer1+1);
	strncpy(buffer,buffer1,num);
	buffer[num] = '\0';
	//printf("Buffer is:%s\n",buffer);
	strcpy(name,argv[1]);
	//printf("I am here and name is:%s\n",name);
      }
      /*Path may still be relative, but there is at least one '/'*/
      else {
	/*Check if there is an ending '/'*/
	if(strlen(last) == 1) {         //Checks if the last character is "/"
	  get_abs_path(buffer, argv[1]);
	  //printf("Buffer is:%s\n",buffer);
	  strncpy(buffer1,buffer,(strlen(buffer)-1));
	  //printf("Buffer1 is:%s\n",buffer1);
	  buffer1[strlen(buffer)-1]='\0';
	  last = rindex(buffer1,'/');
	  if(last == 0) {
	    buffer[0] = '\0';
	    num = 1;
	  }
	  else {
	    num = (int)(last-buffer1+1);
	    strncpy(buffer,buffer1,num);
	    buffer[num] = '\0';
	    //printf("Buffer is:%s\n",buffer);
	    last = rindex(buffer1,'/');
	    if(last == 0) {
	      buffer[0] = '\0';
	    }
	  }
	}
	/*No ending '/', continue*/
	else {
	  //printf("Last is:%d\n",strlen(last));
	  num = (int)(last-argv[1]+1);
	  strncpy(buffer,argv[1],num);
	  strcpy(buffer1,argv[1]);
	  //printf("Buffer is:%s\n",buffer);
	  buffer[num] = '\0';
	}
	/*Check if the path is really relative*/
	if(argv[1][0] != '/' && last != 0) {
	  last = rindex(buffer1,'/');
	  num = (int)(last-buffer1+1);
	  //printf("%d\n",num);
          strcpy(name,&buffer1[num]);
        } 
	else if(argv[1][0] != '/' && last == 0) {
	  strcpy(name,buffer1);
	}
	/*Path is not relative, continue*/
	else {
	  strcpy(file_name,&buffer1[num]);  //Keeps track of the new directory name
	  //printf("%d\n",strlen(buffer1)-1);
	  file_name[strlen(buffer1)-1]='\0';
	  //printf("File name is:%s\n",file_name);
	  if(file_name[0] == '/') {       //Checks if the first character is the "/"
	    for(i=0;i<(strlen(buffer1)-1);i++) {
	      name[i] = file_name[i+1];
	    }
	    name[strlen(buffer1)-1]= '\0';
	  }
          else {
	    strcpy(name,file_name);
	  }
	}
      }
      
      //printf("num: %d buffer: %s\n", num, buffer);
      status = parse_path(buffer,&flc,&index);
      free_FLC = get_free_block();
      info = get_file_info(flc,index);
      info.attrib = '\x10';
      etmp = (char*)strtok(name, ".");
      strcpy(info.filename,etmp);
      etmp = (char*)strtok(NULL,".");
      strcpy(info.ext, ((etmp == NULL) ? "   " : etmp));
      allocate_block(free_FLC,info,info.FLC,&new_flc,&new_index);
      strcpy(info.filename,"..");
      strcpy(info.ext,"   ");
      allocate_block(0,info,free_FLC,&new_flc,&new_index);
      strcpy(info.filename,".");
      strcpy(info.ext,"   ");
      info.FLC = free_FLC;
      allocate_block(0,info,free_FLC,&new_flc,&new_index);
      return 1;
    }
  }
  kill_util();
}
Пример #21
0
/*
 *  ======== cmm_calloc_buf ========
 *  Purpose:
 *      Allocate a SM buffer, zero contents, and return the physical address
 *      and optional driver context virtual address(pp_buf_va).
 *
 *      The freelist is sorted in increasing size order. Get the first
 *      block that satifies the request and sort the remaining back on
 *      the freelist; if large enough. The kept block is placed on the
 *      inUseList.
 */
void *cmm_calloc_buf(struct cmm_object *hcmm_mgr, u32 usize,
		     struct cmm_attrs *pattrs, OUT void **pp_buf_va)
{
	struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
	void *buf_pa = NULL;
	struct cmm_mnode *pnode = NULL;
	struct cmm_mnode *new_node = NULL;
	struct cmm_allocator *allocator = NULL;
	u32 delta_size;
	u8 *pbyte = NULL;
	s32 cnt;

	if (pattrs == NULL)
		pattrs = &cmm_dfltalctattrs;

	if (pp_buf_va != NULL)
		*pp_buf_va = NULL;

	if (cmm_mgr_obj && (usize != 0)) {
		if (pattrs->ul_seg_id > 0) {
			/* SegId > 0 is SM */
			/* get the allocator object for this segment id */
			allocator =
			    get_allocator(cmm_mgr_obj, pattrs->ul_seg_id);
			/* keep block size a multiple of ul_min_block_size */
			usize =
			    ((usize - 1) & ~(cmm_mgr_obj->ul_min_block_size -
					     1))
			    + cmm_mgr_obj->ul_min_block_size;
			mutex_lock(&cmm_mgr_obj->cmm_lock);
			pnode = get_free_block(allocator, usize);
		}
		if (pnode) {
			delta_size = (pnode->ul_size - usize);
			if (delta_size >= cmm_mgr_obj->ul_min_block_size) {
				/* create a new block with the leftovers and
				 * add to freelist */
				new_node =
				    get_node(cmm_mgr_obj, pnode->dw_pa + usize,
					     pnode->dw_va + usize,
					     (u32) delta_size);
				if (new_node) {
					/* leftovers go free */
					add_to_free_list(allocator, new_node);
				}
				/* adjust our node's size */
				pnode->ul_size = usize;
			}
			/* Tag node with client process requesting allocation
			 * We'll need to free up a process's alloc'd SM if the
			 * client process goes away.
			 */
			/* Return TGID instead of process handle */
			pnode->client_proc = current->tgid;

			/* put our node on InUse list */
			lst_put_tail(allocator->in_use_list_head,
				     (struct list_head *)pnode);
			buf_pa = (void *)pnode->dw_pa;	/* physical address */
			/* clear mem */
			pbyte = (u8 *) pnode->dw_va;
			for (cnt = 0; cnt < (s32) usize; cnt++, pbyte++)
				*pbyte = 0;

			if (pp_buf_va != NULL) {
				/* Virtual address */
				*pp_buf_va = (void *)pnode->dw_va;
			}
		}
		mutex_unlock(&cmm_mgr_obj->cmm_lock);
	}
	return buf_pa;
}
Пример #22
0
int main(int argc, char const *argv[]){
	if(argc != 4) {
        fprintf(stderr, "Usage: ext2_cp <formatted virtual disk> <local path> <absolute disk path>\n");
        exit(1);
    }

    int fd = open(argv[1], O_RDWR);

    disk = mmap(NULL, 128 * EXT2_BLOCK_SIZE, PROT_READ 
    						| PROT_WRITE, MAP_SHARED, fd, 0);

    if(disk == MAP_FAILED) {
		perror("mmap");
		exit(1);
    }

    FILE * fp;
    fp = fopen(argv[2], "r");
    if (fp == NULL) {
    	printf("File not found\n");
    	exit(ENOENT);
    }
    //get file size
    fseek(fp, 0L, SEEK_END);
    int file_sz = ftell(fp);
    fseek(fp, 0L, SEEK_SET);
    //number of blocks needed to copy file
    int num_blocks_needed = (int) (file_sz / EXT2_BLOCK_SIZE) + 1;

    //get the superblock 
    struct ext2_super_block *superblock = (struct ext2_super_block *)
    										(disk + EXT2_BLOCK_SIZE);

    int first_data_block = superblock->s_first_data_block;

    if (num_blocks_needed > superblock->s_free_blocks_count){
    	fprintf(stderr, "No space left on device\n");
    	exit(ENOSPC);
    }

	// get the group descriptor table
	// we know that this table always start at third datablock (index 2)
	struct ext2_group_desc *group_des_table = (struct ext2_group_desc*)
												(disk + EXT2_BLOCK_SIZE * 2);
	int inode_bitmap = group_des_table->bg_inode_bitmap;
	int block_bitmap = group_des_table->bg_block_bitmap;
	int inode_table = group_des_table->bg_inode_table;
	void *tablestart = disk + EXT2_BLOCK_SIZE * inode_table;

	//check that the path does not already exist
	int found_inode;
	found_inode = search_inode(argv[3]);
    if (found_inode != -1){ // has to be not found
    	fprintf(stderr, "File exists\n");
        exit(EEXIST);
    }

    //get the parent directory into which to copy the file
    int parent_inode_num = parent_conversion(argv[3]);
    if (parent_inode_num == -1){
    	fprintf(stderr, "No such file or directory\n");
    	exit(ENOENT);
    }

    //get the inode of that parent directory
    struct ext2_inode *parent_inode = (struct ext2_inode*)
    									(tablestart) + (parent_inode_num - 1);
    if (parent_inode->i_mode & EXT2_S_IFREG){
    	fprintf(stderr, "No such file or directory\n");
    	exit(ENOENT); 
    }

	//get block bitmap
    int block_bitmap_block = block_bitmap * EXT2_BLOCK_SIZE;
    void * block_bits = (void *)(disk + block_bitmap_block);

    //get inode bitmap
    unsigned long inode_bitmap_block = inode_bitmap * EXT2_BLOCK_SIZE;
    void * inode_bits = (void *)(disk + inode_bitmap_block);

    //find free inode
    int inode_indx = get_free_inode(inode_bits);

    if (inode_indx == -1){
    	fprintf(stderr, "No space left on device\n");
    	exit(ENOSPC);
    }

    //update superblock
    superblock->s_free_inodes_count = superblock->s_free_inodes_count - 1;
    
    //init new inode
    struct ext2_inode *new_inode = (struct ext2_inode*)(tablestart) 
    													+ (inode_indx);
    new_inode->i_mode = 32768; //is file
    new_inode->i_size = file_sz;
    new_inode->i_blocks = 1;
    new_inode->i_links_count = 1;

    //global variables for indirect block if necessary
    void *indirect_block;
    unsigned int indr_block[15];
    void *data_block;

    int i;
    for (i = 0; i < num_blocks_needed; i++){
    	if (i < 12){
    		int free_block_num = get_free_block(block_bits);
    		if (free_block_num == -1){
    			fprintf(stderr, "No space left on device\n");
    			exit(ENOSPC);
    		}
    		superblock->s_free_blocks_count = superblock->s_free_blocks_count - 1;
    		new_inode->i_blocks += 1;
    		new_inode->i_block[i] = first_data_block + free_block_num -1;
    		data_block = (void *)(disk + (EXT2_BLOCK_SIZE * 
    													new_inode->i_block[i]));

    	}	
    	else if (i == 12){
    		//i_blocks[12] entry is the 13th entry in the array
    		//It holds the block number of the indirect block
    		//- this block contains an array of block numbers 
    		//for the next data blocks of the file.
    		//get free block for indirect block
    		int indirect_block_num = get_free_block(block_bits);
    		if (indirect_block_num == -1){
    			fprintf(stderr, "No space left on device\n");
    			exit(ENOSPC);
    		}
    		new_inode->i_block[i] = first_data_block + indirect_block_num;
    		//initialize indirect block
    		indirect_block = (void *)(disk + (EXT2_BLOCK_SIZE 
    											* new_inode->i_block[i]));
    		//get data block
    		int free_block_num = get_free_block(block_bits);
    		if (free_block_num == -1){
    			fprintf(stderr, "No space left on device\n");
    			exit(ENOSPC);
    		}
    		superblock->s_free_blocks_count = superblock->s_free_blocks_count - 1;
    		new_inode->i_blocks += 1;
    		indr_block[i - 12] = first_data_block + free_block_num -1;
    		memcpy(indirect_block, (void *) indr_block, 16);
    		data_block = (void *)(disk + (EXT2_BLOCK_SIZE * indr_block[i - 12]));
    	}
    	else if (i > 12){
    		int free_block_num = get_free_block(block_bits);
    		if (free_block_num == -1){
    			fprintf(stderr, "No space left on device\n");
    			exit(ENOSPC);
    		}
    		superblock->s_free_blocks_count = superblock->s_free_blocks_count - 1;
    		new_inode->i_blocks += 1;
    		indr_block[i - 12] = first_data_block + free_block_num -1;
    		memcpy(indirect_block, (void *) indr_block, 16);
    		data_block = (void *)(disk + (EXT2_BLOCK_SIZE * indr_block[i - 12]));
    	}

    	//read data from file to data block
    	int num_read = fread(data_block, 1, EXT2_BLOCK_SIZE, fp);
    	if (num_read == 0){
    		perror("Error reading file");
    	}
    }

    fclose(fp);

    //add this new file's directory entry to the parent directory
    int c;
    //loop through directory entries to get to the last entry
    for (c = 0; c < EXT2_BLOCK_SIZE;){
    	struct ext2_dir_entry_2 *node_dir = (struct ext2_dir_entry_2 *)
    				(disk + (EXT2_BLOCK_SIZE * parent_inode->i_block[0]) + c);

    	if (c + node_dir->rec_len == EXT2_BLOCK_SIZE){
    		//this is the last block in the directory
			int new_rec_len = node_dir->rec_len - node_dir->name_len - 8;
			node_dir->rec_len = node_dir->name_len + 8;

			//create directory entry
		    struct ext2_dir_entry_2 *par_dir = (struct ext2_dir_entry_2 *)
		    		(disk + (EXT2_BLOCK_SIZE * parent_inode->i_block[0] 
		    		+ c + node_dir->rec_len));

		    par_dir->inode = inode_indx + 1;
		    par_dir->file_type = 1;

		    //get name of new file
		    char dup_path[strlen(argv[3])];
		    strcpy(dup_path, argv[3]);
		    char *ret;
		    ret = strrchr(dup_path, '/');
		    if (ret[0] == '/'){
		    	ret++;
		    }
		    par_dir->rec_len = new_rec_len;
		    par_dir->name_len = strlen(ret);
		    strcpy(par_dir->name, ret);
		    break;
    	}
    	c += node_dir->rec_len;
    }
    return 0;
}
Пример #23
0
int mk_new_directory(jfs_t *jfs, char *pathname, 
		      int parent_inodenum, int grandparent_inodenum) 
{
    /* we need to create this directory */
    /* round size up to nearest 4 byte boundary */
    int size, prev_size, bytes_done=0;
    int new_inodenum, new_blocknum;
    char block[BLOCKSIZE];
    struct inode* new_inode, *parent_inode;

    /* calculate the size of the new parent dirent */
    size = (((strlen(pathname)/4) + 1) * 4) + 16;

    /* does it fit?*/
    if (bytes_done + size > BLOCKSIZE) {
	fprintf(stderr,
		"No more space in the directory to add another entry\n");
	exit(1);
    }

    /* allocate an inode for this directory */
    if (strcmp(pathname, ".")==0) {
	new_inodenum = parent_inodenum;
    } else if (strcmp(pathname, "..")==0) {
	new_inodenum = grandparent_inodenum;
    } else {
	new_inodenum = get_free_inode(jfs);
    }


    /* update the parent directories inode size field */
    jfs_read_block(jfs, block, inode_to_block(parent_inodenum));
    parent_inode = (struct inode*)(block + (parent_inodenum % INODES_PER_BLOCK)
				   * INODE_SIZE);

    prev_size = parent_inode->size;
    parent_inode->size += size;
    jfs_write_block(jfs, block, inode_to_block(parent_inodenum));

    /* create an entry in the parent directory */
    create_dirent(jfs, pathname, DT_DIRECTORY, parent_inode->blockptrs[0],
		  prev_size, size, new_inodenum);


    if (strcmp(pathname, ".")!=0 && strcmp(pathname, "..")!=0) {
	/* it's a real directory */

	/* get a block to hold the directory */
	new_blocknum = get_free_block(jfs);

	/* read in the block that contains our new inode */
	jfs_read_block(jfs, block, inode_to_block(new_inodenum));
	
	new_inode = (struct inode*)(block + (new_inodenum % INODES_PER_BLOCK)
				    * INODE_SIZE);
	new_inode->flags = FLAG_DIR;
	new_inode->blockptrs[0] = new_blocknum;
	new_inode->size = 0;
	
	/* write back the inode block */
	jfs_write_block(jfs, block, inode_to_block(new_inodenum));
	return new_inodenum;
    }

    return parent_inodenum;
}
Пример #24
0
Файл: mm.c Проект: yuriyao/PS
void* Ps_Malloc(long size)
{
	struct mm_block *block;
	char *ret;
	int index;
	int d = size;

	size += sizeof(struct mm_head);
	index = SIZE2INDEX(size);
	size = ROUND(size);

	//待申请的内存太大,使用普通的内存分配方法
	if(size > SMALL_MEM_LIMIT)
	{
		ret = (char*)malloc(size);
		/*((struct mm_head*)ret)->size = size;
		ret += sizeof(struct mm_head);
		return ret;*/
		WRAP_TO_RET(ret, size);
	}
	MM_GET_LOCK();
	if(mm_structs[index].frees)
	{
		ret = (char*)(mm_structs[index].frees);
		mm_structs[index].frees = (void*)(*(long*)ret);
		/*((struct mm_head*)ret)->size = size;
		ret += sizeof(struct mm_head);
		return ret;*/
		WRAP_TO_RET(ret, size);
	}

	//没有找到适合的内存块
	if(get_perfect_index(size) == -1)
	{
		block = get_free_block();
		if(!block)
		{
			MM_RELEASE_LOCK();
			return NULL;
		}
		block->next = mm_structs[index].block;
		mm_structs[index].block = block;
		block->begin = (void*)((char*)block + BLOCK_STRUCT_SIZE);
		ret = block->begin;
		block->free_number = (BLOCK_SIZE - BLOCK_STRUCT_SIZE) / size - 1;
		block->frees = (void*)((char*)ret + size);
		WRAP_TO_RET(ret, size);
	}
	else
	{
		int pi = get_perfect_index(size);
		int tmp;
		int remain;
		assert(mm_structs[pi].block->free_number > 0);
		if(pi < index)
		{
			tmp = (index + 1) / (pi + 1);
			tmp = (tmp * (pi + 1) == index + 1) ? tmp : (tmp + 1);
			ret = mm_structs[pi].block->frees;
			remain = tmp * INDEX2SIZE(pi) - size;
			assert(tmp <= mm_structs[pi].block->free_number);
			mm_structs[pi].block->free_number -= tmp;
			mm_structs[pi].block->frees = (void*)((char*)mm_structs[pi].block->frees + tmp * INDEX2SIZE(pi));

			assert(remain >= 0);
			assert(remain < size);
			if(remain)
			{
				struct mm_head *head = (struct mm_head*)(ret + size);
				*(long*)head = (long)mm_structs[SIZE2INDEX(remain)].frees;
				mm_structs[SIZE2INDEX(remain)].frees = (void*)head;
			}
			WRAP_TO_RET(ret, size);
		}
		else if(pi == index)
		{
			mm_structs[index].block->free_number --;
			ret = (char*)mm_structs[index].block->frees;
			mm_structs[index].block->frees = (void*)((char*)ret + size);
			WRAP_TO_RET(ret, size);
		}
		else
		{
			void *rp;
			mm_structs[pi].block->free_number --;
			ret = (char*)mm_structs[pi].block->frees;
			mm_structs[pi].block->frees = (void*)((char*)ret + INDEX2SIZE(pi));
			remain = INDEX2SIZE(pi) - size;
			rp = ret + size;
			*(long*)rp = (long)mm_structs[SIZE2INDEX(remain)].frees;
			mm_structs[SIZE2INDEX(remain)].frees = rp;
			WRAP_TO_RET(ret, size);
		}

	}

}
Пример #25
0
/* Reads from or writes to the given sector at bytes i such that from <= i < to,
 * reading them to or writing them from buffer. buffer must have size at least
 * from - to. 
 *
 * For internal use.
 */
static void
cached_read_write(block_sector_t sector, bool write,
                  uint32_t from, uint32_t to, void *buffer)
{
    ASSERT (from < to);
    ASSERT (to <= BLOCK_SECTOR_SIZE);

    struct cached_block *cb;
    while (true) {
        reader_acquire(&sector_lock);
        cb = find_cached_sector(sector);
        if (cb != NULL) {
            reader_release(&sector_lock);
            rw_acquire(&cb->rw_lock, write);
            if (cb->sector == sector && (cb->state == CLEAN || cb->state == DIRTY)) {
                /* Typical case: Found the sector in cache, and it didn't
                 * change before we got a chance to see it. */

                if (write) {
                    memcpy(cb->data + from, buffer, (to - from));
                    cb->state = DIRTY;
                }
                else {
                    memcpy(buffer, cb->data + from, (to - from));
                }

                cb->accessed = true;  /* XXX synchronized? */
                rw_release(&cb->rw_lock, write);
                return;
            }
            /* Atypical case: We found the sector in cache, but it changed
             * before we got a chance to see it: Try again. */
            rw_release(&cb->rw_lock, write);
        } else {
            cb = get_free_block();
            reader_release(&sector_lock);
            writer_acquire(&sector_lock);
            if (find_cached_sector(sector) == NULL) {
                /* Typical case: We didn't find the sector in cache, and it
                 * didn't pop up before we could add it */
                cb->sector = sector;
                cb->state = IN_IO;
                writer_release(&sector_lock);

                block_read(fs_device, cb->sector, cb->data);
                cb->state = CLEAN;

                if (write) {
                    memcpy(cb->data + from, buffer, (to - from));
                    cb->state = DIRTY;
                }
                else {
                    memcpy(buffer, cb->data + from, (to - from));
                }

                cb->accessed = true;
                writer_release(&cb->rw_lock);
                return;
            }
            /* Atypical case: We didn't find the sector in cache, but it
             * popped up before we could add it: Try again. */
            writer_release(&sector_lock);
            writer_release(&cb->rw_lock);
        }
    }
}
Пример #26
0
/**
 * Allocate a block of memory
 *
 * @param sz size of the required block
 * @returns pointer to block
 */
void *kmalloc(u32 sz)
{
	kerror(ERR_DETAIL, "Allocating %d bytes of memory", sz);

	// We don't want two processes using the same memory block!
	lock(&alloc_lock);

	// Find the smallest memory block that we can use
	u32 idx = find_hole(sz);

	// Couldn't find one...
	if(idx == 0xFFFFFFFF) return 0;

	int block = idx >> 16;
	int index = idx & 0xFFFF;

	if(empty_slots(block) == 4) // Get ready ahead of time
	{
		u32 asz = ALLOC_BLOCK * sizeof(struct alcent);

		u32 idx = find_hole(asz);
		if(idx == 0xFFFFFFFF) kpanic("Could not create another allocation block!");

		int block = idx >> 16;
		int index = idx & 0xFFFF;

		if(allocs[block][index].size == asz)
		{
			allocs[block][index].used = 1;
			allocs[get_free_block()] = (struct alcent *)allocs[block][index].addr;
		}
		else
		{
			allocs[block][index].size -= asz;
			struct alcent ae = { .valid = 1, .used = 1, .addr = allocs[block][index].addr, .size = asz };
			allocs[block][index].addr += asz;
			add_alloc(&ae);
			allocs[get_free_block()] = (struct alcent *)ae.addr;
		}
	}

	// If the previous block of code was used, we may have to reinitialize these
	idx = find_hole(sz);
	if(idx == 0xFFFFFFFF) return 0;
	block = idx >> 16;
	index = idx & 0xFFFF;


	if(allocs[block][index].size == sz)
	{
		allocs[block][index].used = 1;
		unlock(&alloc_lock);
		kerror(ERR_DETAIL, "  -> %08X W", allocs[block][index].addr);
		return (void *)allocs[block][index].addr;
	}

	allocs[block][index].size -= sz; // We are using part of this block

	struct alcent ae = { .valid = 1, .used = 1, .addr = allocs[block][index].addr, .size = sz };

	allocs[block][index].addr += sz; // We don't want anything else using the allocated memory

	add_alloc(&ae); // We will just assume this worked, the worst that could happen is we can't `free` it (FIXME)

	// Let other processes allocate memory
	unlock(&alloc_lock);

	kerror(ERR_DETAIL, "  -> %08X P", ae.addr);
	return (void *)ae.addr;
}

/**
 * Free an allocated block of memory
 *
 * @param ptr pointer to the previously allocated memory block
 */
void kfree(void *ptr)
{
	kerror(ERR_DETAIL, "Freeing %08X", ptr);

	lock(&alloc_lock);

	int i, j = 0;

	// Find the corresponding memory block
	for(; j < ALLOC_BLOCKS; j++)
	{
		if(!allocs[j]) continue;
		for(i = 0; i < ALLOC_BLOCK; i++)
			if(allocs[j][i].valid) // Is it valid?
				if(allocs[j][i].addr == (u32)ptr) // Is it the correct block?
					rm_alloc(j, i); // Free it!
	}

	unlock(&alloc_lock);
}