|
@@ -763,39 +763,47 @@ int ext4_get_block_unwritten(struct inode *inode, sector_t iblock,
|
|
/* Maximum number of blocks we map for direct IO at once. */
|
|
/* Maximum number of blocks we map for direct IO at once. */
|
|
#define DIO_MAX_BLOCKS 4096
|
|
#define DIO_MAX_BLOCKS 4096
|
|
|
|
|
|
-static handle_t *start_dio_trans(struct inode *inode,
|
|
|
|
- struct buffer_head *bh_result)
|
|
|
|
|
|
+/*
|
|
|
|
+ * Get blocks function for the cases that need to start a transaction -
|
|
|
|
+ * generally difference cases of direct IO and DAX IO. It also handles retries
|
|
|
|
+ * in case of ENOSPC.
|
|
|
|
+ */
|
|
|
|
+static int ext4_get_block_trans(struct inode *inode, sector_t iblock,
|
|
|
|
+ struct buffer_head *bh_result, int flags)
|
|
{
|
|
{
|
|
int dio_credits;
|
|
int dio_credits;
|
|
|
|
+ handle_t *handle;
|
|
|
|
+ int retries = 0;
|
|
|
|
+ int ret;
|
|
|
|
|
|
/* Trim mapping request to maximum we can map at once for DIO */
|
|
/* Trim mapping request to maximum we can map at once for DIO */
|
|
if (bh_result->b_size >> inode->i_blkbits > DIO_MAX_BLOCKS)
|
|
if (bh_result->b_size >> inode->i_blkbits > DIO_MAX_BLOCKS)
|
|
bh_result->b_size = DIO_MAX_BLOCKS << inode->i_blkbits;
|
|
bh_result->b_size = DIO_MAX_BLOCKS << inode->i_blkbits;
|
|
dio_credits = ext4_chunk_trans_blocks(inode,
|
|
dio_credits = ext4_chunk_trans_blocks(inode,
|
|
bh_result->b_size >> inode->i_blkbits);
|
|
bh_result->b_size >> inode->i_blkbits);
|
|
- return ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, dio_credits);
|
|
|
|
|
|
+retry:
|
|
|
|
+ handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, dio_credits);
|
|
|
|
+ if (IS_ERR(handle))
|
|
|
|
+ return PTR_ERR(handle);
|
|
|
|
+
|
|
|
|
+ ret = _ext4_get_block(inode, iblock, bh_result, flags);
|
|
|
|
+ ext4_journal_stop(handle);
|
|
|
|
+
|
|
|
|
+ if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
|
|
|
|
+ goto retry;
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/* Get block function for DIO reads and writes to inodes without extents */
|
|
/* Get block function for DIO reads and writes to inodes without extents */
|
|
int ext4_dio_get_block(struct inode *inode, sector_t iblock,
|
|
int ext4_dio_get_block(struct inode *inode, sector_t iblock,
|
|
struct buffer_head *bh, int create)
|
|
struct buffer_head *bh, int create)
|
|
{
|
|
{
|
|
- handle_t *handle;
|
|
|
|
- int ret;
|
|
|
|
-
|
|
|
|
/* We don't expect handle for direct IO */
|
|
/* We don't expect handle for direct IO */
|
|
WARN_ON_ONCE(ext4_journal_current_handle());
|
|
WARN_ON_ONCE(ext4_journal_current_handle());
|
|
|
|
|
|
- if (create) {
|
|
|
|
- handle = start_dio_trans(inode, bh);
|
|
|
|
- if (IS_ERR(handle))
|
|
|
|
- return PTR_ERR(handle);
|
|
|
|
- }
|
|
|
|
- ret = _ext4_get_block(inode, iblock, bh,
|
|
|
|
- create ? EXT4_GET_BLOCKS_CREATE : 0);
|
|
|
|
- if (create)
|
|
|
|
- ext4_journal_stop(handle);
|
|
|
|
- return ret;
|
|
|
|
|
|
+ if (!create)
|
|
|
|
+ return _ext4_get_block(inode, iblock, bh, 0);
|
|
|
|
+ return ext4_get_block_trans(inode, iblock, bh, EXT4_GET_BLOCKS_CREATE);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -806,18 +814,13 @@ int ext4_dio_get_block(struct inode *inode, sector_t iblock,
|
|
static int ext4_dio_get_block_unwritten_async(struct inode *inode,
|
|
static int ext4_dio_get_block_unwritten_async(struct inode *inode,
|
|
sector_t iblock, struct buffer_head *bh_result, int create)
|
|
sector_t iblock, struct buffer_head *bh_result, int create)
|
|
{
|
|
{
|
|
- handle_t *handle;
|
|
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
/* We don't expect handle for direct IO */
|
|
/* We don't expect handle for direct IO */
|
|
WARN_ON_ONCE(ext4_journal_current_handle());
|
|
WARN_ON_ONCE(ext4_journal_current_handle());
|
|
|
|
|
|
- handle = start_dio_trans(inode, bh_result);
|
|
|
|
- if (IS_ERR(handle))
|
|
|
|
- return PTR_ERR(handle);
|
|
|
|
- ret = _ext4_get_block(inode, iblock, bh_result,
|
|
|
|
- EXT4_GET_BLOCKS_IO_CREATE_EXT);
|
|
|
|
- ext4_journal_stop(handle);
|
|
|
|
|
|
+ ret = ext4_get_block_trans(inode, iblock, bh_result,
|
|
|
|
+ EXT4_GET_BLOCKS_IO_CREATE_EXT);
|
|
|
|
|
|
/*
|
|
/*
|
|
* When doing DIO using unwritten extents, we need io_end to convert
|
|
* When doing DIO using unwritten extents, we need io_end to convert
|
|
@@ -850,18 +853,13 @@ static int ext4_dio_get_block_unwritten_async(struct inode *inode,
|
|
static int ext4_dio_get_block_unwritten_sync(struct inode *inode,
|
|
static int ext4_dio_get_block_unwritten_sync(struct inode *inode,
|
|
sector_t iblock, struct buffer_head *bh_result, int create)
|
|
sector_t iblock, struct buffer_head *bh_result, int create)
|
|
{
|
|
{
|
|
- handle_t *handle;
|
|
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
/* We don't expect handle for direct IO */
|
|
/* We don't expect handle for direct IO */
|
|
WARN_ON_ONCE(ext4_journal_current_handle());
|
|
WARN_ON_ONCE(ext4_journal_current_handle());
|
|
|
|
|
|
- handle = start_dio_trans(inode, bh_result);
|
|
|
|
- if (IS_ERR(handle))
|
|
|
|
- return PTR_ERR(handle);
|
|
|
|
- ret = _ext4_get_block(inode, iblock, bh_result,
|
|
|
|
- EXT4_GET_BLOCKS_IO_CREATE_EXT);
|
|
|
|
- ext4_journal_stop(handle);
|
|
|
|
|
|
+ ret = ext4_get_block_trans(inode, iblock, bh_result,
|
|
|
|
+ EXT4_GET_BLOCKS_IO_CREATE_EXT);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Mark inode as having pending DIO writes to unwritten extents.
|
|
* Mark inode as having pending DIO writes to unwritten extents.
|