Commit 16fe4101 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: partial revert to fix double brelse WARNING()
  ext4: Fix return value of ext4_split_unwritten_extents() to fix direct I/O
  ext4: code clean up for dio fallocate handling
  ext4: skip conversion of uninit extents after direct IO if there isn't any
  ext4: fix ext4_ext_direct_IO()'s return value after converting uninit extents
  ext4: discard preallocation when restarting a transaction during truncate
parents 7bbf8ef6 1e424a34
......@@ -322,6 +322,7 @@ static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
#define EXT4_STATE_NO_EXPAND 0x00000008 /* No space for expansion */
#define EXT4_STATE_DA_ALLOC_CLOSE 0x00000010 /* Alloc DA blks on close */
#define EXT4_STATE_EXT_MIGRATE 0x00000020 /* Inode is migrating */
#define EXT4_STATE_DIO_UNWRITTEN 0x00000040 /* need convert on dio done*/
/* Used to pass group descriptor data when online resize is done */
struct ext4_new_group_input {
......
......@@ -2807,6 +2807,8 @@ fix_extent_len:
* into three uninitialized extent(at most). After IO complete, the part
* being filled will be convert to initialized by the end_io callback function
* via ext4_convert_unwritten_extents().
*
* Returns the size of uninitialized extent to be written on success.
*/
static int ext4_split_unwritten_extents(handle_t *handle,
struct inode *inode,
......@@ -2824,7 +2826,6 @@ static int ext4_split_unwritten_extents(handle_t *handle,
unsigned int allocated, ee_len, depth;
ext4_fsblk_t newblock;
int err = 0;
int ret = 0;
ext_debug("ext4_split_unwritten_extents: inode %lu,"
"iblock %llu, max_blocks %u\n", inode->i_ino,
......@@ -2842,12 +2843,12 @@ static int ext4_split_unwritten_extents(handle_t *handle,
ext4_ext_store_pblock(&orig_ex, ext_pblock(ex));
/*
* if the entire unintialized extent length less than
* the size of extent to write, there is no need to split
* uninitialized extent
* If the uninitialized extent begins at the same logical
* block where the write begins, and the write completely
* covers the extent, then we don't need to split it.
*/
if (allocated <= max_blocks)
return ret;
if ((iblock == ee_block) && (allocated <= max_blocks))
return allocated;
err = ext4_ext_get_access(handle, inode, path + depth);
if (err)
......@@ -3048,12 +3049,18 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
ret = ext4_split_unwritten_extents(handle,
inode, path, iblock,
max_blocks, flags);
/* flag the io_end struct that we need convert when IO done */
/*
* Flag the inode(non aio case) or end_io struct (aio case)
* that this IO needs to convertion to written when IO is
* completed
*/
if (io)
io->flag = DIO_AIO_UNWRITTEN;
else
EXT4_I(inode)->i_state |= EXT4_STATE_DIO_UNWRITTEN;
goto out;
}
/* DIO end_io complete, convert the filled extent to written */
/* async DIO end_io complete, convert the filled extent to written */
if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) {
ret = ext4_convert_unwritten_extents_dio(handle, inode,
path);
......@@ -3295,10 +3302,16 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
* To avoid unecessary convertion for every aio dio rewrite
* to the mid of file, here we flag the IO that is really
* need the convertion.
*
* For non asycn direct IO case, flag the inode state
* that we need to perform convertion when IO is done.
*/
if (io && flags == EXT4_GET_BLOCKS_DIO_CREATE_EXT)
io->flag = DIO_AIO_UNWRITTEN;
if (flags == EXT4_GET_BLOCKS_DIO_CREATE_EXT) {
if (io)
io->flag = DIO_AIO_UNWRITTEN;
else
EXT4_I(inode)->i_state |=
EXT4_STATE_DIO_UNWRITTEN;;
}
}
err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
if (err) {
......@@ -3519,6 +3532,7 @@ retry:
*
* This function is called from the direct IO end io call back
* function, to convert the fallocated extents after IO is completed.
* Returns 0 on success.
*/
int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
loff_t len)
......
......@@ -193,7 +193,7 @@ static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
* so before we call here everything must be consistently dirtied against
* this transaction.
*/
int ext4_truncate_restart_trans(handle_t *handle, struct inode *inode,
int ext4_truncate_restart_trans(handle_t *handle, struct inode *inode,
int nblocks)
{
int ret;
......@@ -209,6 +209,7 @@ static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
up_write(&EXT4_I(inode)->i_data_sem);
ret = ext4_journal_restart(handle, blocks_for_truncate(inode));
down_write(&EXT4_I(inode)->i_data_sem);
ext4_discard_preallocations(inode);
return ret;
}
......@@ -3445,8 +3446,6 @@ out:
return ret;
}
/* Maximum number of blocks we map for direct IO at once. */
static int ext4_get_block_dio_write(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
......@@ -3654,13 +3653,14 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
ext4_io_end_t *io_end = iocb->private;
struct workqueue_struct *wq;
/* if not async direct IO or dio with 0 bytes write, just return */
if (!io_end || !size)
return;
ext_debug("ext4_end_io_dio(): io_end 0x%p"
"for inode %lu, iocb 0x%p, offset %llu, size %llu\n",
iocb->private, io_end->inode->i_ino, iocb, offset,
size);
/* if not async direct IO or dio with 0 bytes write, just return */
if (!io_end || !size)
return;
/* if not aio dio with unwritten extents, just free io and return */
if (io_end->flag != DIO_AIO_UNWRITTEN){
......@@ -3771,13 +3771,19 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
ext4_free_io_end(iocb->private);
iocb->private = NULL;
} else if (ret > 0)
} else if (ret > 0 && (EXT4_I(inode)->i_state &
EXT4_STATE_DIO_UNWRITTEN)) {
int err;
/*
* for non AIO case, since the IO is already
* completed, we could do the convertion right here
*/
ret = ext4_convert_unwritten_extents(inode,
offset, ret);
err = ext4_convert_unwritten_extents(inode,
offset, ret);
if (err < 0)
ret = err;
EXT4_I(inode)->i_state &= ~EXT4_STATE_DIO_UNWRITTEN;
}
return ret;
}
......
......@@ -1518,12 +1518,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
return retval;
if (blocks == 1 && !dx_fallback &&
EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
retval = make_indexed_dir(handle, dentry, inode, bh);
if (retval == -ENOSPC)
brelse(bh);
return retval;
}
EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
return make_indexed_dir(handle, dentry, inode, bh);
brelse(bh);
}
bh = ext4_append(handle, dir, &block, &retval);
......@@ -1532,10 +1528,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
de = (struct ext4_dir_entry_2 *) bh->b_data;
de->inode = 0;
de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize);
retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
if (retval == -ENOSPC)
brelse(bh);
return retval;
return add_dirent_to_buf(handle, dentry, inode, de, bh);
}
/*
......@@ -1664,8 +1657,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
if (!de)
goto cleanup;
err = add_dirent_to_buf(handle, dentry, inode, de, bh);
if (err != -ENOSPC)
bh = NULL;
bh = NULL;
goto cleanup;
journal_error:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment