示例#1
0
文件: seguse.c 项目: ppadala/lfs
/* Primary function to update the seguse_table. Updates the segusage entry for
 * the partiulcar segment.
 */
void segusetbl_update_entry(struct super_block *sb, int segnum, 
			    struct segusage *seguse)
{
	int offset;
	sector_t newblock;
	struct buffer_head *bh;
	struct inode *inode = SEGUSETBL_INODE(sb);
	struct segusage *pseguse = NULL;

	if(is_new_segment(segnum, inode))
		inode->i_size += LFS_SEGUSE_SIZE;
	bh = segusetbl_read_entry(sb, segnum, &pseguse);
	/* update the seguse_table */
	if(bh) {
		/* updating the in-memory contents */
		//dprintk("Updating in-memory contents\n");
		offset = LFS_CI_SIZE + LFS_SEGUSE_SIZE * segnum;
		offset = offset % LFS_BSIZE;
		//dprintk("Updating at offset = %d\n", offset);
		newblock = segment_write_block_from_bh(
			 	sb, seguse, LFS_SEGUSE_SIZE, offset, bh);
		if(newblock != bh->b_blocknr)
			update_inode(inode, get_iblock_nr(segnum), newblock);
		brelse(bh);
	}
	else {	
		/* new seguse entry */
		offset = 0;
		newblock = segment_write_block(	sb, seguse, LFS_SEGUSE_SIZE, 
						offset, 0);
		update_inode(inode, get_iblock_nr(segnum), newblock);
		//dprintk("updating %Lu to %Lu block\n", get_iblock_nr(segp), newblock);
	}
	mark_inode_dirty(inode);
}
bool recover_inline_data(struct inode *inode, struct page *npage)
{
    struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
    struct f2fs_inode *ri = NULL;
    void *src_addr, *dst_addr;
    struct page *ipage;

    /*
     * The inline_data recovery policy is as follows.
     * [prev.] [next] of inline_data flag
     *    o       o  -> recover inline_data
     *    o       x  -> remove inline_data, and then recover data blocks
     *    x       o  -> remove inline_data, and then recover inline_data
     *    x       x  -> recover data blocks
     */
    if (IS_INODE(npage))
        ri = F2FS_INODE(npage);

    if (f2fs_has_inline_data(inode) &&
            ri && (ri->i_inline & F2FS_INLINE_DATA)) {
process_inline:
        ipage = get_node_page(sbi, inode->i_ino);
        f2fs_bug_on(sbi, IS_ERR(ipage));

        f2fs_wait_on_page_writeback(ipage, NODE);

        src_addr = inline_data_addr(npage);
        dst_addr = inline_data_addr(ipage);
        memcpy(dst_addr, src_addr, MAX_INLINE_DATA);

        set_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
        set_inode_flag(F2FS_I(inode), FI_DATA_EXIST);

        update_inode(inode, ipage);
        f2fs_put_page(ipage, 1);
        return true;
    }

    if (f2fs_has_inline_data(inode)) {
        ipage = get_node_page(sbi, inode->i_ino);
        f2fs_bug_on(sbi, IS_ERR(ipage));
        truncate_inline_inode(ipage, 0);
        f2fs_clear_inline_inode(inode);
        update_inode(inode, ipage);
        f2fs_put_page(ipage, 1);
    } else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) {
        truncate_blocks(inode, 0, false);
        goto process_inline;
    }
    return false;
}
示例#3
0
void f2fs_drop_nlink(struct inode *dir, struct inode *inode, struct page *page)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);

	down_write(&F2FS_I(inode)->i_sem);

	if (S_ISDIR(inode->i_mode)) {
		drop_nlink(dir);
		if (page)
			update_inode(dir, page);
		else
			update_inode_page(dir);
	}
	inode->i_ctime = CURRENT_TIME;

	drop_nlink(inode);
	if (S_ISDIR(inode->i_mode)) {
		drop_nlink(inode);
		i_size_write(inode, 0);
	}
	up_write(&F2FS_I(inode)->i_sem);
	update_inode_page(inode);

	if (inode->i_nlink == 0)
		add_orphan_inode(sbi, inode->i_ino);
	else
		release_orphan_inode(sbi);
}
示例#4
0
int gen_inum(MFS_Header_t **header, int offset) {
	int i, j, tmp_offset;
	MFS_Imap_t *imap_temp;
	void *block_ptr = (void *)(*header) + sizeof(MFS_Header_t);
	i = 0;
	while(i < 4096/ 14) {

		if((*header)->map[i] == -1) {
			imap_temp = allot_space(header, sizeof(MFS_Imap_t), &tmp_offset);
			
			for(j = 0; j < 14; j++) {
				imap_temp->inodes[j] = -1;
			}
			
			imap_temp->inodes[0] = offset;
			(*header)->map[i] = tmp_offset;
			
			return (i * 14) + 0;
		} else {
			imap_temp = (MFS_Imap_t *)(block_ptr + (*header)->map[i]);
			
			for(j = 0; j < 14; j++) {
				if(imap_temp->inodes[j] == -1) {
					update_inode(header, (i * 14) + j, offset);
					return (i * 14) + j;
				}
			}
		}
		i++;
	}
	return -1;
}
示例#5
0
文件: inline.c 项目: 7799/linux
int recover_inline_data(struct inode *inode, struct page *npage)
{
	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
	struct f2fs_inode *ri = NULL;
	void *src_addr, *dst_addr;
	struct page *ipage;

	/*
	 * The inline_data recovery policy is as follows.
	 * [prev.] [next] of inline_data flag
	 *    o       o  -> recover inline_data
	 *    o       x  -> remove inline_data, and then recover data blocks
	 *    x       o  -> remove inline_data, and then recover inline_data
	 *    x       x  -> recover data blocks
	 */
	if (IS_INODE(npage))
		ri = F2FS_INODE(npage);

	if (f2fs_has_inline_data(inode) &&
			ri && ri->i_inline & F2FS_INLINE_DATA) {
process_inline:
		ipage = get_node_page(sbi, inode->i_ino);
		f2fs_bug_on(IS_ERR(ipage));

		src_addr = inline_data_addr(npage);
		dst_addr = inline_data_addr(ipage);
		memcpy(dst_addr, src_addr, MAX_INLINE_DATA);
		update_inode(inode, ipage);
		f2fs_put_page(ipage, 1);
		return -1;
	}

	if (f2fs_has_inline_data(inode)) {
		ipage = get_node_page(sbi, inode->i_ino);
		f2fs_bug_on(IS_ERR(ipage));
		zero_user_segment(ipage, INLINE_DATA_OFFSET,
				 INLINE_DATA_OFFSET + MAX_INLINE_DATA);
		clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
		update_inode(inode, ipage);
		f2fs_put_page(ipage, 1);
	} else if (ri && ri->i_inline & F2FS_INLINE_DATA) {
		truncate_blocks(inode, 0);
		set_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
		goto process_inline;
	}
	return 0;
}
示例#6
0
文件: filemap.c 项目: wtaysom/tau
static int change_root_fmap (tree_s *tree, buf_s *root)
{
	info_s	*file = container(tree, info_s, in_tree);
	int	rc;
FN;
	file->in_inode.i_root = root->b_blkno;
	rc = update_inode( &file->in_inode);
	return rc;
}
示例#7
0
int update_inode_page(struct inode *inode)
{
	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
	struct page *node_page;

	node_page = get_node_page(sbi, inode->i_ino);
	if (IS_ERR(node_page))
		return PTR_ERR(node_page);

	update_inode(inode, node_page);
	f2fs_put_page(node_page, 1);
	return 0;
}
示例#8
0
文件: inode.c 项目: Abioy/kasan
void update_inode_page(struct inode *inode)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	struct page *node_page;
retry:
	node_page = get_node_page(sbi, inode->i_ino);
	if (IS_ERR(node_page)) {
		int err = PTR_ERR(node_page);
		if (err == -ENOMEM) {
			cond_resched();
			goto retry;
		} else if (err != -ENOENT) {
			f2fs_stop_checkpoint(sbi);
		}
		return;
	}
	update_inode(inode, node_page);
	f2fs_put_page(node_page, 1);
}
示例#9
0
int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
{
	struct page *page;
	int err = 0;

	down_write(&F2FS_I(inode)->i_sem);
	page = init_inode_metadata(inode, dir, NULL);
	if (IS_ERR(page)) {
		err = PTR_ERR(page);
		goto fail;
	}
	/* we don't need to mark_inode_dirty now */
	update_inode(inode, page);
	f2fs_put_page(page, 1);

	clear_inode_flag(F2FS_I(inode), FI_NEW_INODE);
fail:
	up_write(&F2FS_I(inode)->i_sem);
	return err;
}
示例#10
0
/*
 * Caller should grab and release a rwsem by calling f2fs_lock_op() and
 * f2fs_unlock_op().
 */
