Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16fe4101 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 {
+25 −11
Original line number Diff line number Diff line
@@ -2807,6 +2807,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 * 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)
		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 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
 *
 * 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)
+15 −9
Original line number Diff line number Diff line
@@ -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 @@ static ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
	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,
			err = ext4_convert_unwritten_extents(inode,
							     offset, ret);
			if (err < 0)
				ret = err;
			EXT4_I(inode)->i_state &= ~EXT4_STATE_DIO_UNWRITTEN;
		}
		return ret;
	}

+4 −12
Original line number Diff line number Diff line
@@ -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,7 +1657,6 @@ 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;
	goto cleanup;