Пример #1
0
int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
				 handle_t *handle, struct inode *inode,
				 struct buffer_head *bh)
{
	int err = 0;

	if (ext4_handle_valid(handle)) {
		err = jbd2_journal_dirty_metadata(handle, bh);
		if (err) {
			/* Errors can only happen if there is a bug */
			handle->h_err = err;
			__ext4_journal_stop(where, line, handle);
		}
	} else {
		if (inode)
			mark_buffer_dirty_inode(bh, inode);
		else
			mark_buffer_dirty(bh);
		if (inode && inode_needs_sync(inode)) {
			sync_dirty_buffer(bh);
			if (buffer_req(bh) && !buffer_uptodate(bh)) {
				struct ext4_super_block *es;

				es = EXT4_SB(inode->i_sb)->s_es;
				es->s_last_error_block =
					cpu_to_le64(bh->b_blocknr);
				ext4_error_inode(inode, where, line,
						 bh->b_blocknr,
					"IO error syncing itable block");
				err = -EIO;
			}
		}
	}
	return err;
}
Пример #2
0
int __ext4_journal_dirty_metadata(const char *where,
                handle_t *handle, struct buffer_head *bh)
{
    int err = jbd2_journal_dirty_metadata(handle, bh);
    if (err)
        ext4_journal_abort_handle(where, __func__, bh, handle, err);
    return err;
}
Пример #3
0
int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
                                 handle_t *handle, struct inode *inode,
                                 struct buffer_head *bh)
{
    int err = 0;

    might_sleep();

    set_buffer_meta(bh);
    set_buffer_prio(bh);
    if (ext4_handle_valid(handle)) {
        err = jbd2_journal_dirty_metadata(handle, bh);
        /* Errors can only happen if there is a bug */
        if (WARN_ON_ONCE(err)) {
            ext4_journal_abort_handle(where, line, __func__, bh,
                                      handle, err);
            if (inode == NULL) {
                pr_err("EXT4: jbd2_journal_dirty_metadata "
                       "failed: handle type %u started at "
                       "line %u, credits %u/%u, errcode %d",
                       handle->h_type,
                       handle->h_line_no,
                       handle->h_requested_credits,
                       handle->h_buffer_credits, err);
                return err;
            }
            ext4_error_inode(inode, where, line,
                             bh->b_blocknr,
                             "journal_dirty_metadata failed: "
                             "handle type %u started at line %u, "
                             "credits %u/%u, errcode %d",
                             handle->h_type,
                             handle->h_line_no,
                             handle->h_requested_credits,
                             handle->h_buffer_credits, err);
        }
    } else {
        if (inode)
            mark_buffer_dirty_inode(bh, inode);
        else
            mark_buffer_dirty(bh);
        if (inode && inode_needs_sync(inode)) {
            sync_dirty_buffer(bh);
            if (buffer_req(bh) && !buffer_uptodate(bh)) {
                struct ext4_super_block *es;

                es = EXT4_SB(inode->i_sb)->s_es;
                es->s_last_error_block =
                    cpu_to_le64(bh->b_blocknr);
                ext4_error_inode(inode, where, line,
                                 bh->b_blocknr,
                                 "IO error syncing itable block");
                err = -EIO;
            }
        }
    }
    return err;
}
Пример #4
0
int __ext4_handle_dirty_super(const char *where, unsigned int line,
			      handle_t *handle, struct super_block *sb)
{
	struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
	int err = 0;

	if (ext4_handle_valid(handle)) {
		err = jbd2_journal_dirty_metadata(handle, bh);
		if (err)
			ext4_journal_abort_handle(where, line, __func__,
						  bh, handle, err);
	} else
		sb->s_dirt = 1;
	return err;
}
Пример #5
0
int __ext4_handle_dirty_super(const char *where, unsigned int line,
			      handle_t *handle, struct super_block *sb,
			      int now)
{
	struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
	int err = 0;

	if (ext4_handle_valid(handle)) {
		ext4_superblock_csum_set(sb,
				(struct ext4_super_block *)bh->b_data);
		err = jbd2_journal_dirty_metadata(handle, bh);
		if (err)
			ext4_journal_abort_handle(where, line, __func__,
						  bh, handle, err);
	} else if (now) {
		ext4_superblock_csum_set(sb,
				(struct ext4_super_block *)bh->b_data);
		mark_buffer_dirty(bh);
	} else
		sb->s_dirt = 1;
	return err;
}
Пример #6
0
/* FIXME: The write support is rudimentary. I have not figured out a way to do writes
 * from particular offsets (even though I have written some untested code for this below) efficiently. */
ssize_t simplefs_write(struct file * filp, const char __user * buf, size_t len,
                       loff_t * ppos)
{
    /* After the commit dd37978c5 in the upstream linux kernel,
     * we can use just filp->f_inode instead of the
     * f->f_path.dentry->d_inode redirection */
    struct inode *inode;
    struct simplefs_inode *sfs_inode;
    struct buffer_head *bh;
    struct super_block *sb;
    struct simplefs_super_block *sfs_sb;
    handle_t *handle;

    char *buffer;

    int retval;

    sb = filp->f_path.dentry->d_inode->i_sb;
    sfs_sb = SIMPLEFS_SB(sb);

    handle = jbd2_journal_start(sfs_sb->journal, 1);
    if (IS_ERR(handle))
        return PTR_ERR(handle);
    retval = generic_write_checks(filp, ppos, &len, 0);
    if (retval)
        return retval;

    inode = filp->f_path.dentry->d_inode;
    sfs_inode = SIMPLEFS_INODE(inode);

    bh = sb_bread(filp->f_path.dentry->d_inode->i_sb,
                  sfs_inode->data_block_number);

    if (!bh) {
        printk(KERN_ERR "Reading the block number [%llu] failed.",
               sfs_inode->data_block_number);
        return 0;
    }
    buffer = (char *)bh->b_data;

    /* Move the pointer until the required byte offset */
    buffer += *ppos;

    retval = jbd2_journal_get_write_access(handle, bh);
    if (WARN_ON(retval)) {
        brelse(bh);
        sfs_trace("Can't get write access for bh\n");
        return retval;
    }

    if (copy_from_user(buffer, buf, len)) {
        brelse(bh);
        printk(KERN_ERR
               "Error copying file contents from the userspace buffer to the kernel space\n");
        return -EFAULT;
    }
    *ppos += len;

    retval = jbd2_journal_dirty_metadata(handle, bh);
    if (WARN_ON(retval)) {
        brelse(bh);
        return retval;
    }
    handle->h_sync = 1;
    retval = jbd2_journal_stop(handle);
    if (WARN_ON(retval)) {
        brelse(bh);
        return retval;
    }

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

    /* Set new size
     * sfs_inode->file_size = max(sfs_inode->file_size, *ppos);
     *
     * FIXME: What to do if someone writes only some parts in between ?
     * The above code will also fail in case a file is overwritten with
     * a shorter buffer */
    if (mutex_lock_interruptible(&simplefs_inodes_mgmt_lock)) {
        sfs_trace("Failed to acquire mutex lock\n");
        return -EINTR;
    }
    sfs_inode->file_size = *ppos;
    retval = simplefs_inode_save(sb, sfs_inode);
    if (retval) {
        len = retval;
    }
    mutex_unlock(&simplefs_inodes_mgmt_lock);

    return len;
}