Пример #1
0
static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err)
{
#ifdef EXT2FS_DEBUG
	static unsigned long alloc_hits = 0, alloc_attempts = 0;
#endif
	unsigned long result;


#ifdef EXT2_PREALLOCATE
	/* Writer: ->i_prealloc* */
	if (inode->u.ext2_i.i_prealloc_count &&
	    (goal == inode->u.ext2_i.i_prealloc_block ||
	     goal + 1 == inode->u.ext2_i.i_prealloc_block))
	{		
		result = inode->u.ext2_i.i_prealloc_block++;
		inode->u.ext2_i.i_prealloc_count--;
		/* Writer: end */
		ext2_debug ("preallocation hit (%lu/%lu).\n",
			    ++alloc_hits, ++alloc_attempts);
	} else {
		ext2_discard_prealloc (inode);
		ext2_debug ("preallocation miss (%lu/%lu).\n",
			    alloc_hits, ++alloc_attempts);
		if (S_ISREG(inode->i_mode))
			result = ext2_new_block (inode, goal, 
				 &inode->u.ext2_i.i_prealloc_count,
				 &inode->u.ext2_i.i_prealloc_block, err);
		else
			result = ext2_new_block (inode, goal, 0, 0, err);
	}
#else
	result = ext2_new_block (inode, goal, 0, 0, err);
#endif
	return result;
}
Пример #2
0
/*
 * COMP3301 Addition
 * Write immediate files data to the inode. Covert back to
 * Regular files when the data exceeds the limit.
 */
ssize_t do_immediate_write (struct file* flip, const char __user* buf,
	size_t len, loff_t *ppos, int need_to_encrypt) {

	struct ext2_inode_info *inode_info = EXT2_I(flip->f_dentry->d_inode);
	struct inode *inode = flip->f_dentry->d_inode;
	char *data = (char *)inode_info->i_data;
	char *copy;
	char *ext_inode_data = (char *) (EXT2_I(inode)->i_data);
	int err;
	ssize_t result;


	if (*ppos + len >= IMMEDIATE_FILE_SIZE) {
		// Convert to regular file

       	copy = (char *) kmalloc(sizeof(char) * strlen(ext_inode_data)
       	 	+ 1, GFP_KERNEL);
       	memset(copy, 0, strlen(ext_inode_data) + 1);
       	memcpy(copy, ext_inode_data, strlen(ext_inode_data));
       	copy[strlen(ext_inode_data)] = 0;


       	inode->i_mode &= ~(S_IF_IMMEDIATE & S_IFMT);
       	inode->i_mode |= S_IFREG & S_IFMT;

        inode_info->i_data[0] = ext2_new_block(inode, 0, &err);
        mark_inode_dirty(inode);

       	flip->f_pos = 0;
       	result = write_encrypt(flip, copy, strlen(copy), &flip->f_pos);
       	result = write_encrypt(flip, buf, len, ppos);

       	kfree(copy);
        return result;
	}

    if (need_to_encrypt) {
    	encrypt(buf, len);
    }

	if (copy_from_user(data + *ppos, buf, len)) {
		return -1;
	}

    *ppos += len;
    flip->f_pos = *ppos;
    inode->i_size += len;
    mark_inode_dirty(inode);

	return len;
}
Пример #3
0
/*
 * This function zeros out the allocated block, and updates all of the
 * appropriate filesystem records.
 */
bool ext2_alloc_block(PEXT2_FILESYS fs, ULONG goal, ULONG *ret)
{
    bool        retval;
    ULONG       block;
    char        *buf = NULL;

    buf = (char *)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, fs->blocksize);
    if (!buf)
        return false;

    if (!fs->block_map)
    {
        retval = ext2_read_block_bitmap(fs);
        if (!retval)
            goto fail;
    }

    retval = ext2_new_block(fs, goal, 0, &block);

    if (!retval)
        goto fail;

    retval = NT_SUCCESS(Ext2WriteDisk(
                fs,
                ((LONGLONG)block * fs->blocksize),
                fs->blocksize, (unsigned char *)buf));

    if (!retval)
    {
        goto fail;
    }
    
    ext2_block_alloc_stats(fs, block, +1);
    *ret = block;

    if (buf)
    {
        RtlFreeHeap(RtlGetProcessHeap(), 0, buf);
    }

    return true;