int __f2fs_add_link(struct inode *dir, const struct qstr *name,
						struct inode *inode)
{
	unsigned int bit_pos;
	unsigned int level;
	unsigned int current_depth;
	unsigned long bidx, block;
	f2fs_hash_t dentry_hash;
	struct f2fs_dir_entry *de;
	unsigned int nbucket, nblock;
	size_t namelen = name->len;
	struct page *dentry_page = NULL;
	struct f2fs_dentry_block *dentry_blk = NULL;
	int slots = GET_DENTRY_SLOTS(namelen);
	struct page *page;
	int err = 0;
	int i;

	dentry_hash = f2fs_dentry_hash(name);
	level = 0;
	current_depth = F2FS_I(dir)->i_current_depth;
	if (F2FS_I(dir)->chash == dentry_hash) {
		level = F2FS_I(dir)->clevel;
		F2FS_I(dir)->chash = 0;
	}

start:
	if (unlikely(current_depth == MAX_DIR_HASH_DEPTH))
		return -ENOSPC;

	/* Increase the depth, if required */
	if (level == current_depth)
		++current_depth;

	nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level);
	nblock = bucket_blocks(level);

	bidx = dir_block_index(level, F2FS_I(dir)->i_dir_level,
				(le32_to_cpu(dentry_hash) % nbucket));

	for (block = bidx; block <= (bidx + nblock - 1); block++) {
		dentry_page = get_new_data_page(dir, NULL, block, true);
		if (IS_ERR(dentry_page))
			return PTR_ERR(dentry_page);

		dentry_blk = kmap(dentry_page);
		bit_pos = room_for_filename(dentry_blk, slots);
		if (bit_pos < NR_DENTRY_IN_BLOCK)
			goto add_dentry;

		kunmap(dentry_page);
		f2fs_put_page(dentry_page, 1);
	}

	/* Move to next level to find the empty slot for new dentry */
	++level;
	goto start;
add_dentry:
	f2fs_wait_on_page_writeback(dentry_page, DATA);

	down_write(&F2FS_I(inode)->i_sem);
	page = init_inode_metadata(inode, dir, name);
	if (IS_ERR(page)) {
		err = PTR_ERR(page);
		goto fail;
	}
	de = &dentry_blk->dentry[bit_pos];
	de->hash_code = dentry_hash;
	de->name_len = cpu_to_le16(namelen);
	memcpy(dentry_blk->filename[bit_pos], name->name, name->len);
	de->ino = cpu_to_le32(inode->i_ino);
	set_de_type(de, inode);
	for (i = 0; i < slots; i++)
		test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
	set_page_dirty(dentry_page);

	/* we don't need to mark_inode_dirty now */
	F2FS_I(inode)->i_pino = dir->i_ino;
	update_inode(inode, page);
	f2fs_put_page(page, 1);

	update_parent_metadata(dir, inode, current_depth);
fail:
	up_write(&F2FS_I(inode)->i_sem);

	if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) {
		update_inode_page(dir);
		clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR);
	}
	kunmap(dentry_page);
	f2fs_put_page(dentry_page, 1);
	return err;
}
示例#11
0
static int __f2fs_setxattr(struct inode *inode, int index,
			const char *name, const void *value, size_t size,
			struct page *ipage, int flags)
{
	struct f2fs_inode_info *fi = F2FS_I(inode);
	struct f2fs_xattr_entry *here, *last;
	void *base_addr;
	int found, newsize;
	size_t len;
	__u32 new_hsize;
	int error = -ENOMEM;

	if (name == NULL)
		return -EINVAL;

	if (value == NULL)
		size = 0;

	len = strlen(name);

	if (len > F2FS_NAME_LEN || size > MAX_VALUE_LEN(inode))
		return -ERANGE;

	base_addr = read_all_xattrs(inode, ipage);
	if (!base_addr)
		goto exit;

	/* find entry with wanted name. */
	here = __find_xattr(base_addr, index, len, name);

	found = IS_XATTR_LAST_ENTRY(here) ? 0 : 1;

