Example #1
0
static int simplefs_create_fs_object(struct inode *dir, struct dentry *dentry,
                                     umode_t mode)
{
    struct inode *inode;
    struct simplefs_inode *sfs_inode;
    struct super_block *sb;
    struct simplefs_inode *parent_dir_inode;
    struct buffer_head *bh;
    struct simplefs_dir_record *dir_contents_datablock;
    uint64_t count;
    int ret;

    if (mutex_lock_interruptible(&simplefs_directory_children_update_lock)) {
        sfs_trace("Failed to acquire mutex lock\n");
        return -EINTR;
    }
    sb = dir->i_sb;

    ret = simplefs_sb_get_objects_count(sb, &count);
    if (ret < 0) {
        mutex_unlock(&simplefs_directory_children_update_lock);
        return ret;
    }

    if (unlikely(count >= SIMPLEFS_MAX_FILESYSTEM_OBJECTS_SUPPORTED)) {
        /* The above condition can be just == insted of the >= */
        printk(KERN_ERR
               "Maximum number of objects supported by simplefs is already reached");
        mutex_unlock(&simplefs_directory_children_update_lock);
        return -ENOSPC;
    }

    if (!S_ISDIR(mode) && !S_ISREG(mode)) {
        printk(KERN_ERR
               "Creation request but for neither a file nor a directory");
        mutex_unlock(&simplefs_directory_children_update_lock);
        return -EINVAL;
    }

    inode = new_inode(sb);
    if (!inode) {
        mutex_unlock(&simplefs_directory_children_update_lock);
        return -ENOMEM;
    }

    inode->i_sb = sb;
    inode->i_op = &simplefs_inode_ops;
    inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
    inode->i_ino = (count + SIMPLEFS_START_INO - SIMPLEFS_RESERVED_INODES + 1);

    sfs_inode = kmem_cache_alloc(sfs_inode_cachep, GFP_KERNEL);
    sfs_inode->inode_no = inode->i_ino;
    inode->i_private = sfs_inode;
    sfs_inode->mode = mode;

    if (S_ISDIR(mode)) {
        printk(KERN_INFO "New directory creation request\n");
        sfs_inode->dir_children_count = 0;
        inode->i_fop = &simplefs_dir_operations;
    } else if (S_ISREG(mode)) {
        printk(KERN_INFO "New file creation request\n");
        sfs_inode->file_size = 0;
        inode->i_fop = &simplefs_file_operations;
    }

    /* First get a free block and update the free map,
     * Then add inode to the inode store and update the sb inodes_count,
     * Then update the parent directory's inode with the new child.
     *
     * The above ordering helps us to maintain fs consistency
     * even in most crashes
     */
    ret = simplefs_sb_get_a_freeblock(sb, &sfs_inode->data_block_number);
    if (ret < 0) {
        printk(KERN_ERR "simplefs could not get a freeblock");
        mutex_unlock(&simplefs_directory_children_update_lock);
        return ret;
    }

    simplefs_inode_add(sb, sfs_inode);

    parent_dir_inode = SIMPLEFS_INODE(dir);
    bh = sb_bread(sb, parent_dir_inode->data_block_number);
    BUG_ON(!bh);

    dir_contents_datablock = (struct simplefs_dir_record *)bh->b_data;

    /* Navigate to the last record in the directory contents */
    dir_contents_datablock += parent_dir_inode->dir_children_count;

    dir_contents_datablock->inode_no = sfs_inode->inode_no;
    strcpy(dir_contents_datablock->filename, dentry->d_name.name);

    mark_buffer_dirty(bh);
    sync_dirty_buffer(bh);
    brelse(bh);

    if (mutex_lock_interruptible(&simplefs_inodes_mgmt_lock)) {
        mutex_unlock(&simplefs_directory_children_update_lock);
        sfs_trace("Failed to acquire mutex lock\n");
        return -EINTR;
    }

    parent_dir_inode->dir_children_count++;
    ret = simplefs_inode_save(sb, parent_dir_inode);
    if (ret) {
        mutex_unlock(&simplefs_inodes_mgmt_lock);
        mutex_unlock(&simplefs_directory_children_update_lock);

        /* TODO: Remove the newly created inode from the disk and in-memory inode store
         * and also update the superblock, freemaps etc. to reflect the same.
         * Basically, Undo all actions done during this create call */
        return ret;
    }

    mutex_unlock(&simplefs_inodes_mgmt_lock);
    mutex_unlock(&simplefs_directory_children_update_lock);

    inode_init_owner(inode, dir, mode);
    d_add(dentry, inode);

    return 0;
}
Example #2
0
static int simplefs_create_fs_object(struct inode *dir, struct dentry *dentry,
				     umode_t mode)
{
	struct inode *inode;
	struct simplefs_inode *sfs_inode;
	struct simplefs_inode *inode_iterator;
	struct super_block *sb;
	struct simplefs_dir_record *record;
	struct simplefs_inode *parent_dir_inode;
	struct buffer_head *bh;
	struct simplefs_dir_record *dir_contents_datablock;
	uint64_t count;
	int ret;

	if (mutex_lock_interruptible(&simplefs_directory_children_update_lock)) {
		printk(KERN_ERR "Failed to acquire mutex lock %s +%d\n",
		       __FILE__, __LINE__);
		return -EINTR;
	}
	sb = dir->i_sb;

	ret = simplefs_sb_get_objects_count(sb, &count);
	if (ret < 0) {
		mutex_unlock(&simplefs_directory_children_update_lock);
		return ret;
	}

	if (unlikely(count >= SIMPLEFS_MAX_FILESYSTEM_OBJECTS_SUPPORTED)) {
		/* The above condition can be just == insted of the >= */
		printk(KERN_ERR
		       "Maximum number of objects supported by simplefs is already reached");
		mutex_unlock(&simplefs_directory_children_update_lock);
		return -ENOSPC;
	}

	if (!S_ISDIR(mode) && !S_ISREG(mode)) {
		printk(KERN_ERR
		       "Creation request but for neither a file nor a directory");
		mutex_unlock(&simplefs_directory_children_update_lock);
		return -EINVAL;
	}

	inode = new_inode(sb);
	if (!inode) {
		mutex_unlock(&simplefs_directory_children_update_lock);
		return -ENOMEM;
	}

	inode->i_sb = sb;
	inode->i_op = &simplefs_inode_ops;
	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
	inode->i_ino = 10;

	/* Loop until we get an unique inode number */
	while (simplefs_get_inode(sb, inode->i_ino)) {
		/* inode inode->i_ino already exists */
		inode->i_ino++;
	}

	/* FIXME: This is leaking. We need to free all in-memory inodes sometime */
	sfs_inode = kmalloc(sizeof(struct simplefs_inode), GFP_KERNEL);
	sfs_inode->inode_no = inode->i_ino;
	inode->i_private = sfs_inode;
	sfs_inode->mode = mode;

	if (S_ISDIR(mode)) {
		printk(KERN_INFO "New directory creation request\n");
		sfs_inode->dir_children_count = 0;
		inode->i_fop = &simplefs_dir_operations;
	} else if (S_ISREG(mode)) {
		printk(KERN_INFO "New file creation request\n");
		sfs_inode->file_size = 0;
		inode->i_fop = &simplefs_file_operations;
	}

	/* First get a free block and update the free map,
	 * Then add inode to the inode store and update the sb inodes_count,
	 * Then update the parent directory's inode with the new child.
	 *
	 * The above ordering helps us to maintain fs consistency
	 * even in most crashes
	 */
	ret = simplefs_sb_get_a_freeblock(sb, &sfs_inode->data_block_number);
	if (ret < 0) {
		printk(KERN_ERR "simplefs could not get a freeblock");
		mutex_unlock(&simplefs_directory_children_update_lock);
		return ret;
	}

	simplefs_inode_add(sb, sfs_inode);

	record = kmalloc(sizeof(struct simplefs_dir_record), GFP_KERNEL);
	record->inode_no = sfs_inode->inode_no;
	strcpy(record->filename, dentry->d_name.name);

	parent_dir_inode = SIMPLEFS_INODE(dir);
	bh = sb_bread(sb, parent_dir_inode->data_block_number);
	dir_contents_datablock = (struct simplefs_dir_record *)bh->b_data;

	/* Navigate to the last record in the directory contents */
	dir_contents_datablock += parent_dir_inode->dir_children_count;

	memcpy(dir_contents_datablock, record,
	       sizeof(struct simplefs_dir_record));

	mark_buffer_dirty(bh);
	sync_dirty_buffer(bh);
	brelse(bh);

	if (mutex_lock_interruptible(&simplefs_inodes_mgmt_lock)) {
		mutex_unlock(&simplefs_directory_children_update_lock);
		printk(KERN_ERR "Failed to acquire mutex lock %s +%d\n",
		       __FILE__, __LINE__);
		return -EINTR;
	}

	bh = (struct buffer_head *)sb_bread(sb,
					    SIMPLEFS_INODESTORE_BLOCK_NUMBER);

	inode_iterator = (struct simplefs_inode *)bh->b_data;

	if (mutex_lock_interruptible(&simplefs_sb_lock)) {
		printk(KERN_ERR "Failed to acquire mutex lock %s +%d\n",
		       __FILE__, __LINE__);
		return -EINTR;
	}

	count = 0;
	while (inode_iterator->inode_no != parent_dir_inode->inode_no
	       && count < SIMPLEFS_SB(sb)->inodes_count) {
		count++;
		inode_iterator++;
	}

	if (likely(inode_iterator->inode_no == parent_dir_inode->inode_no)) {
		parent_dir_inode->dir_children_count++;
		inode_iterator->dir_children_count =
		    parent_dir_inode->dir_children_count;
		/* Updated the parent inode's dir count to reflect the new child too */

		mark_buffer_dirty(bh);
		sync_dirty_buffer(bh);
	} else {
		printk(KERN_ERR
		       "The updated childcount could not be stored to the dir inode.");
		/* TODO: Remove the newly created inode from the disk and in-memory inode store
		 * and also update the superblock, freemaps etc. to reflect the same.
		 * Basically, Undo all actions done during this create call */
	}

	brelse(bh);

	mutex_unlock(&simplefs_sb_lock);
	mutex_unlock(&simplefs_inodes_mgmt_lock);
	mutex_unlock(&simplefs_directory_children_update_lock);

	inode_init_owner(inode, dir, mode);
	d_add(dentry, inode);

	return 0;
}