fail:

    if (buf)
    {
        RtlFreeHeap(RtlGetProcessHeap(), 0, buf);
    }

    return false;
}
Пример #4
0
static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err)
{
#ifdef EXT2FS_DEBUG
    static unsigned long alloc_hits, alloc_attempts;
#endif
    unsigned long result;


#ifdef EXT2_PREALLOCATE
    struct ext2_inode_info *ei = EXT2_I(inode);
    write_lock(&ei->i_meta_lock);
    if (ei->i_prealloc_count &&
            (goal == ei->i_prealloc_block || goal + 1 == ei->i_prealloc_block))
    {
        result = ei->i_prealloc_block++;
        ei->i_prealloc_count--;
        write_unlock(&ei->i_meta_lock);
        ext2_debug ("preallocation hit (%lu/%lu).\n",
                    ++alloc_hits, ++alloc_attempts);
    } else {
        write_unlock(&ei->i_meta_lock);
        ext2_discard_prealloc (inode);
        ext2_debug ("preallocation miss (%lu/%lu).\n",
                    alloc_hits, ++alloc_attempts);
        if (S_ISREG(inode->i_mode))
            result = ext2_new_block (inode, goal,
                                     &ei->i_prealloc_count,
                                     &ei->i_prealloc_block, err);
        else
            result = ext2_new_block(inode, goal, NULL, NULL, err);
    }
#else
    result = ext2_new_block (inode, goal, 0, 0, err);
#endif
    return result;
}
Пример #5
0
/*
 * Allocate a block in the file system.
 *
 * this takes the framework from ffs_alloc. To implement the
 * actual allocation, it calls ext2_new_block, the ported version
 * of the same Linux routine.
 *
 * we note that this is always called in connection with ext2_blkpref
 *
 * preallocation is done as Linux does it
 */
int
ext2_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size,
	   struct ucred *cred, daddr_t *bnp)
{
	struct ext2_sb_info *fs;
	daddr_t bno;
#if QUOTA
	int error;
#endif

	*bnp = 0;
	fs = ip->i_e2fs;
#if DIAGNOSTIC
	if ((u_int)size > fs->s_blocksize || blkoff(fs, size) != 0) {
		kprintf("dev = %s, bsize = %lu, size = %d, fs = %s\n",
		    devtoname(ip->i_dev), fs->s_blocksize, size, fs->fs_fsmnt);
		panic("ext2_alloc: bad size");
	}
	if (cred == NOCRED)
		panic("ext2_alloc: missing credential");
#endif /* DIAGNOSTIC */
	if (size == fs->s_blocksize && fs->s_es->s_free_blocks_count == 0)
		goto nospace;
	if (cred->cr_uid != 0 &&
		fs->s_es->s_free_blocks_count < fs->s_es->s_r_blocks_count)
		goto nospace;
#if QUOTA
	if ((error = ext2_chkdq(ip, (long)btodb(size), cred, 0)) != 0)
		return (error);
#endif
	if (bpref >= fs->s_es->s_blocks_count)
		bpref = 0;
	/* call the Linux code */
#ifdef EXT2_PREALLOCATE
	/* To have a preallocation hit, we must
	 * - have at least one block preallocated
	 * - and our preferred block must have that block number or one below
	 */
        if (ip->i_prealloc_count &&
            (bpref == ip->i_prealloc_block ||
             bpref + 1 == ip->i_prealloc_block))
        {
                bno = ip->i_prealloc_block++;
                ip->i_prealloc_count--;
                /* ext2_debug ("preallocation hit (%lu/%lu).\n",
                            ++alloc_hits, ++alloc_attempts); */

		/* Linux gets, clears, and releases the buffer at this
		   point - we don't have to that; we leave it to the caller
		 */
        } else {
                ext2_discard_prealloc (ip);
                /* ext2_debug ("preallocation miss (%lu/%lu).\n",
                            alloc_hits, ++alloc_attempts); */
                if (S_ISREG(ip->i_mode))
                        bno = ext2_new_block
                                (ITOV(ip)->v_mount, bpref,
                                 &ip->i_prealloc_count,
                                 &ip->i_prealloc_block);
                else
			bno = (daddr_t)ext2_new_block(ITOV(ip)->v_mount,
					bpref, 0, 0);
        }
#else
	bno = (daddr_t)ext2_new_block(ITOV(ip)->v_mount, bpref, 0, 0);
#endif

	if (bno > 0) {
		/* set next_alloc fields as done in block_getblk */
		ip->i_next_alloc_block = lbn;
		ip->i_next_alloc_goal = bno;

		ip->i_blocks += btodb(size);
		ip->i_flag |= IN_CHANGE | IN_UPDATE;
		*bnp = bno;
		return (0);
	}
#if QUOTA
	/*
	 * Restore user's disk quota because allocation failed.
	 */
	ext2_chkdq(ip, (long)-btodb(size), cred, FORCE);
#endif
nospace:
	ext2_fserr(fs, cred->cr_uid, "file system full");
	uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
	return (ENOSPC);
}