	if ((flags & XATTR_REPLACE) && !found) {
		error = -ENODATA;
		goto exit;
	} else if ((flags & XATTR_CREATE) && found) {
		error = -EEXIST;
		goto exit;
	}

	last = here;
	while (!IS_XATTR_LAST_ENTRY(last))
		last = XATTR_NEXT_ENTRY(last);

	newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + len + size);

	/* 1. Check space */
	if (value) {
		int free;
		/*
		 * If value is NULL, it is remove operation.
		 * In case of update operation, we caculate free.
		 */
		free = MIN_OFFSET(inode) - ((char *)last - (char *)base_addr);
		if (found)
			free = free + ENTRY_SIZE(here);

		if (unlikely(free < newsize)) {
			error = -ENOSPC;
			goto exit;
		}
	}

	/* 2. Remove old entry */
	if (found) {
		/*
		 * If entry is found, remove old entry.
		 * If not found, remove operation is not needed.
		 */
		struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here);
		int oldsize = ENTRY_SIZE(here);

		memmove(here, next, (char *)last - (char *)next);
		last = (struct f2fs_xattr_entry *)((char *)last - oldsize);
		memset(last, 0, oldsize);
	}

	new_hsize = (char *)last - (char *)base_addr;

	/* 3. Write new entry */
	if (value) {
		char *pval;
		/*
		 * Before we come here, old entry is removed.
		 * We just write new entry.
		 */
		memset(last, 0, newsize);
		last->e_name_index = index;
		last->e_name_len = len;
		memcpy(last->e_name, name, len);
		pval = last->e_name + len;
		memcpy(pval, value, size);
		last->e_value_size = cpu_to_le16(size);
		new_hsize += newsize;
	}

	error = write_all_xattrs(inode, new_hsize, base_addr, ipage);
	if (error)
		goto exit;

	if (is_inode_flag_set(fi, FI_ACL_MODE)) {
		inode->i_mode = fi->i_acl_mode;
		inode->i_ctime = CURRENT_TIME;
		clear_inode_flag(fi, FI_ACL_MODE);
	}

	if (ipage)
		update_inode(inode, ipage);
	else
		update_inode_page(inode);
exit:
	kzfree(base_addr);
	return error;
}
示例#12
0
int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name,
                          struct inode *inode, nid_t ino, umode_t mode)
{
    struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
    struct page *ipage;
    unsigned int bit_pos;
    f2fs_hash_t name_hash;
    size_t namelen = name->len;
    struct f2fs_inline_dentry *dentry_blk = NULL;
    struct f2fs_dentry_ptr d;
    int slots = GET_DENTRY_SLOTS(namelen);
    struct page *page = NULL;
    int err = 0;

    ipage = get_node_page(sbi, dir->i_ino);
    if (IS_ERR(ipage))
        return PTR_ERR(ipage);

    dentry_blk = inline_data_addr(ipage);
    bit_pos = room_for_filename(&dentry_blk->dentry_bitmap,
                                slots, NR_INLINE_DENTRY);
    if (bit_pos >= NR_INLINE_DENTRY) {
        err = f2fs_convert_inline_dir(dir, ipage, dentry_blk);
        if (!err)
            err = -EAGAIN;
        goto out;
    }

    if (inode) {
        down_write(&F2FS_I(inode)->i_sem);
        page = init_inode_metadata(inode, dir, name, ipage);
        if (IS_ERR(page)) {
            err = PTR_ERR(page);
            goto fail;
        }
    }

    f2fs_wait_on_page_writeback(ipage, NODE);

    name_hash = f2fs_dentry_hash(name);
    make_dentry_ptr(NULL, &d, (void *)dentry_blk, 2);
    f2fs_update_dentry(ino, mode, &d, name, name_hash, bit_pos);

    set_page_dirty(ipage);

    /* we don't need to mark_inode_dirty now */
    if (inode) {
        F2FS_I(inode)->i_pino = dir->i_ino;
        update_inode(inode, page);
        f2fs_put_page(page, 1);
    }

    update_parent_metadata(dir, inode, 0);
fail:
    if (inode)
        up_write(&F2FS_I(inode)->i_sem);

    if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) {
        update_inode(dir, ipage);
        clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR);
    }
