Skip to contentSkip to conversation

ext4: add dio overwrite nolock]

RFC PATCH Superseded Zheng Liu 1 participant 1 message May 2, 2012

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Zheng Liu

author
#0 lore raw

RFC PATCH 3/3 ext4: add dio overwrite nolock]

[Sorry, when I reply this mail to the mailing list, I get an error. So I resend it to the mailing list.]

----- Forwarded message from Zheng Liu <[email protected]> -----

Date: Wed, 2 May 2012 23:49:35 +0800
From: Zheng Liu <[email protected]>
To: Eric Sandeen <[email protected]>
Cc: "[email protected]" <[email protected]>, Zheng Liu <[email protected]>
Subject: Re: [RFC][PATCH 3/3] ext4: add dio overwrite nolock

Quoted 12 lines · Eric Sandeen
Quoted 3 lines · Zheng Liu

From: Zheng Liu <[email protected] <javascript:;>>

Aligned and overwrite direct IO can be parallelized. In

ext4_file_dio_write,

Quoted 1 line

we first check whether these conditions are satisfied or not. If so, we

unlock

Quoted 1 line

the i_mutex and acquire i_data_sem directly. Meanwhile iocb->private is

set to

Quoted 2 lines

indicate that this is a overwrite dio, and it will be processed in ext4_ext_direct_IO.

Quoted 7 lines

This copies almost 100 lines of generic_file_aio_write() back into ext4. Do we really need to do this? Copying core code into the fs can be a maintenance nightmare...

I'll have to think more about the big picture and whether or not it's possible, but my first reaction is to find a way to leverage or modify existing IO code rather than pasting it all into ext4 with changes...

The key issue is file_update_time. In this function, it starts a new journal. It will cause a deadlock because we usually start a new journal firstly, and then try to lock i_data_sem. But in overwrite this order is reversed. If we can avoid this deadlock, we won't need to copy core code into ext4.

Regards,
Zheng

Quoted 88 lines

-Eric

Quoted 3 lines
---
 fs/ext4/file.c |  140

++++++++++++++++++++++++++++++++++++++++++++++++++++++-

Quoted 20 lines
 1 files changed, 137 insertions(+), 3 deletions(-)
fs/ext4/file.c +7 -2
index e5d6be3..8a5f713 100644
@@ -100,9 +100,21 @@ static ssize_t
 ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
                  unsigned long nr_segs, loff_t pos)
 {
-     struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
-     int unaligned_aio = 0;
+     struct file *file = iocb->ki_filp;
+     struct address_space * mapping = file->f_mapping;
+     struct inode *inode = file->f_path.dentry->d_inode;
+     struct blk_plug plug;
      ssize_t ret;
+     ssize_t written, written_buffered;
+     size_t length = iov_length(iov, nr_segs);
+     size_t ocount;          /* original count */

fs/ext4/file.c static ssize_t · line 120

Quoted 10 lines
fs/ext4/file.c +7 -0
+     size_t count;           /* after file limit checks */
+     int unaligned_aio = 0;
+     int overwrite = 0;
+     loff_t *ppos = &iocb->ki_pos;
+     loff_t endbyte;
+
+     BUG_ON(iocb->ki_pos != pos);
 
      if (!is_sync_kiocb(iocb))
              unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs,

pos);

fs/ext4/file.c ext4_file_dio_write(struct kiocb *iocb, const

Quoted 1 line
fs/ext4/file.c +0 -0
@@ -121,7 +133,129 @@ ext4_file_dio_write(struct kiocb *iocb, const

struct iovec *iov,

Quoted 12 lines
fs/ext4/file.c +8 -1
              ext4_aiodio_wait(inode);
      }
 
-     ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
+     mutex_lock(&inode->i_mutex);
+     blk_start_plug(&plug);
+
+     ocount = 0;
+     ret = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
+     if (ret)
+             goto unlock_out;
+

fs/ext4/file.c ext4_file_dio_write(struct kiocb *iocb, const · line 153

Quoted 10 lines
fs/ext4/file.c +10 -0
+     count = ocount;
+     pos = *ppos;
+
+     vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+
+     /* We can write back this queue in page reclaim */
+     current->backing_dev_info = mapping->backing_dev_info;
+     written = 0;
+
+     ret = generic_write_checks(file, &pos, &count,

S_ISBLK(inode->i_mode));

Quoted 14 lines
fs/ext4/file.c +14 -0
+     if (ret)
+             goto out;
+
+     if (count == 0)
+             goto out;
+
+     ret = file_remove_suid(file);
+     if (ret)
+             goto out;
+
+     file_update_time(file);
+
+     iocb->private = NULL;
+

fs/ext4/file.c ext4_file_dio_write(struct kiocb *iocb, const · line 177

Quoted 10 lines
fs/ext4/file.c +10 -0
+     if (!unaligned_aio && !file->f_mapping->nrpages &&
+         pos + length < i_size_read(inode) &&
+         ext4_should_dioread_nolock(inode)) {
+             struct ext4_map_blocks map;
+             unsigned int blkbits = inode->i_blkbits;
+             int err;
+             int len;
+
+             map.m_lblk = pos >> blkbits;
+             map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >>

blkbits)

Quoted 7 lines

fs/ext4/file.c ext4_file_dio_write(struct kiocb *iocb, const · line 184

Quoted 7 lines
fs/ext4/file.c +7 -0
+                     - map.m_lblk;
+             len = map.m_len;
+
+             err = ext4_map_blocks(NULL, inode, &map, 0);
+             if (err == len && (!map.m_flags ||
+                 map.m_flags & EXT4_MAP_MAPPED)) {
+

----- End forwarded message -----