aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
authorMingming Cao <cmm@us.ibm.com>2009-09-28 15:48:29 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-09-28 15:48:29 -0400
commit8d5d02e6b176565c77ff03604908b1453a22044d (patch)
tree0d29e4f28233f24960c7921c1c0a7608077bf713 /fs/ext4/extents.c
parent4c0425ff68b1b87b802ffeda7b6a46ff7da7241c (diff)
ext4: async direct IO for holes and fallocate support
For async direct IO that covers holes or fallocate, the end_io callback function now queued the convertion work on workqueue but don't flush the work rightaway as it might take too long to afford. But when fsync is called after all the data is completed, user expects the metadata also being updated before fsync returns. Thus we need to flush the conversion work when fsync() is called. This patch keep track of a listed of completed async direct io that has a work queued on workqueue. When fsync() is called, it will go through the list and do the conversion. Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index a38e651c004e..10a63096a95a 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3033,6 +3033,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
3033{ 3033{
3034 int ret = 0; 3034 int ret = 0;
3035 int err = 0; 3035 int err = 0;
3036 ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
3036 3037
3037 ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical" 3038 ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical"
3038 "block %llu, max_blocks %u, flags %d, allocated %u", 3039 "block %llu, max_blocks %u, flags %d, allocated %u",
@@ -3045,6 +3046,9 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
3045 ret = ext4_split_unwritten_extents(handle, 3046 ret = ext4_split_unwritten_extents(handle,
3046 inode, path, iblock, 3047 inode, path, iblock,
3047 max_blocks, flags); 3048 max_blocks, flags);
3049 /* flag the io_end struct that we need convert when IO done */
3050 if (io)
3051 io->flag = DIO_AIO_UNWRITTEN;
3048 goto out; 3052 goto out;
3049 } 3053 }
3050 /* DIO end_io complete, convert the filled extent to written */ 3054 /* DIO end_io complete, convert the filled extent to written */
@@ -3130,6 +3134,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
3130 int err = 0, depth, ret, cache_type; 3134 int err = 0, depth, ret, cache_type;
3131 unsigned int allocated = 0; 3135 unsigned int allocated = 0;
3132 struct ext4_allocation_request ar; 3136 struct ext4_allocation_request ar;
3137 ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
3133 3138
3134 __clear_bit(BH_New, &bh_result->b_state); 3139 __clear_bit(BH_New, &bh_result->b_state);
3135 ext_debug("blocks %u/%u requested for inode %lu\n", 3140 ext_debug("blocks %u/%u requested for inode %lu\n",
@@ -3279,8 +3284,20 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
3279 /* try to insert new extent into found leaf and return */ 3284 /* try to insert new extent into found leaf and return */
3280 ext4_ext_store_pblock(&newex, newblock); 3285 ext4_ext_store_pblock(&newex, newblock);
3281 newex.ee_len = cpu_to_le16(ar.len); 3286 newex.ee_len = cpu_to_le16(ar.len);
3282 if (flags & EXT4_GET_BLOCKS_UNINIT_EXT) /* Mark uninitialized */ 3287 /* Mark uninitialized */
3288 if (flags & EXT4_GET_BLOCKS_UNINIT_EXT){
3283 ext4_ext_mark_uninitialized(&newex); 3289 ext4_ext_mark_uninitialized(&newex);
3290 /*
3291 * io_end structure was created for every async
3292 * direct IO write to the middle of the file.
3293 * To avoid unecessary convertion for every aio dio rewrite
3294 * to the mid of file, here we flag the IO that is really
3295 * need the convertion.
3296 *
3297 */
3298 if (io && flags == EXT4_GET_BLOCKS_DIO_CREATE_EXT)
3299 io->flag = DIO_AIO_UNWRITTEN;
3300 }
3284 err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); 3301 err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
3285 if (err) { 3302 if (err) {
3286 /* free data blocks we just allocated */ 3303 /* free data blocks we just allocated */