out:
    f2fs_put_page(ipage, 1);
    return err;
}
示例#13
0
/* FIXME: Ugliest function of all in LFS, need I say more? */
static ssize_t lfs_file_write( 	struct file *file, const char __user *buf, 	
				size_t count, loff_t *ppos)
{	
	loff_t pos;
	struct page *page;
	ssize_t res, written, bytes;
	struct inode *inode = file->f_dentry->d_inode;
	struct super_block *sb = inode->i_sb;
	struct segment *segp = LFS_SBI(sb)->s_curr;

	//dprintk("lfs_file_write called for %lu at pos %Lu\n", inode->i_ino, *ppos);
	if(file->f_flags & O_DIRECT) {
		dprintk("The file is requesting direct IO\n");
		return -EINVAL;
	}

	if (unlikely(count < 0 ))
		return -EINVAL;
	if (unlikely(!access_ok(VERIFY_READ, buf, count)))
		return -EFAULT;

	//down(&inode->i_sem);	/* lock the file */
	mutex_lock(&inode->i_mutex); //BrechREiZ: We need this for Kernel 2.6.17
	lfs_lock(sb);
		
	pos = *ppos;
	res = generic_write_checks(file, &pos, &count, 0);
	if (res)
		goto out;
	if(count == 0)
		goto out;
	
	res = remove_suid(file->f_dentry);
	if(res)
		goto out;
	//inode_update_time(inode, 1);	/* update mtime and ctime */
	file_update_time(inode); //BrechREiZ: We need this for Kernel 2.6.17

	written = 0;
	do {
		long offset;
		size_t copied;
		int i, siblock, eiblock, boffset;
		sector_t block;
				
		offset = (segp->offset % BUF_IN_PAGE) * LFS_BSIZE; 
		offset += pos & (LFS_BSIZE - 1); /* within block */
		bytes = PAGE_CACHE_SIZE - offset; /* number of bytes written
						     in this iteration */
		invalidate_old_page(inode, pos);

		if (bytes > count) 
			bytes = count;
		
		//dprintk("1:segp->start=%Lu,segp->offset=%d,segp->end=%Lu,offset=%lu,bytes=%d\n", segp->start, segp->offset, segp->end,offset,bytes);
		
		siblock = pos >> LFS_BSIZE_BITS;
		eiblock = (pos + bytes - 1) >> LFS_BSIZE_BITS;

		//dprintk("writing %d bytes at offset %ld (pos = %Lu)\n", bytes, offset, pos);
		//dprintk("siblock = %d, eiblock = %d\n", siblock, eiblock);
		

		/*
		 * Bring in the user page that we will copy from _first_.
		 * Otherwise there's a nasty deadlock on copying from the
		 * same page as we're writing to, without it being marked
		 * up-to-date.
		 */
		fault_in_pages_readable(buf, bytes);
		page = get_seg_page(segp);
		if (!page) {
			res = -ENOMEM;
			break;
		}

		/* fill the page with current inode blocks if any */
		boffset = offset / LFS_BSIZE;;
		for(i = siblock; i <= eiblock; ++i, ++boffset) {
			struct buffer_head *bh;
			//dprintk("Asking for block %d\n", i);
			bh = lfs_read_block(inode, i);
			if(!bh) /* new block */
				break;
			//dprintk("boffset = %d\n", boffset);
			memcpy(page_address(page) + LFS_BSIZE * boffset, bh->b_data, LFS_BSIZE);
			brelse(bh);
		}

		copied = __copy_from_user(page_address(page) + offset, buf, bytes);
		flush_dcache_page(page);

		block = segp->start + segp->offset;
		for(i = siblock;i <= eiblock; ++i, ++block)
			segsum_update_finfo(segp, inode->i_ino, i, block);

		block = segp->start + segp->offset;
		segp->offset += (bytes  - 1)/LFS_BSIZE + 1;
		//dprintk("2:segp->start=%Lu,segp->offset=%d,segp->end=%Lu,offset=%lu,bytes=%d\n",
		//segp->start, segp->offset, segp->end,offset,bytes);
		BUG_ON(segp->start + segp->offset > segp->end);
		if(segp->start + segp->offset == segp->end) {
			dprintk("allocating new segment\n");
			/* This also is going to write the previous segment */
			segment_allocate_new(inode->i_sb, segp, segp->start + segp->offset);
			segp = LFS_SBI(sb)->s_curr;
		}

		/* update the inode */
		for(i = siblock;i <= eiblock; ++i, ++block)
			update_inode(inode, i, block);
		//dprintk("start=%Lu,offset=%d,end=%Lu\n", segp->start, segp->offset, segp->end);
		segusetbl_add_livebytes(sb, segp->segnum, bytes);
		
		written += bytes;
		buf += bytes;
		pos += bytes;
		count -= bytes;
	} while(count);

	*ppos = pos;
	if(pos > inode->i_size)
		i_size_write(inode, pos);
	if(written)
		mark_inode_dirty(inode);
	
	lfs_unlock(sb);
	//up(&inode->i_sem);
	mutex_unlock(&inode->i_mutex); //BrechREiZ: and unlocking...
	return written ? written : res;
out:
	lfs_unlock(sb);
	//up(&inode->i_sem);
	mutex_unlock(&inode->i_mutex); //BrechREiZ: and unlocking...
	return res; 
}
示例#14
0
int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name,
						struct inode *inode)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
	struct page *ipage;
	unsigned int bit_pos;
	f2fs_hash_t name_hash;
	struct f2fs_dir_entry *de;
	size_t namelen = name->len;
	struct f2fs_inline_dentry *dentry_blk = NULL;
	int slots = GET_DENTRY_SLOTS(namelen);
	struct page *page;
	int err = 0;
	int i;

	name_hash = f2fs_dentry_hash(name);

	ipage = get_node_page(sbi, dir->i_ino);
	if (IS_ERR(ipage))
		return PTR_ERR(ipage);

	dentry_blk = inline_data_addr(ipage);
	bit_pos = room_for_filename(&dentry_blk->dentry_bitmap,
						slots, NR_INLINE_DENTRY);
	if (bit_pos >= NR_INLINE_DENTRY) {
		err = f2fs_convert_inline_dir(dir, ipage, dentry_blk);
		if (!err)
			err = -EAGAIN;
		goto out;
	}

	down_write(&F2FS_I(inode)->i_sem);
	page = init_inode_metadata(inode, dir, name, ipage);
	if (IS_ERR(page)) {
		err = PTR_ERR(page);
		goto fail;
	}

	f2fs_wait_on_page_writeback(ipage, NODE);
	de = &dentry_blk->dentry[bit_pos];
	de->hash_code = name_hash;
	de->name_len = cpu_to_le16(namelen);
	memcpy(dentry_blk->filename[bit_pos], name->name, name->len);
	de->ino = cpu_to_le32(inode->i_ino);
	set_de_type(de, inode);
	for (i = 0; i < slots; i++)
		test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
	set_page_dirty(ipage);

	/* we don't need to mark_inode_dirty now */
	F2FS_I(inode)->i_pino = dir->i_ino;
	update_inode(inode, page);
	f2fs_put_page(page, 1);

	update_parent_metadata(dir, inode, 0);
fail:
	up_write(&F2FS_I(inode)->i_sem);

	if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) {
		update_inode(dir, ipage);
		clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR);
	}
out:
	f2fs_put_page(ipage, 1);
	return err;
}
示例#15
0
struct inode *f2fs_iget_nowait(struct super_block *sb, unsigned long ino)
{
	struct f2fs_iget_args args = {
		.ino = ino,
		.on_free = 0
	};
	struct inode *inode = ilookup5(sb, ino, f2fs_iget_test, &args);

	if (inode)
		return inode;
	if (!args.on_free)
		return f2fs_iget(sb, ino);
	return ERR_PTR(-ENOENT);
}

static int do_read_inode(struct inode *inode)
{
	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
	struct f2fs_inode_info *fi = F2FS_I(inode);
	struct page *node_page;
	struct f2fs_node *rn;
	struct f2fs_inode *ri;

	/* Check if ino is within scope */
	check_nid_range(sbi, inode->i_ino);

	node_page = get_node_page(sbi, inode->i_ino);
	if (IS_ERR(node_page))
		return PTR_ERR(node_page);

	rn = page_address(node_page);
	ri = &(rn->i);

	inode->i_mode = le16_to_cpu(ri->i_mode);
	i_uid_write(inode, le32_to_cpu(ri->i_uid));
	i_gid_write(inode, le32_to_cpu(ri->i_gid));
	set_nlink(inode, le32_to_cpu(ri->i_links));
	inode->i_size = le64_to_cpu(ri->i_size);
	inode->i_blocks = le64_to_cpu(ri->i_blocks);

	inode->i_atime.tv_sec = le64_to_cpu(ri->i_atime);
	inode->i_ctime.tv_sec = le64_to_cpu(ri->i_ctime);
	inode->i_mtime.tv_sec = le64_to_cpu(ri->i_mtime);
	inode->i_atime.tv_nsec = le32_to_cpu(ri->i_atime_nsec);
	inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec);
	inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
	inode->i_generation = le32_to_cpu(ri->i_generation);

	fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
	fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
	fi->i_flags = le32_to_cpu(ri->i_flags);
	fi->flags = 0;
	fi->data_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver) - 1;
	fi->i_advise = ri->i_advise;
	fi->i_pino = le32_to_cpu(ri->i_pino);
	get_extent_info(&fi->ext, ri->i_ext);
	f2fs_put_page(node_page, 1);
	return 0;
}

struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
{
	struct f2fs_sb_info *sbi = F2FS_SB(sb);
	struct inode *inode;
	int ret;

	inode = iget_locked(sb, ino);
	if (!inode)
		return ERR_PTR(-ENOMEM);
	if (!(inode->i_state & I_NEW))
		return inode;
	if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi))
		goto make_now;

	ret = do_read_inode(inode);
	if (ret)
		goto bad_inode;

	if (!sbi->por_doing && inode->i_nlink == 0) {
		ret = -ENOENT;
		goto bad_inode;
	}

make_now:
	if (ino == F2FS_NODE_INO(sbi)) {
		inode->i_mapping->a_ops = &f2fs_node_aops;
		mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
	} else if (ino == F2FS_META_INO(sbi)) {
		inode->i_mapping->a_ops = &f2fs_meta_aops;
		mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
	} else if (S_ISREG(inode->i_mode)) {
		inode->i_op = &f2fs_file_inode_operations;
		inode->i_fop = &f2fs_file_operations;
		inode->i_mapping->a_ops = &f2fs_dblock_aops;
	} else if (S_ISDIR(inode->i_mode)) {
		inode->i_op = &f2fs_dir_inode_operations;
		inode->i_fop = &f2fs_dir_operations;
		inode->i_mapping->a_ops = &f2fs_dblock_aops;
		mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER_MOVABLE |
				__GFP_ZERO);
	} else if (S_ISLNK(inode->i_mode)) {
		inode->i_op = &f2fs_symlink_inode_operations;
		inode->i_mapping->a_ops = &f2fs_dblock_aops;
	} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
			S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
		inode->i_op = &f2fs_special_inode_operations;
		init_special_inode(inode, inode->i_mode, inode->i_rdev);
	} else {
		ret = -EIO;
		goto bad_inode;
	}
	unlock_new_inode(inode);

	return inode;

bad_inode:
	iget_failed(inode);
	return ERR_PTR(ret);
}

void update_inode(struct inode *inode, struct page *node_page)
{
	struct f2fs_node *rn;
	struct f2fs_inode *ri;

	wait_on_page_writeback(node_page);

	rn = page_address(node_page);
	ri = &(rn->i);

	ri->i_mode = cpu_to_le16(inode->i_mode);
	ri->i_advise = F2FS_I(inode)->i_advise;
	ri->i_uid = cpu_to_le32(i_uid_read(inode));
	ri->i_gid = cpu_to_le32(i_gid_read(inode));
	ri->i_links = cpu_to_le32(inode->i_nlink);
	ri->i_size = cpu_to_le64(i_size_read(inode));
	ri->i_blocks = cpu_to_le64(inode->i_blocks);
	set_raw_extent(&F2FS_I(inode)->ext, &ri->i_ext);

	ri->i_atime = cpu_to_le64(inode->i_atime.tv_sec);
	ri->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
	ri->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
	ri->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
	ri->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
	ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
	ri->i_current_depth = cpu_to_le32(F2FS_I(inode)->i_current_depth);
	ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
	ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
	ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
	ri->i_generation = cpu_to_le32(inode->i_generation);
	set_cold_node(inode, node_page);
	set_page_dirty(node_page);
}

int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
{
	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
	struct page *node_page;
	bool need_lock = false;

	if (inode->i_ino == F2FS_NODE_INO(sbi) ||
			inode->i_ino == F2FS_META_INO(sbi))
		return 0;

	if (wbc)
		f2fs_balance_fs(sbi);

	node_page = get_node_page(sbi, inode->i_ino);
	if (IS_ERR(node_page))
		return PTR_ERR(node_page);

	if (!PageDirty(node_page)) {
		need_lock = true;
		f2fs_put_page(node_page, 1);
		mutex_lock(&sbi->write_inode);
		node_page = get_node_page(sbi, inode->i_ino);
		if (IS_ERR(node_page)) {
			mutex_unlock(&sbi->write_inode);
			return PTR_ERR(node_page);
		}
	}
	update_inode(inode, node_page);
	f2fs_put_page(node_page, 1);
	if (need_lock)
		mutex_unlock(&sbi->write_inode);
	return 0;
}

/*
 * Called at the last iput() if i_nlink is zero
 */
void f2fs_evict_inode(struct inode *inode)
{
	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);

	truncate_inode_pages(&inode->i_data, 0);

	if (inode->i_ino == F2FS_NODE_INO(sbi) ||
			inode->i_ino == F2FS_META_INO(sbi))
		goto no_delete;

	BUG_ON(atomic_read(&F2FS_I(inode)->dirty_dents));
	remove_dirty_dir_inode(inode);

	if (inode->i_nlink || is_bad_inode(inode))
		goto no_delete;

	set_inode_flag(F2FS_I(inode), FI_NO_ALLOC);
	i_size_write(inode, 0);

	if (F2FS_HAS_BLOCKS(inode))
		f2fs_truncate(inode);

	remove_inode_page(inode);
no_delete:
	clear_inode(inode);
}
int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
			const void *value, size_t value_len, struct page *ipage)
{
	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
	struct f2fs_inode_info *fi = F2FS_I(inode);
	struct f2fs_xattr_header *header = NULL;
	struct f2fs_xattr_entry *here, *last;
	struct page *page;
	void *base_addr;
	int error, found, free, newsize;
	size_t name_len;
	char *pval;
	int ilock;

	if (name == NULL)
		return -EINVAL;

	if (value == NULL)
		value_len = 0;

	name_len = strlen(name);

	if (name_len > F2FS_NAME_LEN || value_len > MAX_VALUE_LEN)
		return -ERANGE;

	f2fs_balance_fs(sbi);

	ilock = mutex_lock_op(sbi);

	if (!fi->i_xattr_nid) {
		/* Allocate new attribute block */
		struct dnode_of_data dn;

		if (!alloc_nid(sbi, &fi->i_xattr_nid)) {
			error = -ENOSPC;
			goto exit;
		}
		set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid);
		mark_inode_dirty(inode);

		page = new_node_page(&dn, XATTR_NODE_OFFSET, ipage);
		if (IS_ERR(page)) {
			alloc_nid_failed(sbi, fi->i_xattr_nid);
			fi->i_xattr_nid = 0;
			error = PTR_ERR(page);
			goto exit;
		}

		alloc_nid_done(sbi, fi->i_xattr_nid);
		base_addr = page_address(page);
		header = XATTR_HDR(base_addr);
		header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC);
		header->h_refcount = cpu_to_le32(1);
	} else {
		/* The inode already has an extended attribute block. */
		page = get_node_page(sbi, fi->i_xattr_nid);
		if (IS_ERR(page)) {
			error = PTR_ERR(page);
			goto exit;
		}

		base_addr = page_address(page);
		header = XATTR_HDR(base_addr);
	}

	if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) {
		error = -EIO;
		goto cleanup;
	}

	/* find entry with wanted name. */
	found = 0;
	list_for_each_xattr(here, base_addr) {
		if (here->e_name_index != name_index)
			continue;
		if (here->e_name_len != name_len)
			continue;
		if (!memcmp(here->e_name, name, name_len)) {
			found = 1;
			break;
		}
	}

	last = here;

	while (!IS_XATTR_LAST_ENTRY(last))
		last = XATTR_NEXT_ENTRY(last);

	newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) +
			name_len + value_len);

	/* 1. Check space */
	if (value) {
		/* If value is NULL, it is remove operation.
		 * In case of update operation, we caculate free.
		 */
		free = MIN_OFFSET - ((char *)last - (char *)header);
		if (found)
			free = free - ENTRY_SIZE(here);

		if (free < newsize) {
			error = -ENOSPC;
			goto cleanup;
		}
	}

	/* 2. Remove old entry */
	if (found) {
		/* If entry is found, remove old entry.
		 * If not found, remove operation is not needed.
		 */
		struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here);
		int oldsize = ENTRY_SIZE(here);

		memmove(here, next, (char *)last - (char *)next);
		last = (struct f2fs_xattr_entry *)((char *)last - oldsize);
		memset(last, 0, oldsize);
	}

	/* 3. Write new entry */
	if (value) {
		/* Before we come here, old entry is removed.
		 * We just write new entry. */
		memset(last, 0, newsize);
		last->e_name_index = name_index;
		last->e_name_len = name_len;
		memcpy(last->e_name, name, name_len);
		pval = last->e_name + name_len;
		memcpy(pval, value, value_len);
		last->e_value_size = cpu_to_le16(value_len);
	}

	set_page_dirty(page);
	f2fs_put_page(page, 1);

	if (is_inode_flag_set(fi, FI_ACL_MODE)) {
		inode->i_mode = fi->i_acl_mode;
		inode->i_ctime = CURRENT_TIME;
		clear_inode_flag(fi, FI_ACL_MODE);
	}
	if (ipage)
		update_inode(inode, ipage);
	else
		update_inode_page(inode);
	mutex_unlock_op(sbi, ilock);

	return 0;
cleanup:
	f2fs_put_page(page, 1);
exit:
	mutex_unlock_op(sbi, ilock);
	return error;
}
示例#17
0
uint8_t* ramdisk_init(){
	int i;
	uint8_t* ramdisk;
	int root_bid;
	struct rd_inode* root_inode;
	struct rd_super_block* InitSuperBlock;
#ifdef UL_DEBUG
	if(!(ramdisk=(uint8_t*)malloc(RAMDISK_SIZE*sizeof(uint8_t)))){
		fprintf(stderr,"No sufficient mem space for ramdisk!\n");
		exit(-1);
	}
#endif

#ifndef UL_DEBUG
	if(!(ramdisk=(uint8_t*)vmalloc(RAMDISK_SIZE*sizeof(uint8_t)))){
		printk("<1> No sufficient mem space for ramdisk!\n");
		return NULL;
	}
#endif

	//Nullify all the data in ramdisk
	memset(ramdisk,0,RAMDISK_SIZE);

	//Init the bitmap
	for(i=0;i<=(BITMAP_LIMIT+1)/RD_BLOCK_SIZE;i++){
		set_bitmap(ramdisk,i);
	}

	//Init the root directory
	root_bid=find_next_free_block(ramdisk);//BlockNO for root dir
#ifdef UL_DEBUG
	if(!(root_inode=(struct rd_inode*)malloc(sizeof(struct rd_inode)))){
		fprintf(stderr, "No sufficient mem space for root dir!\n");
		exit(-1);
	}
#endif
#ifndef UL_DEBUG
	if(!(root_inode=(struct rd_inode*)vmalloc(sizeof(struct rd_inode)))){
		printk("<1> No sufficient mem space for root dir!\n");
		return NULL;
	}
#endif

	root_inode->type=0;
	root_inode->size=0;
	root_inode->BlockPointer[0]=root_bid;
	update_inode(ramdisk,0,root_inode);
	
	//Init the superblock
#ifdef UL_DEBUG
	if(!(InitSuperBlock=(struct rd_super_block*)malloc(sizeof(struct rd_super_block)))){
		fprintf(stderr,"No sufficient mem\n");
		exit(-1);
	}
#endif 
#ifndef UL_DEBUG
	if(!(InitSuperBlock=(struct rd_super_block*)vmalloc(sizeof(struct rd_super_block)))){
		printk("<1> No sufficient mem\n");
		return NULL;
	}
#endif 

	InitSuperBlock->FreeBlockNum=BLOCK_NUM-(BITMAP_LIMIT+1)/RD_BLOCK_SIZE;
	InitSuperBlock->FreeInodeNum=INODE_NUM-1;//The root dir takes one inode
	memset(InitSuperBlock->InodeBitmap,0,INODEBITMAP_SIZE);
	update_superblock(ramdisk,InitSuperBlock);
	
	//Init the inode bitmap in superblock
	set_inode_bitmap(ramdisk,0);

#ifndef UL_DEBUG
	vfree(root_inode);
#endif
	return ramdisk;	

}
示例#18
0
int
main(int argc, char *argv[])
{
	// check for correct arguments
	if(argc != 3) {
		fprintf(stderr, "Usage: %s <port> <file-system-image>\n", argv[0]);
		exit(1);
	}
	
	int portnum = atoi(argv[1]);
	char *fs_image = argv[2];
    int sd = UDP_Open(portnum);
    assert(sd > -1);

	int fd = open(fs_image, O_RDWR|O_CREAT, S_IRWXU);
	if(fd < 0) {
		fprintf(stderr, "Cannot open file image");
		exit(1);
	}
	
	struct stat file_stat;
	if(fstat(fd, &file_stat) < 0) {
		fprintf(stderr, "Cannot open file image");
		exit(1);
	}
	
	int i, j, rc;
	MFS_Header_t *header;
	int image_size;
	free_bytes = MFS_BYTE_STEP_SIZE; 
	
	int entry_offset, inode_offset, new_dir_offset, parent_inode_offset;
	int tmp_offset, tmp_inode_offset, tmp_imap_offset;
	int done = 0;
	MFS_Imap_t *imap_temp;
	MFS_Inode_t *inode_temp;
	MFS_Inode_t *new_inode;
	MFS_DirEnt_t *entry_temp;
	
	if(file_stat.st_size >= sizeof(MFS_Header_t)) {
	
		image_size = file_stat.st_size + MFS_BYTE_STEP_SIZE;
		printf("Using old file of size %d\n", (int)file_stat.st_size);
		header = (MFS_Header_t *)malloc(image_size);
		// Put text in memory
		rc = read(fd, header, file_stat.st_size);
		
		if(rc < 0){
			fprintf(stderr, "Cannot open file");
			exit(1);
		}
	} else {
		//Initialize
		image_size = sizeof(MFS_Header_t) + MFS_BYTE_STEP_SIZE;
		header = (MFS_Header_t *)malloc(image_size);

		// root initialization
		inode_temp = allot_space(&header, sizeof(MFS_Inode_t), &tmp_inode_offset);
		imap_temp = allot_space(&header, sizeof(MFS_Imap_t), &tmp_imap_offset);
		imap_temp->inodes[0] = tmp_inode_offset;
		prepare_inode(inode_temp, MFS_DIRECTORY, NULL);

		for (i = 0; i < 14; i++) {
			imap_temp->inodes[i] = -1;
		}
		
		// header initialization
		for (i = 0; i < 4096/14; i++) {
			header->map[i] = -1;	
		}
	
		imap_temp->inodes[0] = tmp_inode_offset;

		// add two default entries
		entry_temp = allot_space(&header, MFS_BLOCK_SIZE, &tmp_offset);
		entry_temp[0].name[0] = '.';
		entry_temp[0].name[1] = '\0';
		entry_temp[0].inum = 0; 
		entry_temp[1].name[0] = '.';
		entry_temp[1].name[1] = '.';
		entry_temp[1].name[2] = '\0';
		entry_temp[1].inum = 0; 

		for (i = 2; i < MFS_BLOCK_SIZE/sizeof(MFS_DirEnt_t); i++) {
			entry_temp[i].inum = -1;
		}
		
		inode_temp->data[0] = tmp_offset;

		//Write to disk
		header->map[0] = tmp_imap_offset;
		flush(fd);		
		write_header(fd, header);
		printf("Initializing new file\n");
	}
	
	void* header_ptr = (void*)header;
	void* block_ptr = header_ptr + sizeof(MFS_Header_t);

	prot_r = (MFS_Prot_t*)malloc(sizeof(MFS_Prot_t));

	printf("Started listening at port %d\n", portnum);
	
    while (1) {
		struct sockaddr_in s;
		rc = UDP_Read(sd, &s, (char*)prot_r, sizeof(MFS_Prot_t));
		if (rc > 0) {
			
			//Special case for shutdown
			if(prot_r->cmd == CMD_INIT){
				printf("Server initialized\n");
				prot_r->ret = 0;
			} else if(prot_r->cmd == CMD_LOOKUP){
				
				prot_r->ret = -1;
				MFS_Inode_t* parent_inode = fix_inode(header, prot_r->pinum);
				prot_r->ret = lookup(block_ptr, parent_inode, &(prot_r->datapacket[0]));
			} else if(prot_r->cmd == CMD_SHUTDOWN){
				//Close file
				rc = close(fd);
				if(rc < 0){
					fprintf(stderr, "Cannot open file");
					exit(1);
				}
				prot_r->ret = 0;
				if(UDP_Write(sd, &s, (char*)prot_r, sizeof(MFS_Prot_t)) < -1){
					fprintf(stderr, "Unable to send result");
					exit(1);
				}
				exit(0);
			} else if(prot_r->cmd == CMD_UNLINK){
				
				verify(&header, &block_ptr, 16384);
				prot_r->ret = -1;
				MFS_Inode_t* parent_inode = fix_inode(header, prot_r->pinum);
				if(parent_inode != NULL && parent_inode->type == MFS_DIRECTORY){
					int exist = lookup(block_ptr, parent_inode, &(prot_r->datapacket[0]));
					if(exist != -1){
						//Check if empty
						MFS_Inode_t* this_inode = fix_inode(header, exist);
						if(!(this_inode->type == MFS_DIRECTORY && this_inode->size != 0)){
							//Need to remove
							MFS_DirEnt_t* new_dir_entry = allot_space(&header, MFS_BLOCK_SIZE, &entry_offset);
							MFS_Inode_t* new_parent_inode = allot_space(&header, sizeof(MFS_Inode_t), &parent_inode_offset);

							prepare_inode(new_parent_inode, 0, parent_inode);
							update_inode(&header, prot_r->pinum, parent_inode_offset);
							i = 0, done = 0;
							while(i < 14) {
								if(parent_inode->data[i] != -1){
									j = 0;
									while(j < MFS_BLOCK_SIZE / sizeof(MFS_DirEnt_t)){
										//printf("Parent node %d %d\n", inode->data[i], MFS_BLOCK_SIZE / sizeof(MFS_DirEnt_t) );
										MFS_DirEnt_t* entry = (MFS_DirEnt_t*)(block_ptr + parent_inode->data[i] + (j * sizeof(MFS_DirEnt_t)));			
										if(entry->inum != -1 && strcmp(entry->name, prot_r->datapacket) == 0 ){
											memcpy(new_dir_entry, block_ptr + parent_inode->data[i] , MFS_BLOCK_SIZE);
											//We now know which entry
											new_parent_inode->data[i] = entry_offset;
											new_dir_entry[j].inum = -1;
											update_inode(&header, exist, -1);
											prot_r->ret = 0;
											new_parent_inode->size--;
											done = 1;
											break;
										}
										j++;
									}
									if(done == 1) break;
								}
								i++;
							}


						}

					}else{
						prot_r->ret = 0;
					}
				}

			} else if(prot_r->cmd == CMD_READ){
				
				prot_r->ret = -1;
				MFS_Inode_t* parent_inode = fix_inode(header, prot_r->pinum);
				if(parent_inode != NULL && parent_inode->type == MFS_REGULAR_FILE && prot_r->block >= 0 && prot_r->block < 14){
					//New inode
					memcpy(prot_r->datapacket, block_ptr + parent_inode->data[prot_r->block], MFS_BLOCK_SIZE);
					prot_r->ret = 0;
				}
			} else if(prot_r->cmd == CMD_STAT){
				
				prot_r->ret = -1;
				MFS_Inode_t* parent_inode = fix_inode(header, prot_r->pinum);
				if(parent_inode != NULL && prot_r->block >= 0 && prot_r->block < 14){
					//New inode
					prot_r->block = parent_inode->size;
					prot_r->datapacket[0] = parent_inode->type;
					prot_r->ret = 0;
				}
			} else if(prot_r->cmd == CMD_WRITE){
				
				verify(&header, &block_ptr, 16384);
				prot_r->ret = -1;
				MFS_Inode_t* parent_inode = fix_inode(header, prot_r->pinum);
				int block_offset;
				if(parent_inode != NULL && parent_inode->type == MFS_REGULAR_FILE && prot_r->block >= 0 && prot_r->block < 14){
					//New inode
					new_inode = (MFS_Inode_t*)allot_space(&header, sizeof(MFS_Inode_t), &inode_offset);
					prepare_inode(new_inode, 0, parent_inode);
					void* new_block = allot_space(&header, MFS_BLOCK_SIZE, &block_offset);

					memcpy(new_block, prot_r->datapacket, MFS_BLOCK_SIZE);
					i = prot_r->block;
					while(new_inode->data[i] == -1 && i >= 0){
						new_inode->size += MFS_BLOCK_SIZE;
						new_inode->data[i] = block_offset; 
						i--;
					}
					new_inode->data[prot_r->block] = block_offset; 
					update_inode(&header, prot_r->pinum, inode_offset);
					prot_r->ret = 0;
				}

			} else if(prot_r->cmd == CMD_CREAT){
				
				verify(&header, &block_ptr, 16384);
				prot_r->ret = -1;

				MFS_Inode_t* parent_inode = fix_inode(header, prot_r->pinum);
				int exist = lookup(block_ptr, parent_inode, &(prot_r->datapacket[1]));

				if(exist == -1){

					new_inode = allot_space(&header, sizeof(MFS_Inode_t), &inode_offset);
					prepare_inode(new_inode, prot_r->datapacket[0], NULL);
					int new_inode_inum = gen_inum(&header, inode_offset);


					if(parent_inode != NULL && parent_inode->type == MFS_DIRECTORY && strlen(&(prot_r->datapacket[1])) <= 28 && new_inode_inum != -1){
						//Check if the dir is full
						MFS_DirEnt_t* entry;
						//Initialize new data block for entries
						MFS_DirEnt_t* new_entry =  allot_space(&header, MFS_BLOCK_SIZE, &entry_offset);

						MFS_Inode_t* new_parent_inode = allot_space(&header, sizeof(MFS_Inode_t), &parent_inode_offset);
						prepare_inode(new_parent_inode, 0, parent_inode);
						update_inode(&header, prot_r->pinum, parent_inode_offset);

						//Copy new stuff	
						done = 0;
						i = 0;
						while(i < 14) {
							if(parent_inode->data[i] != -1){

								j = 0;
								while(j < MFS_BLOCK_SIZE / sizeof(MFS_DirEnt_t)){
									entry = (MFS_DirEnt_t*)(block_ptr + parent_inode->data[i] + (j * sizeof(MFS_DirEnt_t)));			
									if(entry->inum == -1){

										//Copy the dir entry
										memcpy(new_entry, block_ptr + parent_inode->data[i], MFS_BLOCK_SIZE);
										new_parent_inode->data[i] = entry_offset;
										new_entry[j].inum = new_inode_inum;	
										strcpy(new_entry[j].name, &(prot_r->datapacket[1]));
										//printf("Name: %s - %s\n",entry->name, &(prot_r->datapacket[1]));
										done = 1;
										break;
									}
									j++;
								}
								if(done == 1) break;
							}else{	

								//Create new node
								//Initialize
								for (j = 0; j < MFS_BLOCK_SIZE / sizeof(MFS_DirEnt_t); j++) {
									new_entry[j].inum = -1;
								}
								new_parent_inode->data[i] = entry_offset;
								new_entry[0].inum = new_inode_inum;			
								strcpy(new_entry[0].name, &(prot_r->datapacket[1]));
								done = 1;
								break;
							}
							i++;
						}
						if(done){
							//Actually create the inode
							//Add .. and . dirs
							if(new_inode->type == MFS_DIRECTORY){
								MFS_DirEnt_t* new_dir_entry =  allot_space(&header, MFS_BLOCK_SIZE, &new_dir_offset);
								for (i = 0; i < MFS_BLOCK_SIZE/sizeof(MFS_DirEnt_t); i++) {
									new_dir_entry[i].inum = -1;
								}
								new_dir_entry[0].name[0] = '.';
								new_dir_entry[0].name[1] = '\0';
								new_dir_entry[0].inum = new_inode_inum; 
								new_dir_entry[1].name[0] = '.';
								new_dir_entry[1].name[1] = '.';
								new_dir_entry[1].name[2] = '\0';
								new_dir_entry[1].inum = prot_r->pinum; 
								new_inode->data[0] = new_dir_offset;
							}	

							//Write to block
							new_parent_inode->size++;
							header->total_inode++;
							prot_r->ret = 0;
						}else{
							header->total_byte -= unwritten_bytes;
							unwritten_bytes = 0;
						}
					}else{
						header->total_byte -= unwritten_bytes;
						unwritten_bytes = 0;
					}
				}else{
					prot_r->ret = 0;
				}

			} else {
				fprintf(stderr, "Unknown command");
				exit(1);
				continue;
			}

			flush(fd);
			write_header(fd, header);
			if(UDP_Write(sd, &s, (char*)prot_r, sizeof(MFS_Prot_t)) < -1){
				fprintf(stderr, "Unable to send result");
				exit(1);
			}
		}

    }

    return 0;
}