All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 5/7] f2fs: enhance multithread dio write performance
@ 2015-09-11  6:41 ` Chao Yu
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Yu @ 2015-09-11  6:41 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-f2fs-devel, linux-kernel

When dio writes perform concurrently, our performace will be low because of
Thread A's allocation of multi continuous blocks will be break by Thread B,
there are two cases as below:
 - In Thread B, we may change current segment to a new segment for LFS
   allocation if we dio write in the beginning of the file.
 - In Thread B, we may allocate blocks in the middle of Thread A's
   allocation, which make blocks which allocated in Thread A being
   discontinuous.

This patch adds writepages mutex lock to make block allocation in dio write
atomic to avoid above issues.

Test environment:
ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
32g kingston sd card.

fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs --filesize=256m --size=16m --bs=2m --direct=1
--numjobs=10

before:
  WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec, maxt=52083msec

patched:
  WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec, maxt=16329msec

Signed-off-by: Chao Yu <chao2.yu@samsung.com>
---
 fs/f2fs/data.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index a737ca5..a0a5849 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 	struct file *file = iocb->ki_filp;
 	struct address_space *mapping = file->f_mapping;
 	struct inode *inode = mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
 	size_t count = iov_iter_count(iter);
+	int rw = iov_iter_rw(iter);
 	int err;
 
 	/* we don't need to use inline_data strictly */
@@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 
 	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
 
-	if (iov_iter_rw(iter) == WRITE)
+	if (rw == WRITE) {
+		mutex_lock(&sbi->writepages);
 		__allocate_data_blocks(inode, offset, count);
+	}
 
 	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
-	if (err < 0 && iov_iter_rw(iter) == WRITE)
-		f2fs_write_failed(mapping, offset + count);
+	if (rw == WRITE) {
+		mutex_unlock(&sbi->writepages);
+		if (err)
+			f2fs_write_failed(mapping, offset + count);
+	}
 
 	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
 
-- 
2.4.2



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/7] f2fs: enhance multithread dio write performance
@ 2015-09-11  6:41 ` Chao Yu
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Yu @ 2015-09-11  6:41 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-kernel, linux-f2fs-devel

When dio writes perform concurrently, our performace will be low because of
Thread A's allocation of multi continuous blocks will be break by Thread B,
there are two cases as below:
 - In Thread B, we may change current segment to a new segment for LFS
   allocation if we dio write in the beginning of the file.
 - In Thread B, we may allocate blocks in the middle of Thread A's
   allocation, which make blocks which allocated in Thread A being
   discontinuous.

This patch adds writepages mutex lock to make block allocation in dio write
atomic to avoid above issues.

Test environment:
ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
32g kingston sd card.

fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs --filesize=256m --size=16m --bs=2m --direct=1
--numjobs=10

before:
  WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec, maxt=52083msec

patched:
  WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec, maxt=16329msec

Signed-off-by: Chao Yu <chao2.yu@samsung.com>
---
 fs/f2fs/data.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index a737ca5..a0a5849 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 	struct file *file = iocb->ki_filp;
 	struct address_space *mapping = file->f_mapping;
 	struct inode *inode = mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
 	size_t count = iov_iter_count(iter);
+	int rw = iov_iter_rw(iter);
 	int err;
 
 	/* we don't need to use inline_data strictly */
@@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 
 	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
 
-	if (iov_iter_rw(iter) == WRITE)
+	if (rw == WRITE) {
+		mutex_lock(&sbi->writepages);
 		__allocate_data_blocks(inode, offset, count);
+	}
 
 	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
-	if (err < 0 && iov_iter_rw(iter) == WRITE)
-		f2fs_write_failed(mapping, offset + count);
+	if (rw == WRITE) {
+		mutex_unlock(&sbi->writepages);
+		if (err)
+			f2fs_write_failed(mapping, offset + count);
+	}
 
 	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
 
-- 
2.4.2



------------------------------------------------------------------------------

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
  2015-09-11  6:41 ` Chao Yu
  (?)
@ 2015-09-15 21:20 ` Jaegeuk Kim
  2015-09-16 10:15   ` Chao Yu
  -1 siblings, 1 reply; 15+ messages in thread
From: Jaegeuk Kim @ 2015-09-15 21:20 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-f2fs-devel, linux-kernel

Hi Chao,

On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> When dio writes perform concurrently, our performace will be low because of
> Thread A's allocation of multi continuous blocks will be break by Thread B,
> there are two cases as below:
>  - In Thread B, we may change current segment to a new segment for LFS
>    allocation if we dio write in the beginning of the file.
>  - In Thread B, we may allocate blocks in the middle of Thread A's
>    allocation, which make blocks which allocated in Thread A being
>    discontinuous.
> 
> This patch adds writepages mutex lock to make block allocation in dio write
> atomic to avoid above issues.
> 
> Test environment:
> ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> 32g kingston sd card.
> 
> fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs --filesize=256m --size=16m --bs=2m --direct=1
> --numjobs=10
> 
> before:
>   WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec, maxt=52083msec
> 
> patched:
>   WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec, maxt=16329msec
> 
> Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> ---
>  fs/f2fs/data.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index a737ca5..a0a5849 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
>  	struct file *file = iocb->ki_filp;
>  	struct address_space *mapping = file->f_mapping;
>  	struct inode *inode = mapping->host;
> +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
>  	size_t count = iov_iter_count(iter);
> +	int rw = iov_iter_rw(iter);
>  	int err;
>  
>  	/* we don't need to use inline_data strictly */
> @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
>  
>  	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
>  
> -	if (iov_iter_rw(iter) == WRITE)
> +	if (rw == WRITE) {
> +		mutex_lock(&sbi->writepages);

Why do we have to share sbi->writepages?

>  		__allocate_data_blocks(inode, offset, count);

If the problem lies on the misaligned blocks, how about calling mutex_unlock
here?

Thanks,

> +	}
>  
>  	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> -		f2fs_write_failed(mapping, offset + count);
> +	if (rw == WRITE) {
> +		mutex_unlock(&sbi->writepages);
> +		if (err)
> +			f2fs_write_failed(mapping, offset + count);
> +	}
>  
>  	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
>  
> -- 
> 2.4.2

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 5/7] f2fs: enhance multithread dio write performance
  2015-09-15 21:20 ` Jaegeuk Kim
@ 2015-09-16 10:15   ` Chao Yu
  2015-09-16 18:12       ` Jaegeuk Kim
  2015-09-17  0:39       ` He YunLei
  0 siblings, 2 replies; 15+ messages in thread
From: Chao Yu @ 2015-09-16 10:15 UTC (permalink / raw)
  To: 'Jaegeuk Kim'; +Cc: linux-f2fs-devel, linux-kernel

Hi Jaegeuk,

> -----Original Message-----
> From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> Sent: Wednesday, September 16, 2015 5:21 AM
> To: Chao Yu
> Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> 
> Hi Chao,
> 
> On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> > When dio writes perform concurrently, our performace will be low because of
> > Thread A's allocation of multi continuous blocks will be break by Thread B,
> > there are two cases as below:
> >  - In Thread B, we may change current segment to a new segment for LFS
> >    allocation if we dio write in the beginning of the file.
> >  - In Thread B, we may allocate blocks in the middle of Thread A's
> >    allocation, which make blocks which allocated in Thread A being
> >    discontinuous.
> >
> > This patch adds writepages mutex lock to make block allocation in dio write
> > atomic to avoid above issues.
> >
> > Test environment:
> > ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> > 32g kingston sd card.
> >
> > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> --filesize=256m --size=16m --bs=2m --direct=1
> > --numjobs=10
> >
> > before:
> >   WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
> maxt=52083msec
> >
> > patched:
> >   WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
> maxt=16329msec
> >
> > Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> > ---
> >  fs/f2fs/data.c | 13 ++++++++++---
> >  1 file changed, 10 insertions(+), 3 deletions(-)
> >
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index a737ca5..a0a5849 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
> >  	struct file *file = iocb->ki_filp;
> >  	struct address_space *mapping = file->f_mapping;
> >  	struct inode *inode = mapping->host;
> > +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> >  	size_t count = iov_iter_count(iter);
> > +	int rw = iov_iter_rw(iter);
> >  	int err;
> >
> >  	/* we don't need to use inline_data strictly */
> > @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> *iter,
> >
> >  	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
> >
> > -	if (iov_iter_rw(iter) == WRITE)
> > +	if (rw == WRITE) {
> > +		mutex_lock(&sbi->writepages);
> 
> Why do we have to share sbi->writepages?

The root cause of this issue is that: in f2fs, we have no suitable
dispatcher which can do the following things as an atomic operation:
a) allocate position(s) in flash device for current block(s);
b) submit user data in allocated position(s) in block layer.

Without the dispatcher, we will suffer performance issue in following
scenario:
Thread A		Thread B		Thread C
allocate pos+1
			allocate pos+2
						allocate pos+3
submit pos+1
						submit pos+3
			submit pos+2

Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
running into non-LFS mode, therefore resulting in bad performance.

writepages mutex lock supply us with a good solution for above issue.
It not only make the allocating and submitting pair executing atomically,
but also reduce the fragmentation for one file since we submit blocks
belong to single inode as continuous as possible.

So here I choose to use writepages mutex lock to fix the performance
issue caused by both dio write vs dio write and dio write vs buffered
write.

If I'm missing something, please correct me.

> 
> >  		__allocate_data_blocks(inode, offset, count);
> 
> If the problem lies on the misaligned blocks, how about calling mutex_unlock
> here?

When changing to unlock here, I got regression when testing with following command:
fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs --filesize=256m --size=4m --bs=64k --direct=1
--numjobs=20

unlock here:
  WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec, maxt=14119msec
unlock after dio finished:
  WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec, maxt=13454msec

So how about keep it in original place in this patch?

Thanks,
> 
> Thanks,
> 
> > +	}
> >
> >  	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> > -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> > -		f2fs_write_failed(mapping, offset + count);
> > +	if (rw == WRITE) {
> > +		mutex_unlock(&sbi->writepages);
> > +		if (err)
> > +			f2fs_write_failed(mapping, offset + count);
> > +	}
> >
> >  	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
> >
> > --
> > 2.4.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
  2015-09-16 10:15   ` Chao Yu
@ 2015-09-16 18:12       ` Jaegeuk Kim
  2015-09-17  0:39       ` He YunLei
  1 sibling, 0 replies; 15+ messages in thread
From: Jaegeuk Kim @ 2015-09-16 18:12 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-f2fs-devel, linux-kernel

Hi Chao,

On Wed, Sep 16, 2015 at 06:15:55PM +0800, Chao Yu wrote:
> Hi Jaegeuk,
> 
> > -----Original Message-----
> > From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> > Sent: Wednesday, September 16, 2015 5:21 AM
> > To: Chao Yu
> > Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> > Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> > 
> > Hi Chao,
> > 
> > On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> > > When dio writes perform concurrently, our performace will be low because of
> > > Thread A's allocation of multi continuous blocks will be break by Thread B,
> > > there are two cases as below:
> > >  - In Thread B, we may change current segment to a new segment for LFS
> > >    allocation if we dio write in the beginning of the file.
> > >  - In Thread B, we may allocate blocks in the middle of Thread A's
> > >    allocation, which make blocks which allocated in Thread A being
> > >    discontinuous.
> > >
> > > This patch adds writepages mutex lock to make block allocation in dio write
> > > atomic to avoid above issues.
> > >
> > > Test environment:
> > > ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> > > 32g kingston sd card.
> > >
> > > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> > --filesize=256m --size=16m --bs=2m --direct=1
> > > --numjobs=10
> > >
> > > before:
> > >   WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
> > maxt=52083msec
> > >
> > > patched:
> > >   WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
> > maxt=16329msec
> > >
> > > Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> > > ---
> > >  fs/f2fs/data.c | 13 ++++++++++---
> > >  1 file changed, 10 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > > index a737ca5..a0a5849 100644
> > > --- a/fs/f2fs/data.c
> > > +++ b/fs/f2fs/data.c
> > > @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
> > >  	struct file *file = iocb->ki_filp;
> > >  	struct address_space *mapping = file->f_mapping;
> > >  	struct inode *inode = mapping->host;
> > > +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> > >  	size_t count = iov_iter_count(iter);
> > > +	int rw = iov_iter_rw(iter);
> > >  	int err;
> > >
> > >  	/* we don't need to use inline_data strictly */
> > > @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> > *iter,
> > >
> > >  	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
> > >
> > > -	if (iov_iter_rw(iter) == WRITE)
> > > +	if (rw == WRITE) {
> > > +		mutex_lock(&sbi->writepages);
> > 
> > Why do we have to share sbi->writepages?
> 
> The root cause of this issue is that: in f2fs, we have no suitable
> dispatcher which can do the following things as an atomic operation:
> a) allocate position(s) in flash device for current block(s);
> b) submit user data in allocated position(s) in block layer.
> 
> Without the dispatcher, we will suffer performance issue in following
> scenario:
> Thread A		Thread B		Thread C
> allocate pos+1
> 			allocate pos+2
> 						allocate pos+3
> submit pos+1
> 						submit pos+3
> 			submit pos+2
> 
> Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> running into non-LFS mode, therefore resulting in bad performance.
> 
> writepages mutex lock supply us with a good solution for above issue.
> It not only make the allocating and submitting pair executing atomically,
> but also reduce the fragmentation for one file since we submit blocks
> belong to single inode as continuous as possible.
> 
> So here I choose to use writepages mutex lock to fix the performance
> issue caused by both dio write vs dio write and dio write vs buffered
> write.

Understood, but the concern was the multi-thread performance as you mentioned.
If one thread throws a big dio request, anybody cannot write at all?
How about adding some limits likewise f2fs_write_data_pages whieh is for example
nr_pages_to_write?

Thanks,

> 
> If I'm missing something, please correct me.
> 
> > 
> > >  		__allocate_data_blocks(inode, offset, count);
> > 
> > If the problem lies on the misaligned blocks, how about calling mutex_unlock
> > here?
> 
> When changing to unlock here, I got regression when testing with following command:
> fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs --filesize=256m --size=4m --bs=64k --direct=1
> --numjobs=20
> 
> unlock here:
>   WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec, maxt=14119msec
> unlock after dio finished:
>   WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec, maxt=13454msec
> 
> So how about keep it in original place in this patch?
> 
> Thanks,
> > 
> > Thanks,
> > 
> > > +	}
> > >
> > >  	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> > > -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> > > -		f2fs_write_failed(mapping, offset + count);
> > > +	if (rw == WRITE) {
> > > +		mutex_unlock(&sbi->writepages);
> > > +		if (err)
> > > +			f2fs_write_failed(mapping, offset + count);
> > > +	}
> > >
> > >  	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
> > >
> > > --
> > > 2.4.2

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
@ 2015-09-16 18:12       ` Jaegeuk Kim
  0 siblings, 0 replies; 15+ messages in thread
From: Jaegeuk Kim @ 2015-09-16 18:12 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel

Hi Chao,

On Wed, Sep 16, 2015 at 06:15:55PM +0800, Chao Yu wrote:
> Hi Jaegeuk,
> 
> > -----Original Message-----
> > From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> > Sent: Wednesday, September 16, 2015 5:21 AM
> > To: Chao Yu
> > Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> > Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> > 
> > Hi Chao,
> > 
> > On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> > > When dio writes perform concurrently, our performace will be low because of
> > > Thread A's allocation of multi continuous blocks will be break by Thread B,
> > > there are two cases as below:
> > >  - In Thread B, we may change current segment to a new segment for LFS
> > >    allocation if we dio write in the beginning of the file.
> > >  - In Thread B, we may allocate blocks in the middle of Thread A's
> > >    allocation, which make blocks which allocated in Thread A being
> > >    discontinuous.
> > >
> > > This patch adds writepages mutex lock to make block allocation in dio write
> > > atomic to avoid above issues.
> > >
> > > Test environment:
> > > ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> > > 32g kingston sd card.
> > >
> > > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> > --filesize=256m --size=16m --bs=2m --direct=1
> > > --numjobs=10
> > >
> > > before:
> > >   WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
> > maxt=52083msec
> > >
> > > patched:
> > >   WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
> > maxt=16329msec
> > >
> > > Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> > > ---
> > >  fs/f2fs/data.c | 13 ++++++++++---
> > >  1 file changed, 10 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > > index a737ca5..a0a5849 100644
> > > --- a/fs/f2fs/data.c
> > > +++ b/fs/f2fs/data.c
> > > @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
> > >  	struct file *file = iocb->ki_filp;
> > >  	struct address_space *mapping = file->f_mapping;
> > >  	struct inode *inode = mapping->host;
> > > +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> > >  	size_t count = iov_iter_count(iter);
> > > +	int rw = iov_iter_rw(iter);
> > >  	int err;
> > >
> > >  	/* we don't need to use inline_data strictly */
> > > @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> > *iter,
> > >
> > >  	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
> > >
> > > -	if (iov_iter_rw(iter) == WRITE)
> > > +	if (rw == WRITE) {
> > > +		mutex_lock(&sbi->writepages);
> > 
> > Why do we have to share sbi->writepages?
> 
> The root cause of this issue is that: in f2fs, we have no suitable
> dispatcher which can do the following things as an atomic operation:
> a) allocate position(s) in flash device for current block(s);
> b) submit user data in allocated position(s) in block layer.
> 
> Without the dispatcher, we will suffer performance issue in following
> scenario:
> Thread A		Thread B		Thread C
> allocate pos+1
> 			allocate pos+2
> 						allocate pos+3
> submit pos+1
> 						submit pos+3
> 			submit pos+2
> 
> Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> running into non-LFS mode, therefore resulting in bad performance.
> 
> writepages mutex lock supply us with a good solution for above issue.
> It not only make the allocating and submitting pair executing atomically,
> but also reduce the fragmentation for one file since we submit blocks
> belong to single inode as continuous as possible.
> 
> So here I choose to use writepages mutex lock to fix the performance
> issue caused by both dio write vs dio write and dio write vs buffered
> write.

Understood, but the concern was the multi-thread performance as you mentioned.
If one thread throws a big dio request, anybody cannot write at all?
How about adding some limits likewise f2fs_write_data_pages whieh is for example
nr_pages_to_write?

Thanks,

> 
> If I'm missing something, please correct me.
> 
> > 
> > >  		__allocate_data_blocks(inode, offset, count);
> > 
> > If the problem lies on the misaligned blocks, how about calling mutex_unlock
> > here?
> 
> When changing to unlock here, I got regression when testing with following command:
> fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs --filesize=256m --size=4m --bs=64k --direct=1
> --numjobs=20
> 
> unlock here:
>   WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec, maxt=14119msec
> unlock after dio finished:
>   WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec, maxt=13454msec
> 
> So how about keep it in original place in this patch?
> 
> Thanks,
> > 
> > Thanks,
> > 
> > > +	}
> > >
> > >  	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> > > -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> > > -		f2fs_write_failed(mapping, offset + count);
> > > +	if (rw == WRITE) {
> > > +		mutex_unlock(&sbi->writepages);
> > > +		if (err)
> > > +			f2fs_write_failed(mapping, offset + count);
> > > +	}
> > >
> > >  	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
> > >
> > > --
> > > 2.4.2

------------------------------------------------------------------------------
Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
Get real-time metrics from all of your servers, apps and tools
in one place.
SourceForge users - Click here to start your Free Trial of Datadog now!
http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [f2fs-dev] [PATCH 5/7] f2fs: enhance multithread dio write performance
  2015-09-16 10:15   ` Chao Yu
@ 2015-09-17  0:39       ` He YunLei
  2015-09-17  0:39       ` He YunLei
  1 sibling, 0 replies; 15+ messages in thread
From: He YunLei @ 2015-09-17  0:39 UTC (permalink / raw)
  To: Chao Yu; +Cc: 'Jaegeuk Kim', linux-kernel, linux-f2fs-devel

On 2015/9/16 18:15, Chao Yu wrote:
> Hi Jaegeuk,
>
>> -----Original Message-----
>> From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
>> Sent: Wednesday, September 16, 2015 5:21 AM
>> To: Chao Yu
>> Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
>> Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
>>
>> Hi Chao,
>>
>> On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
>>> When dio writes perform concurrently, our performace will be low because of
>>> Thread A's allocation of multi continuous blocks will be break by Thread B,
>>> there are two cases as below:
>>>   - In Thread B, we may change current segment to a new segment for LFS
>>>     allocation if we dio write in the beginning of the file.
>>>   - In Thread B, we may allocate blocks in the middle of Thread A's
>>>     allocation, which make blocks which allocated in Thread A being
>>>     discontinuous.
>>>
>>> This patch adds writepages mutex lock to make block allocation in dio write
>>> atomic to avoid above issues.
>>>
>>> Test environment:
>>> ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
>>> 32g kingston sd card.
>>>
>>> fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
>> --filesize=256m --size=16m --bs=2m --direct=1
>>> --numjobs=10
>>>
>>> before:
>>>    WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
>> maxt=52083msec
>>>
>>> patched:
>>>    WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
>> maxt=16329msec
>>>
>>> Signed-off-by: Chao Yu <chao2.yu@samsung.com>
>>> ---
>>>   fs/f2fs/data.c | 13 ++++++++++---
>>>   1 file changed, 10 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
>>> index a737ca5..a0a5849 100644
>>> --- a/fs/f2fs/data.c
>>> +++ b/fs/f2fs/data.c
>>> @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
>>>   	struct file *file = iocb->ki_filp;
>>>   	struct address_space *mapping = file->f_mapping;
>>>   	struct inode *inode = mapping->host;
>>> +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
>>>   	size_t count = iov_iter_count(iter);
>>> +	int rw = iov_iter_rw(iter);
>>>   	int err;
>>>
>>>   	/* we don't need to use inline_data strictly */
>>> @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
>> *iter,
>>>
>>>   	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
>>>
>>> -	if (iov_iter_rw(iter) == WRITE)
>>> +	if (rw == WRITE) {
>>> +		mutex_lock(&sbi->writepages);
>>
>> Why do we have to share sbi->writepages?
>
> The root cause of this issue is that: in f2fs, we have no suitable
> dispatcher which can do the following things as an atomic operation:
> a) allocate position(s) in flash device for current block(s);
> b) submit user data in allocated position(s) in block layer.
>
> Without the dispatcher, we will suffer performance issue in following
> scenario:
> Thread A		Thread B		Thread C
> allocate pos+1
> 			allocate pos+2
> 						allocate pos+3
> submit pos+1
> 						submit pos+3
> 			submit pos+2
>
> Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> running into non-LFS mode, therefore resulting in bad performance.
>
> writepages mutex lock supply us with a good solution for above issue.
> It not only make the allocating and submitting pair executing atomically,
> but also reduce the fragmentation for one file since we submit blocks
> belong to single inode as continuous as possible.
>
> So here I choose to use writepages mutex lock to fix the performance
> issue caused by both dio write vs dio write and dio write vs buffered
> write.
>
> If I'm missing something, please correct me.
>
>>
>>>   		__allocate_data_blocks(inode, offset, count);
>>
>> If the problem lies on the misaligned blocks, how about calling mutex_unlock
>> here?
>
> When changing to unlock here, I got regression when testing with following command:
> fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs --filesize=256m --size=4m --bs=64k --direct=1
> --numjobs=20
>
> unlock here:
>    WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec, maxt=14119msec
> unlock after dio finished:
>    WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec, maxt=13454msec
>
> So how about keep it in original place in this patch?

Does share writepages mutex lock have an effect on cache write? Here is AndroBench result on my phone:

Before patch:
				1R1W               8R8W               16R16W
Sequential Write               161.31             163.85              154.67
Random  Write                   9.48               17.66               18.09


After patch:
				1R1W               8R8W               16R16W
Sequential Write               159.61             157.24              160.11
Random  Write                   9.17               8.51                8.8

Unit:Mb/s, File size: 64M, Buffer size: 4k

>
> Thanks,
>>
>> Thanks,
>>
>>> +	}
>>>
>>>   	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
>>> -	if (err < 0 && iov_iter_rw(iter) == WRITE)
>>> -		f2fs_write_failed(mapping, offset + count);
>>> +	if (rw == WRITE) {
>>> +		mutex_unlock(&sbi->writepages);
>>> +		if (err)
>>> +			f2fs_write_failed(mapping, offset + count);
>>> +	}
>>>
>>>   	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
>>>
>>> --
>>> 2.4.2
>
>
> ------------------------------------------------------------------------------
> Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
> Get real-time metrics from all of your servers, apps and tools
> in one place.
> SourceForge users - Click here to start your Free Trial of Datadog now!
> http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
>
> .
>


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
@ 2015-09-17  0:39       ` He YunLei
  0 siblings, 0 replies; 15+ messages in thread
From: He YunLei @ 2015-09-17  0:39 UTC (permalink / raw)
  To: Chao Yu; +Cc: 'Jaegeuk Kim', linux-kernel, linux-f2fs-devel

On 2015/9/16 18:15, Chao Yu wrote:
> Hi Jaegeuk,
>
>> -----Original Message-----
>> From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
>> Sent: Wednesday, September 16, 2015 5:21 AM
>> To: Chao Yu
>> Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
>> Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
>>
>> Hi Chao,
>>
>> On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
>>> When dio writes perform concurrently, our performace will be low because of
>>> Thread A's allocation of multi continuous blocks will be break by Thread B,
>>> there are two cases as below:
>>>   - In Thread B, we may change current segment to a new segment for LFS
>>>     allocation if we dio write in the beginning of the file.
>>>   - In Thread B, we may allocate blocks in the middle of Thread A's
>>>     allocation, which make blocks which allocated in Thread A being
>>>     discontinuous.
>>>
>>> This patch adds writepages mutex lock to make block allocation in dio write
>>> atomic to avoid above issues.
>>>
>>> Test environment:
>>> ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
>>> 32g kingston sd card.
>>>
>>> fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
>> --filesize=256m --size=16m --bs=2m --direct=1
>>> --numjobs=10
>>>
>>> before:
>>>    WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
>> maxt=52083msec
>>>
>>> patched:
>>>    WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
>> maxt=16329msec
>>>
>>> Signed-off-by: Chao Yu <chao2.yu@samsung.com>
>>> ---
>>>   fs/f2fs/data.c | 13 ++++++++++---
>>>   1 file changed, 10 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
>>> index a737ca5..a0a5849 100644
>>> --- a/fs/f2fs/data.c
>>> +++ b/fs/f2fs/data.c
>>> @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
>>>   	struct file *file = iocb->ki_filp;
>>>   	struct address_space *mapping = file->f_mapping;
>>>   	struct inode *inode = mapping->host;
>>> +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
>>>   	size_t count = iov_iter_count(iter);
>>> +	int rw = iov_iter_rw(iter);
>>>   	int err;
>>>
>>>   	/* we don't need to use inline_data strictly */
>>> @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
>> *iter,
>>>
>>>   	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
>>>
>>> -	if (iov_iter_rw(iter) == WRITE)
>>> +	if (rw == WRITE) {
>>> +		mutex_lock(&sbi->writepages);
>>
>> Why do we have to share sbi->writepages?
>
> The root cause of this issue is that: in f2fs, we have no suitable
> dispatcher which can do the following things as an atomic operation:
> a) allocate position(s) in flash device for current block(s);
> b) submit user data in allocated position(s) in block layer.
>
> Without the dispatcher, we will suffer performance issue in following
> scenario:
> Thread A		Thread B		Thread C
> allocate pos+1
> 			allocate pos+2
> 						allocate pos+3
> submit pos+1
> 						submit pos+3
> 			submit pos+2
>
> Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> running into non-LFS mode, therefore resulting in bad performance.
>
> writepages mutex lock supply us with a good solution for above issue.
> It not only make the allocating and submitting pair executing atomically,
> but also reduce the fragmentation for one file since we submit blocks
> belong to single inode as continuous as possible.
>
> So here I choose to use writepages mutex lock to fix the performance
> issue caused by both dio write vs dio write and dio write vs buffered
> write.
>
> If I'm missing something, please correct me.
>
>>
>>>   		__allocate_data_blocks(inode, offset, count);
>>
>> If the problem lies on the misaligned blocks, how about calling mutex_unlock
>> here?
>
> When changing to unlock here, I got regression when testing with following command:
> fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs --filesize=256m --size=4m --bs=64k --direct=1
> --numjobs=20
>
> unlock here:
>    WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec, maxt=14119msec
> unlock after dio finished:
>    WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec, maxt=13454msec
>
> So how about keep it in original place in this patch?

Does share writepages mutex lock have an effect on cache write? Here is AndroBench result on my phone:

Before patch:
				1R1W               8R8W               16R16W
Sequential Write               161.31             163.85              154.67
Random  Write                   9.48               17.66               18.09


After patch:
				1R1W               8R8W               16R16W
Sequential Write               159.61             157.24              160.11
Random  Write                   9.17               8.51                8.8

Unit:Mb/s, File size: 64M, Buffer size: 4k

>
> Thanks,
>>
>> Thanks,
>>
>>> +	}
>>>
>>>   	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
>>> -	if (err < 0 && iov_iter_rw(iter) == WRITE)
>>> -		f2fs_write_failed(mapping, offset + count);
>>> +	if (rw == WRITE) {
>>> +		mutex_unlock(&sbi->writepages);
>>> +		if (err)
>>> +			f2fs_write_failed(mapping, offset + count);
>>> +	}
>>>
>>>   	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
>>>
>>> --
>>> 2.4.2
>
>
> ------------------------------------------------------------------------------
> Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
> Get real-time metrics from all of your servers, apps and tools
> in one place.
> SourceForge users - Click here to start your Free Trial of Datadog now!
> http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
>
> .
>


------------------------------------------------------------------------------
Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
Get real-time metrics from all of your servers, apps and tools
in one place.
SourceForge users - Click here to start your Free Trial of Datadog now!
http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 5/7] f2fs: enhance multithread dio write performance
  2015-09-16 18:12       ` Jaegeuk Kim
@ 2015-09-17 12:52         ` Chao Yu
  -1 siblings, 0 replies; 15+ messages in thread
From: Chao Yu @ 2015-09-17 12:52 UTC (permalink / raw)
  To: 'Jaegeuk Kim'; +Cc: linux-f2fs-devel, linux-kernel

Hi Jaegeuk,

> -----Original Message-----
> From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> Sent: Thursday, September 17, 2015 2:13 AM
> To: Chao Yu
> Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> 
> Hi Chao,
> 
> On Wed, Sep 16, 2015 at 06:15:55PM +0800, Chao Yu wrote:
> > Hi Jaegeuk,
> >
> > > -----Original Message-----
> > > From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> > > Sent: Wednesday, September 16, 2015 5:21 AM
> > > To: Chao Yu
> > > Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> > > Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> > >
> > > Hi Chao,
> > >
> > > On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> > > > When dio writes perform concurrently, our performace will be low because of
> > > > Thread A's allocation of multi continuous blocks will be break by Thread B,
> > > > there are two cases as below:
> > > >  - In Thread B, we may change current segment to a new segment for LFS
> > > >    allocation if we dio write in the beginning of the file.
> > > >  - In Thread B, we may allocate blocks in the middle of Thread A's
> > > >    allocation, which make blocks which allocated in Thread A being
> > > >    discontinuous.
> > > >
> > > > This patch adds writepages mutex lock to make block allocation in dio write
> > > > atomic to avoid above issues.
> > > >
> > > > Test environment:
> > > > ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> > > > 32g kingston sd card.
> > > >
> > > > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> > > --filesize=256m --size=16m --bs=2m --direct=1
> > > > --numjobs=10
> > > >
> > > > before:
> > > >   WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
> > > maxt=52083msec
> > > >
> > > > patched:
> > > >   WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
> > > maxt=16329msec
> > > >
> > > > Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> > > > ---
> > > >  fs/f2fs/data.c | 13 ++++++++++---
> > > >  1 file changed, 10 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > > > index a737ca5..a0a5849 100644
> > > > --- a/fs/f2fs/data.c
> > > > +++ b/fs/f2fs/data.c
> > > > @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> *iter,
> > > >  	struct file *file = iocb->ki_filp;
> > > >  	struct address_space *mapping = file->f_mapping;
> > > >  	struct inode *inode = mapping->host;
> > > > +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> > > >  	size_t count = iov_iter_count(iter);
> > > > +	int rw = iov_iter_rw(iter);
> > > >  	int err;
> > > >
> > > >  	/* we don't need to use inline_data strictly */
> > > > @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> > > *iter,
> > > >
> > > >  	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
> > > >
> > > > -	if (iov_iter_rw(iter) == WRITE)
> > > > +	if (rw == WRITE) {
> > > > +		mutex_lock(&sbi->writepages);
> > >
> > > Why do we have to share sbi->writepages?
> >
> > The root cause of this issue is that: in f2fs, we have no suitable
> > dispatcher which can do the following things as an atomic operation:
> > a) allocate position(s) in flash device for current block(s);
> > b) submit user data in allocated position(s) in block layer.
> >
> > Without the dispatcher, we will suffer performance issue in following
> > scenario:
> > Thread A		Thread B		Thread C
> > allocate pos+1
> > 			allocate pos+2
> > 						allocate pos+3
> > submit pos+1
> > 						submit pos+3
> > 			submit pos+2
> >
> > Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> > running into non-LFS mode, therefore resulting in bad performance.
> >
> > writepages mutex lock supply us with a good solution for above issue.
> > It not only make the allocating and submitting pair executing atomically,
> > but also reduce the fragmentation for one file since we submit blocks
> > belong to single inode as continuous as possible.
> >
> > So here I choose to use writepages mutex lock to fix the performance
> > issue caused by both dio write vs dio write and dio write vs buffered
> > write.
> 
> Understood, but the concern was the multi-thread performance as you mentioned.
> If one thread throws a big dio request, anybody cannot write at all?

Buffered write will not be stopped, but actually my way completely stops the
concurrency of multithreads which are doing dio writes, for aspect of improving
concurrency, moving mutex_unlock below __allocate_data_blocks is a good solution
so far.

> How about adding some limits likewise f2fs_write_data_pages whieh is for example
> nr_pages_to_write?

Could you share more details about your idea?

As Yunlei reported, there is performance regression issue, so how about
holding this patch and let me do some investigation?

Thanks,

> 
> Thanks,
> 
> >
> > If I'm missing something, please correct me.
> >
> > >
> > > >  		__allocate_data_blocks(inode, offset, count);
> > >
> > > If the problem lies on the misaligned blocks, how about calling mutex_unlock
> > > here?
> >
> > When changing to unlock here, I got regression when testing with following command:
> > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> --filesize=256m --size=4m --bs=64k --direct=1
> > --numjobs=20
> >
> > unlock here:
> >   WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec,
> maxt=14119msec
> > unlock after dio finished:
> >   WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec,
> maxt=13454msec
> >
> > So how about keep it in original place in this patch?
> >
> > Thanks,
> > >
> > > Thanks,
> > >
> > > > +	}
> > > >
> > > >  	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> > > > -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> > > > -		f2fs_write_failed(mapping, offset + count);
> > > > +	if (rw == WRITE) {
> > > > +		mutex_unlock(&sbi->writepages);
> > > > +		if (err)
> > > > +			f2fs_write_failed(mapping, offset + count);
> > > > +	}
> > > >
> > > >  	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
> > > >
> > > > --
> > > > 2.4.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
@ 2015-09-17 12:52         ` Chao Yu
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Yu @ 2015-09-17 12:52 UTC (permalink / raw)
  To: 'Jaegeuk Kim'; +Cc: linux-kernel, linux-f2fs-devel

Hi Jaegeuk,

> -----Original Message-----
> From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> Sent: Thursday, September 17, 2015 2:13 AM
> To: Chao Yu
> Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> 
> Hi Chao,
> 
> On Wed, Sep 16, 2015 at 06:15:55PM +0800, Chao Yu wrote:
> > Hi Jaegeuk,
> >
> > > -----Original Message-----
> > > From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> > > Sent: Wednesday, September 16, 2015 5:21 AM
> > > To: Chao Yu
> > > Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> > > Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> > >
> > > Hi Chao,
> > >
> > > On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> > > > When dio writes perform concurrently, our performace will be low because of
> > > > Thread A's allocation of multi continuous blocks will be break by Thread B,
> > > > there are two cases as below:
> > > >  - In Thread B, we may change current segment to a new segment for LFS
> > > >    allocation if we dio write in the beginning of the file.
> > > >  - In Thread B, we may allocate blocks in the middle of Thread A's
> > > >    allocation, which make blocks which allocated in Thread A being
> > > >    discontinuous.
> > > >
> > > > This patch adds writepages mutex lock to make block allocation in dio write
> > > > atomic to avoid above issues.
> > > >
> > > > Test environment:
> > > > ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> > > > 32g kingston sd card.
> > > >
> > > > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> > > --filesize=256m --size=16m --bs=2m --direct=1
> > > > --numjobs=10
> > > >
> > > > before:
> > > >   WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
> > > maxt=52083msec
> > > >
> > > > patched:
> > > >   WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
> > > maxt=16329msec
> > > >
> > > > Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> > > > ---
> > > >  fs/f2fs/data.c | 13 ++++++++++---
> > > >  1 file changed, 10 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > > > index a737ca5..a0a5849 100644
> > > > --- a/fs/f2fs/data.c
> > > > +++ b/fs/f2fs/data.c
> > > > @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> *iter,
> > > >  	struct file *file = iocb->ki_filp;
> > > >  	struct address_space *mapping = file->f_mapping;
> > > >  	struct inode *inode = mapping->host;
> > > > +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> > > >  	size_t count = iov_iter_count(iter);
> > > > +	int rw = iov_iter_rw(iter);
> > > >  	int err;
> > > >
> > > >  	/* we don't need to use inline_data strictly */
> > > > @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> > > *iter,
> > > >
> > > >  	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
> > > >
> > > > -	if (iov_iter_rw(iter) == WRITE)
> > > > +	if (rw == WRITE) {
> > > > +		mutex_lock(&sbi->writepages);
> > >
> > > Why do we have to share sbi->writepages?
> >
> > The root cause of this issue is that: in f2fs, we have no suitable
> > dispatcher which can do the following things as an atomic operation:
> > a) allocate position(s) in flash device for current block(s);
> > b) submit user data in allocated position(s) in block layer.
> >
> > Without the dispatcher, we will suffer performance issue in following
> > scenario:
> > Thread A		Thread B		Thread C
> > allocate pos+1
> > 			allocate pos+2
> > 						allocate pos+3
> > submit pos+1
> > 						submit pos+3
> > 			submit pos+2
> >
> > Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> > running into non-LFS mode, therefore resulting in bad performance.
> >
> > writepages mutex lock supply us with a good solution for above issue.
> > It not only make the allocating and submitting pair executing atomically,
> > but also reduce the fragmentation for one file since we submit blocks
> > belong to single inode as continuous as possible.
> >
> > So here I choose to use writepages mutex lock to fix the performance
> > issue caused by both dio write vs dio write and dio write vs buffered
> > write.
> 
> Understood, but the concern was the multi-thread performance as you mentioned.
> If one thread throws a big dio request, anybody cannot write at all?

Buffered write will not be stopped, but actually my way completely stops the
concurrency of multithreads which are doing dio writes, for aspect of improving
concurrency, moving mutex_unlock below __allocate_data_blocks is a good solution
so far.

> How about adding some limits likewise f2fs_write_data_pages whieh is for example
> nr_pages_to_write?

Could you share more details about your idea?

As Yunlei reported, there is performance regression issue, so how about
holding this patch and let me do some investigation?

Thanks,

> 
> Thanks,
> 
> >
> > If I'm missing something, please correct me.
> >
> > >
> > > >  		__allocate_data_blocks(inode, offset, count);
> > >
> > > If the problem lies on the misaligned blocks, how about calling mutex_unlock
> > > here?
> >
> > When changing to unlock here, I got regression when testing with following command:
> > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> --filesize=256m --size=4m --bs=64k --direct=1
> > --numjobs=20
> >
> > unlock here:
> >   WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec,
> maxt=14119msec
> > unlock after dio finished:
> >   WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec,
> maxt=13454msec
> >
> > So how about keep it in original place in this patch?
> >
> > Thanks,
> > >
> > > Thanks,
> > >
> > > > +	}
> > > >
> > > >  	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> > > > -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> > > > -		f2fs_write_failed(mapping, offset + count);
> > > > +	if (rw == WRITE) {
> > > > +		mutex_unlock(&sbi->writepages);
> > > > +		if (err)
> > > > +			f2fs_write_failed(mapping, offset + count);
> > > > +	}
> > > >
> > > >  	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
> > > >
> > > > --
> > > > 2.4.2


------------------------------------------------------------------------------
Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
Get real-time metrics from all of your servers, apps and tools
in one place.
SourceForge users - Click here to start your Free Trial of Datadog now!
http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [f2fs-dev] [PATCH 5/7] f2fs: enhance multithread dio write performance
  2015-09-17  0:39       ` He YunLei
  (?)
@ 2015-09-17 12:53       ` Chao Yu
  -1 siblings, 0 replies; 15+ messages in thread
From: Chao Yu @ 2015-09-17 12:53 UTC (permalink / raw)
  To: 'He YunLei'; +Cc: 'Jaegeuk Kim', linux-kernel, linux-f2fs-devel

Hi Yunlei,

> -----Original Message-----
> From: He YunLei [mailto:heyunlei@huawei.com]
> Sent: Thursday, September 17, 2015 8:40 AM
> To: Chao Yu
> Cc: 'Jaegeuk Kim'; linux-kernel@vger.kernel.org; linux-f2fs-devel@lists.sourceforge.net
> Subject: Re: [f2fs-dev] [PATCH 5/7] f2fs: enhance multithread dio write performance
> 
> On 2015/9/16 18:15, Chao Yu wrote:
> > Hi Jaegeuk,
> >
> >> -----Original Message-----
> >> From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> >> Sent: Wednesday, September 16, 2015 5:21 AM
> >> To: Chao Yu
> >> Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> >> Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> >>
> >> Hi Chao,
> >>
> >> On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> >>> When dio writes perform concurrently, our performace will be low because of
> >>> Thread A's allocation of multi continuous blocks will be break by Thread B,
> >>> there are two cases as below:
> >>>   - In Thread B, we may change current segment to a new segment for LFS
> >>>     allocation if we dio write in the beginning of the file.
> >>>   - In Thread B, we may allocate blocks in the middle of Thread A's
> >>>     allocation, which make blocks which allocated in Thread A being
> >>>     discontinuous.
> >>>
> >>> This patch adds writepages mutex lock to make block allocation in dio write
> >>> atomic to avoid above issues.
> >>>
> >>> Test environment:
> >>> ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> >>> 32g kingston sd card.
> >>>
> >>> fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> >> --filesize=256m --size=16m --bs=2m --direct=1
> >>> --numjobs=10
> >>>
> >>> before:
> >>>    WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
> >> maxt=52083msec
> >>>
> >>> patched:
> >>>    WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
> >> maxt=16329msec
> >>>
> >>> Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> >>> ---
> >>>   fs/f2fs/data.c | 13 ++++++++++---
> >>>   1 file changed, 10 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> >>> index a737ca5..a0a5849 100644
> >>> --- a/fs/f2fs/data.c
> >>> +++ b/fs/f2fs/data.c
> >>> @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> *iter,
> >>>   	struct file *file = iocb->ki_filp;
> >>>   	struct address_space *mapping = file->f_mapping;
> >>>   	struct inode *inode = mapping->host;
> >>> +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> >>>   	size_t count = iov_iter_count(iter);
> >>> +	int rw = iov_iter_rw(iter);
> >>>   	int err;
> >>>
> >>>   	/* we don't need to use inline_data strictly */
> >>> @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> >> *iter,
> >>>
> >>>   	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
> >>>
> >>> -	if (iov_iter_rw(iter) == WRITE)
> >>> +	if (rw == WRITE) {
> >>> +		mutex_lock(&sbi->writepages);
> >>
> >> Why do we have to share sbi->writepages?
> >
> > The root cause of this issue is that: in f2fs, we have no suitable
> > dispatcher which can do the following things as an atomic operation:
> > a) allocate position(s) in flash device for current block(s);
> > b) submit user data in allocated position(s) in block layer.
> >
> > Without the dispatcher, we will suffer performance issue in following
> > scenario:
> > Thread A		Thread B		Thread C
> > allocate pos+1
> > 			allocate pos+2
> > 						allocate pos+3
> > submit pos+1
> > 						submit pos+3
> > 			submit pos+2
> >
> > Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> > running into non-LFS mode, therefore resulting in bad performance.
> >
> > writepages mutex lock supply us with a good solution for above issue.
> > It not only make the allocating and submitting pair executing atomically,
> > but also reduce the fragmentation for one file since we submit blocks
> > belong to single inode as continuous as possible.
> >
> > So here I choose to use writepages mutex lock to fix the performance
> > issue caused by both dio write vs dio write and dio write vs buffered
> > write.
> >
> > If I'm missing something, please correct me.
> >
> >>
> >>>   		__allocate_data_blocks(inode, offset, count);
> >>
> >> If the problem lies on the misaligned blocks, how about calling mutex_unlock
> >> here?
> >
> > When changing to unlock here, I got regression when testing with following command:
> > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> --filesize=256m --size=4m --bs=64k --direct=1
> > --numjobs=20
> >
> > unlock here:
> >    WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec,
> maxt=14119msec
> > unlock after dio finished:
> >    WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec,
> maxt=13454msec
> >
> > So how about keep it in original place in this patch?
> 
> Does share writepages mutex lock have an effect on cache write? Here is AndroBench result on
> my phone:
> 
> Before patch:
> 				1R1W               8R8W               16R16W
> Sequential Write               161.31             163.85              154.67
> Random  Write                   9.48               17.66               18.09
> 
> 
> After patch:
> 				1R1W               8R8W               16R16W
> Sequential Write               159.61             157.24              160.11
> Random  Write                   9.17               8.51                8.8

Thanks for your report, I will do the investigation.

Thanks,

> 
> Unit:Mb/s, File size: 64M, Buffer size: 4k
> 
> >
> > Thanks,
> >>
> >> Thanks,
> >>
> >>> +	}
> >>>
> >>>   	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> >>> -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> >>> -		f2fs_write_failed(mapping, offset + count);
> >>> +	if (rw == WRITE) {
> >>> +		mutex_unlock(&sbi->writepages);
> >>> +		if (err)
> >>> +			f2fs_write_failed(mapping, offset + count);
> >>> +	}
> >>>
> >>>   	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
> >>>
> >>> --
> >>> 2.4.2
> >
> >
> > ------------------------------------------------------------------------------
> > Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
> > Get real-time metrics from all of your servers, apps and tools
> > in one place.
> > SourceForge users - Click here to start your Free Trial of Datadog now!
> > http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140
> > _______________________________________________
> > Linux-f2fs-devel mailing list
> > Linux-f2fs-devel@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
> >
> > .
> >


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
  2015-09-17 12:52         ` Chao Yu
  (?)
@ 2015-09-17 17:48         ` Jaegeuk Kim
  2015-09-18  8:49             ` Chao Yu
  -1 siblings, 1 reply; 15+ messages in thread
From: Jaegeuk Kim @ 2015-09-17 17:48 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-f2fs-devel, linux-kernel

Hi Chao,

On Thu, Sep 17, 2015 at 08:52:10PM +0800, Chao Yu wrote:
> Hi Jaegeuk,
> 
> > -----Original Message-----
> > From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> > Sent: Thursday, September 17, 2015 2:13 AM
> > To: Chao Yu
> > Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> > Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> > 
> > Hi Chao,
> > 
> > On Wed, Sep 16, 2015 at 06:15:55PM +0800, Chao Yu wrote:
> > > Hi Jaegeuk,
> > >
> > > > -----Original Message-----
> > > > From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> > > > Sent: Wednesday, September 16, 2015 5:21 AM
> > > > To: Chao Yu
> > > > Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> > > > Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> > > >
> > > > Hi Chao,
> > > >
> > > > On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> > > > > When dio writes perform concurrently, our performace will be low because of
> > > > > Thread A's allocation of multi continuous blocks will be break by Thread B,
> > > > > there are two cases as below:
> > > > >  - In Thread B, we may change current segment to a new segment for LFS
> > > > >    allocation if we dio write in the beginning of the file.
> > > > >  - In Thread B, we may allocate blocks in the middle of Thread A's
> > > > >    allocation, which make blocks which allocated in Thread A being
> > > > >    discontinuous.
> > > > >
> > > > > This patch adds writepages mutex lock to make block allocation in dio write
> > > > > atomic to avoid above issues.
> > > > >
> > > > > Test environment:
> > > > > ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> > > > > 32g kingston sd card.
> > > > >
> > > > > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> > > > --filesize=256m --size=16m --bs=2m --direct=1
> > > > > --numjobs=10
> > > > >
> > > > > before:
> > > > >   WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
> > > > maxt=52083msec
> > > > >
> > > > > patched:
> > > > >   WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
> > > > maxt=16329msec
> > > > >
> > > > > Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> > > > > ---
> > > > >  fs/f2fs/data.c | 13 ++++++++++---
> > > > >  1 file changed, 10 insertions(+), 3 deletions(-)
> > > > >
> > > > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > > > > index a737ca5..a0a5849 100644
> > > > > --- a/fs/f2fs/data.c
> > > > > +++ b/fs/f2fs/data.c
> > > > > @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> > *iter,
> > > > >  	struct file *file = iocb->ki_filp;
> > > > >  	struct address_space *mapping = file->f_mapping;
> > > > >  	struct inode *inode = mapping->host;
> > > > > +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> > > > >  	size_t count = iov_iter_count(iter);
> > > > > +	int rw = iov_iter_rw(iter);
> > > > >  	int err;
> > > > >
> > > > >  	/* we don't need to use inline_data strictly */
> > > > > @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> > > > *iter,
> > > > >
> > > > >  	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
> > > > >
> > > > > -	if (iov_iter_rw(iter) == WRITE)
> > > > > +	if (rw == WRITE) {
> > > > > +		mutex_lock(&sbi->writepages);
> > > >
> > > > Why do we have to share sbi->writepages?
> > >
> > > The root cause of this issue is that: in f2fs, we have no suitable
> > > dispatcher which can do the following things as an atomic operation:
> > > a) allocate position(s) in flash device for current block(s);
> > > b) submit user data in allocated position(s) in block layer.
> > >
> > > Without the dispatcher, we will suffer performance issue in following
> > > scenario:
> > > Thread A		Thread B		Thread C
> > > allocate pos+1
> > > 			allocate pos+2
> > > 						allocate pos+3
> > > submit pos+1
> > > 						submit pos+3
> > > 			submit pos+2
> > >
> > > Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> > > running into non-LFS mode, therefore resulting in bad performance.
> > >
> > > writepages mutex lock supply us with a good solution for above issue.
> > > It not only make the allocating and submitting pair executing atomically,
> > > but also reduce the fragmentation for one file since we submit blocks
> > > belong to single inode as continuous as possible.
> > >
> > > So here I choose to use writepages mutex lock to fix the performance
> > > issue caused by both dio write vs dio write and dio write vs buffered
> > > write.
> > 
> > Understood, but the concern was the multi-thread performance as you mentioned.
> > If one thread throws a big dio request, anybody cannot write at all?
> 
> Buffered write will not be stopped, but actually my way completely stops the
> concurrency of multithreads which are doing dio writes, for aspect of improving
> concurrency, moving mutex_unlock below __allocate_data_blocks is a good solution
> so far.
> 
> > How about adding some limits likewise f2fs_write_data_pages whieh is for example
> > nr_pages_to_write?
> 
> Could you share more details about your idea?
> 
> As Yunlei reported, there is performance regression issue, so how about
> holding this patch and let me do some investigation?

It seems there is a mutex overhead when handling a bunch of 4KB small dios.
Hmm, I meant, how about serializing pretty long-sized dios only?

> 
> Thanks,
> 
> > 
> > Thanks,
> > 
> > >
> > > If I'm missing something, please correct me.
> > >
> > > >
> > > > >  		__allocate_data_blocks(inode, offset, count);
> > > >
> > > > If the problem lies on the misaligned blocks, how about calling mutex_unlock
> > > > here?
> > >
> > > When changing to unlock here, I got regression when testing with following command:
> > > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> > --filesize=256m --size=4m --bs=64k --direct=1
> > > --numjobs=20
> > >
> > > unlock here:
> > >   WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec,
> > maxt=14119msec
> > > unlock after dio finished:
> > >   WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec,
> > maxt=13454msec
> > >
> > > So how about keep it in original place in this patch?
> > >
> > > Thanks,
> > > >
> > > > Thanks,
> > > >
> > > > > +	}
> > > > >
> > > > >  	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> > > > > -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> > > > > -		f2fs_write_failed(mapping, offset + count);
> > > > > +	if (rw == WRITE) {
> > > > > +		mutex_unlock(&sbi->writepages);
> > > > > +		if (err)
> > > > > +			f2fs_write_failed(mapping, offset + count);
> > > > > +	}
> > > > >
> > > > >  	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
> > > > >
> > > > > --
> > > > > 2.4.2

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 5/7] f2fs: enhance multithread dio write performance
  2015-09-17 17:48         ` Jaegeuk Kim
@ 2015-09-18  8:49             ` Chao Yu
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Yu @ 2015-09-18  8:49 UTC (permalink / raw)
  To: 'Jaegeuk Kim'; +Cc: linux-f2fs-devel, linux-kernel

Hi Jaegeuk,

> -----Original Message-----
> From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> Sent: Friday, September 18, 2015 1:49 AM
> To: Chao Yu
> Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> 
> Hi Chao,
> 
> On Thu, Sep 17, 2015 at 08:52:10PM +0800, Chao Yu wrote:
> > Hi Jaegeuk,
> >
> > > -----Original Message-----
> > > From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> > > Sent: Thursday, September 17, 2015 2:13 AM
> > > To: Chao Yu
> > > Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> > > Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> > >
> > > Hi Chao,
> > >
> > > On Wed, Sep 16, 2015 at 06:15:55PM +0800, Chao Yu wrote:
> > > > Hi Jaegeuk,
> > > >
> > > > > -----Original Message-----
> > > > > From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> > > > > Sent: Wednesday, September 16, 2015 5:21 AM
> > > > > To: Chao Yu
> > > > > Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> > > > > Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> > > > >
> > > > > Hi Chao,
> > > > >
> > > > > On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> > > > > > When dio writes perform concurrently, our performace will be low because of
> > > > > > Thread A's allocation of multi continuous blocks will be break by Thread B,
> > > > > > there are two cases as below:
> > > > > >  - In Thread B, we may change current segment to a new segment for LFS
> > > > > >    allocation if we dio write in the beginning of the file.
> > > > > >  - In Thread B, we may allocate blocks in the middle of Thread A's
> > > > > >    allocation, which make blocks which allocated in Thread A being
> > > > > >    discontinuous.
> > > > > >
> > > > > > This patch adds writepages mutex lock to make block allocation in dio write
> > > > > > atomic to avoid above issues.
> > > > > >
> > > > > > Test environment:
> > > > > > ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> > > > > > 32g kingston sd card.
> > > > > >
> > > > > > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> > > > > --filesize=256m --size=16m --bs=2m --direct=1
> > > > > > --numjobs=10
> > > > > >
> > > > > > before:
> > > > > >   WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
> > > > > maxt=52083msec
> > > > > >
> > > > > > patched:
> > > > > >   WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
> > > > > maxt=16329msec
> > > > > >
> > > > > > Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> > > > > > ---
> > > > > >  fs/f2fs/data.c | 13 ++++++++++---
> > > > > >  1 file changed, 10 insertions(+), 3 deletions(-)
> > > > > >
> > > > > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > > > > > index a737ca5..a0a5849 100644
> > > > > > --- a/fs/f2fs/data.c
> > > > > > +++ b/fs/f2fs/data.c
> > > > > > @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> > > *iter,
> > > > > >  	struct file *file = iocb->ki_filp;
> > > > > >  	struct address_space *mapping = file->f_mapping;
> > > > > >  	struct inode *inode = mapping->host;
> > > > > > +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> > > > > >  	size_t count = iov_iter_count(iter);
> > > > > > +	int rw = iov_iter_rw(iter);
> > > > > >  	int err;
> > > > > >
> > > > > >  	/* we don't need to use inline_data strictly */
> > > > > > @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> > > > > *iter,
> > > > > >
> > > > > >  	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
> > > > > >
> > > > > > -	if (iov_iter_rw(iter) == WRITE)
> > > > > > +	if (rw == WRITE) {
> > > > > > +		mutex_lock(&sbi->writepages);
> > > > >
> > > > > Why do we have to share sbi->writepages?
> > > >
> > > > The root cause of this issue is that: in f2fs, we have no suitable
> > > > dispatcher which can do the following things as an atomic operation:
> > > > a) allocate position(s) in flash device for current block(s);
> > > > b) submit user data in allocated position(s) in block layer.
> > > >
> > > > Without the dispatcher, we will suffer performance issue in following
> > > > scenario:
> > > > Thread A		Thread B		Thread C
> > > > allocate pos+1
> > > > 			allocate pos+2
> > > > 						allocate pos+3
> > > > submit pos+1
> > > > 						submit pos+3
> > > > 			submit pos+2
> > > >
> > > > Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> > > > running into non-LFS mode, therefore resulting in bad performance.
> > > >
> > > > writepages mutex lock supply us with a good solution for above issue.
> > > > It not only make the allocating and submitting pair executing atomically,
> > > > but also reduce the fragmentation for one file since we submit blocks
> > > > belong to single inode as continuous as possible.
> > > >
> > > > So here I choose to use writepages mutex lock to fix the performance
> > > > issue caused by both dio write vs dio write and dio write vs buffered
> > > > write.
> > >
> > > Understood, but the concern was the multi-thread performance as you mentioned.
> > > If one thread throws a big dio request, anybody cannot write at all?
> >
> > Buffered write will not be stopped, but actually my way completely stops the
> > concurrency of multithreads which are doing dio writes, for aspect of improving
> > concurrency, moving mutex_unlock below __allocate_data_blocks is a good solution
> > so far.
> >
> > > How about adding some limits likewise f2fs_write_data_pages whieh is for example
> > > nr_pages_to_write?
> >
> > Could you share more details about your idea?
> >
> > As Yunlei reported, there is performance regression issue, so how about
> > holding this patch and let me do some investigation?
> 
> It seems there is a mutex overhead when handling a bunch of 4KB small dios.
> Hmm, I meant, how about serializing pretty long-sized dios only?

Oh, I got it, thanks for the idea. :)

I will take time to have a test.

Thanks,

> 
> >
> > Thanks,
> >
> > >
> > > Thanks,
> > >
> > > >
> > > > If I'm missing something, please correct me.
> > > >
> > > > >
> > > > > >  		__allocate_data_blocks(inode, offset, count);
> > > > >
> > > > > If the problem lies on the misaligned blocks, how about calling mutex_unlock
> > > > > here?
> > > >
> > > > When changing to unlock here, I got regression when testing with following command:
> > > > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> > > --filesize=256m --size=4m --bs=64k --direct=1
> > > > --numjobs=20
> > > >
> > > > unlock here:
> > > >   WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec,
> > > maxt=14119msec
> > > > unlock after dio finished:
> > > >   WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec,
> > > maxt=13454msec
> > > >
> > > > So how about keep it in original place in this patch?
> > > >
> > > > Thanks,
> > > > >
> > > > > Thanks,
> > > > >
> > > > > > +	}
> > > > > >
> > > > > >  	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> > > > > > -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> > > > > > -		f2fs_write_failed(mapping, offset + count);
> > > > > > +	if (rw == WRITE) {
> > > > > > +		mutex_unlock(&sbi->writepages);
> > > > > > +		if (err)
> > > > > > +			f2fs_write_failed(mapping, offset + count);
> > > > > > +	}
> > > > > >
> > > > > >  	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
> > > > > >
> > > > > > --
> > > > > > 2.4.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
@ 2015-09-18  8:49             ` Chao Yu
  0 siblings, 0 replies; 15+ messages in thread
From: Chao Yu @ 2015-09-18  8:49 UTC (permalink / raw)
  To: 'Jaegeuk Kim'; +Cc: linux-kernel, linux-f2fs-devel

Hi Jaegeuk,

> -----Original Message-----
> From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> Sent: Friday, September 18, 2015 1:49 AM
> To: Chao Yu
> Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> 
> Hi Chao,
> 
> On Thu, Sep 17, 2015 at 08:52:10PM +0800, Chao Yu wrote:
> > Hi Jaegeuk,
> >
> > > -----Original Message-----
> > > From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> > > Sent: Thursday, September 17, 2015 2:13 AM
> > > To: Chao Yu
> > > Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> > > Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> > >
> > > Hi Chao,
> > >
> > > On Wed, Sep 16, 2015 at 06:15:55PM +0800, Chao Yu wrote:
> > > > Hi Jaegeuk,
> > > >
> > > > > -----Original Message-----
> > > > > From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> > > > > Sent: Wednesday, September 16, 2015 5:21 AM
> > > > > To: Chao Yu
> > > > > Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> > > > > Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> > > > >
> > > > > Hi Chao,
> > > > >
> > > > > On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> > > > > > When dio writes perform concurrently, our performace will be low because of
> > > > > > Thread A's allocation of multi continuous blocks will be break by Thread B,
> > > > > > there are two cases as below:
> > > > > >  - In Thread B, we may change current segment to a new segment for LFS
> > > > > >    allocation if we dio write in the beginning of the file.
> > > > > >  - In Thread B, we may allocate blocks in the middle of Thread A's
> > > > > >    allocation, which make blocks which allocated in Thread A being
> > > > > >    discontinuous.
> > > > > >
> > > > > > This patch adds writepages mutex lock to make block allocation in dio write
> > > > > > atomic to avoid above issues.
> > > > > >
> > > > > > Test environment:
> > > > > > ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> > > > > > 32g kingston sd card.
> > > > > >
> > > > > > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> > > > > --filesize=256m --size=16m --bs=2m --direct=1
> > > > > > --numjobs=10
> > > > > >
> > > > > > before:
> > > > > >   WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
> > > > > maxt=52083msec
> > > > > >
> > > > > > patched:
> > > > > >   WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
> > > > > maxt=16329msec
> > > > > >
> > > > > > Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> > > > > > ---
> > > > > >  fs/f2fs/data.c | 13 ++++++++++---
> > > > > >  1 file changed, 10 insertions(+), 3 deletions(-)
> > > > > >
> > > > > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > > > > > index a737ca5..a0a5849 100644
> > > > > > --- a/fs/f2fs/data.c
> > > > > > +++ b/fs/f2fs/data.c
> > > > > > @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> > > *iter,
> > > > > >  	struct file *file = iocb->ki_filp;
> > > > > >  	struct address_space *mapping = file->f_mapping;
> > > > > >  	struct inode *inode = mapping->host;
> > > > > > +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> > > > > >  	size_t count = iov_iter_count(iter);
> > > > > > +	int rw = iov_iter_rw(iter);
> > > > > >  	int err;
> > > > > >
> > > > > >  	/* we don't need to use inline_data strictly */
> > > > > > @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> > > > > *iter,
> > > > > >
> > > > > >  	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
> > > > > >
> > > > > > -	if (iov_iter_rw(iter) == WRITE)
> > > > > > +	if (rw == WRITE) {
> > > > > > +		mutex_lock(&sbi->writepages);
> > > > >
> > > > > Why do we have to share sbi->writepages?
> > > >
> > > > The root cause of this issue is that: in f2fs, we have no suitable
> > > > dispatcher which can do the following things as an atomic operation:
> > > > a) allocate position(s) in flash device for current block(s);
> > > > b) submit user data in allocated position(s) in block layer.
> > > >
> > > > Without the dispatcher, we will suffer performance issue in following
> > > > scenario:
> > > > Thread A		Thread B		Thread C
> > > > allocate pos+1
> > > > 			allocate pos+2
> > > > 						allocate pos+3
> > > > submit pos+1
> > > > 						submit pos+3
> > > > 			submit pos+2
> > > >
> > > > Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> > > > running into non-LFS mode, therefore resulting in bad performance.
> > > >
> > > > writepages mutex lock supply us with a good solution for above issue.
> > > > It not only make the allocating and submitting pair executing atomically,
> > > > but also reduce the fragmentation for one file since we submit blocks
> > > > belong to single inode as continuous as possible.
> > > >
> > > > So here I choose to use writepages mutex lock to fix the performance
> > > > issue caused by both dio write vs dio write and dio write vs buffered
> > > > write.
> > >
> > > Understood, but the concern was the multi-thread performance as you mentioned.
> > > If one thread throws a big dio request, anybody cannot write at all?
> >
> > Buffered write will not be stopped, but actually my way completely stops the
> > concurrency of multithreads which are doing dio writes, for aspect of improving
> > concurrency, moving mutex_unlock below __allocate_data_blocks is a good solution
> > so far.
> >
> > > How about adding some limits likewise f2fs_write_data_pages whieh is for example
> > > nr_pages_to_write?
> >
> > Could you share more details about your idea?
> >
> > As Yunlei reported, there is performance regression issue, so how about
> > holding this patch and let me do some investigation?
> 
> It seems there is a mutex overhead when handling a bunch of 4KB small dios.
> Hmm, I meant, how about serializing pretty long-sized dios only?

Oh, I got it, thanks for the idea. :)

I will take time to have a test.

Thanks,

> 
> >
> > Thanks,
> >
> > >
> > > Thanks,
> > >
> > > >
> > > > If I'm missing something, please correct me.
> > > >
> > > > >
> > > > > >  		__allocate_data_blocks(inode, offset, count);
> > > > >
> > > > > If the problem lies on the misaligned blocks, how about calling mutex_unlock
> > > > > here?
> > > >
> > > > When changing to unlock here, I got regression when testing with following command:
> > > > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> > > --filesize=256m --size=4m --bs=64k --direct=1
> > > > --numjobs=20
> > > >
> > > > unlock here:
> > > >   WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec,
> > > maxt=14119msec
> > > > unlock after dio finished:
> > > >   WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec,
> > > maxt=13454msec
> > > >
> > > > So how about keep it in original place in this patch?
> > > >
> > > > Thanks,
> > > > >
> > > > > Thanks,
> > > > >
> > > > > > +	}
> > > > > >
> > > > > >  	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> > > > > > -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> > > > > > -		f2fs_write_failed(mapping, offset + count);
> > > > > > +	if (rw == WRITE) {
> > > > > > +		mutex_unlock(&sbi->writepages);
> > > > > > +		if (err)
> > > > > > +			f2fs_write_failed(mapping, offset + count);
> > > > > > +	}
> > > > > >
> > > > > >  	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
> > > > > >
> > > > > > --
> > > > > > 2.4.2


------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [f2fs-dev] [PATCH 5/7] f2fs: enhance multithread dio write performance
  2015-09-17  0:39       ` He YunLei
  (?)
  (?)
@ 2015-12-11 10:26       ` Chao Yu
  -1 siblings, 0 replies; 15+ messages in thread
From: Chao Yu @ 2015-12-11 10:26 UTC (permalink / raw)
  To: 'He YunLei'; +Cc: 'Jaegeuk Kim', linux-kernel, linux-f2fs-devel

Hi Yunlei,

> -----Original Message-----
> From: He YunLei [mailto:heyunlei@huawei.com]
> Sent: Thursday, September 17, 2015 8:40 AM
> To: Chao Yu
> Cc: 'Jaegeuk Kim'; linux-kernel@vger.kernel.org; linux-f2fs-devel@lists.sourceforge.net
> Subject: Re: [f2fs-dev] [PATCH 5/7] f2fs: enhance multithread dio write performance
> 
> On 2015/9/16 18:15, Chao Yu wrote:
> > Hi Jaegeuk,
> >
> >> -----Original Message-----
> >> From: Jaegeuk Kim [mailto:jaegeuk@kernel.org]
> >> Sent: Wednesday, September 16, 2015 5:21 AM
> >> To: Chao Yu
> >> Cc: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vger.kernel.org
> >> Subject: Re: [PATCH 5/7] f2fs: enhance multithread dio write performance
> >>
> >> Hi Chao,
> >>
> >> On Fri, Sep 11, 2015 at 02:41:53PM +0800, Chao Yu wrote:
> >>> When dio writes perform concurrently, our performace will be low because of
> >>> Thread A's allocation of multi continuous blocks will be break by Thread B,
> >>> there are two cases as below:
> >>>   - In Thread B, we may change current segment to a new segment for LFS
> >>>     allocation if we dio write in the beginning of the file.
> >>>   - In Thread B, we may allocate blocks in the middle of Thread A's
> >>>     allocation, which make blocks which allocated in Thread A being
> >>>     discontinuous.
> >>>
> >>> This patch adds writepages mutex lock to make block allocation in dio write
> >>> atomic to avoid above issues.
> >>>
> >>> Test environment:
> >>> ubuntu os with linux kernel 4.2+, intel i7-3770, 16g memory,
> >>> 32g kingston sd card.
> >>>
> >>> fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> >> --filesize=256m --size=16m --bs=2m --direct=1
> >>> --numjobs=10
> >>>
> >>> before:
> >>>    WRITE: io=163840KB, aggrb=3145KB/s, minb=314KB/s, maxb=411KB/s, mint=39836msec,
> >> maxt=52083msec
> >>>
> >>> patched:
> >>>    WRITE: io=163840KB, aggrb=10033KB/s, minb=1003KB/s, maxb=1124KB/s, mint=14565msec,
> >> maxt=16329msec
> >>>
> >>> Signed-off-by: Chao Yu <chao2.yu@samsung.com>
> >>> ---
> >>>   fs/f2fs/data.c | 13 ++++++++++---
> >>>   1 file changed, 10 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> >>> index a737ca5..a0a5849 100644
> >>> --- a/fs/f2fs/data.c
> >>> +++ b/fs/f2fs/data.c
> >>> @@ -1536,7 +1536,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> *iter,
> >>>   	struct file *file = iocb->ki_filp;
> >>>   	struct address_space *mapping = file->f_mapping;
> >>>   	struct inode *inode = mapping->host;
> >>> +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> >>>   	size_t count = iov_iter_count(iter);
> >>> +	int rw = iov_iter_rw(iter);
> >>>   	int err;
> >>>
> >>>   	/* we don't need to use inline_data strictly */
> >>> @@ -1555,12 +1557,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter
> >> *iter,
> >>>
> >>>   	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
> >>>
> >>> -	if (iov_iter_rw(iter) == WRITE)
> >>> +	if (rw == WRITE) {
> >>> +		mutex_lock(&sbi->writepages);
> >>
> >> Why do we have to share sbi->writepages?
> >
> > The root cause of this issue is that: in f2fs, we have no suitable
> > dispatcher which can do the following things as an atomic operation:
> > a) allocate position(s) in flash device for current block(s);
> > b) submit user data in allocated position(s) in block layer.
> >
> > Without the dispatcher, we will suffer performance issue in following
> > scenario:
> > Thread A		Thread B		Thread C
> > allocate pos+1
> > 			allocate pos+2
> > 						allocate pos+3
> > submit pos+1
> > 						submit pos+3
> > 			submit pos+2
> >
> > Our final submitting series will: pos+1, pos+3, pos+2, this makes f2fs
> > running into non-LFS mode, therefore resulting in bad performance.
> >
> > writepages mutex lock supply us with a good solution for above issue.
> > It not only make the allocating and submitting pair executing atomically,
> > but also reduce the fragmentation for one file since we submit blocks
> > belong to single inode as continuous as possible.
> >
> > So here I choose to use writepages mutex lock to fix the performance
> > issue caused by both dio write vs dio write and dio write vs buffered
> > write.
> >
> > If I'm missing something, please correct me.
> >
> >>
> >>>   		__allocate_data_blocks(inode, offset, count);
> >>
> >> If the problem lies on the misaligned blocks, how about calling mutex_unlock
> >> here?
> >
> > When changing to unlock here, I got regression when testing with following command:
> > fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs
> --filesize=256m --size=4m --bs=64k --direct=1
> > --numjobs=20
> >
> > unlock here:
> >    WRITE: io=81920KB, aggrb=5802KB/s, minb=290KB/s, maxb=292KB/s, mint=14010msec,
> maxt=14119msec
> > unlock after dio finished:
> >    WRITE: io=81920KB, aggrb=6088KB/s, minb=304KB/s, maxb=1081KB/s, mint=3786msec,
> maxt=13454msec
> >
> > So how about keep it in original place in this patch?
> 
> Does share writepages mutex lock have an effect on cache write? Here is AndroBench result on
> my phone:
> 
> Before patch:
> 				1R1W               8R8W               16R16W
> Sequential Write               161.31             163.85              154.67
> Random  Write                   9.48               17.66               18.09
> 
> 
> After patch:
> 				1R1W               8R8W               16R16W
> Sequential Write               159.61             157.24              160.11
> Random  Write                   9.17               8.51                8.8
> 
> Unit:Mb/s, File size: 64M, Buffer size: 4k

Could you help to test the following patch?

>From 0abff8a16bf87076ec70a7c1b8da913000e9c3b7 Mon Sep 17 00:00:00 2001
From: Chao Yu <chao2.yu@samsung.com>
Date: Wed, 21 Oct 2015 15:12:07 +0800
Subject: [PATCH v2] f2fs: enhance multithread dio write performance

When dio writes perform concurrently, our performace will be low because of
Thread A's allocation of multi continuous blocks will be break by Thread B,
there are two cases as below:
 - In Thread B, we may change current segment to a new segment for LFS
   allocation if we dio write in the beginning of the file.
 - In Thread B, we may allocate blocks in the middle of Thread A's
   allocation, which make blocks allocated in Thread A being inconsecutive.

This patch adds writepages mutex lock to make block allocation in dio write
atomic to avoid above issues.

Test environment:
ubuntu os with linux kernel 4.4-rc4, intel i7-3770, 16g memory,
32g kingston sd card.

fio --name seqw --ioengine=sync --invalidate=1 --rw=write --directory=/mnt/f2fs --filesize=256m --size=16m --bs=2m --direct=1
--numjobs=10

before:
  WRITE: io=163840KB, aggrb=5125KB/s, minb=512KB/s, maxb=776KB/s, mint=21105msec, maxt=31967msec
patched:
  WRITE: io=163840KB, aggrb=10424KB/s, minb=1042KB/s, maxb=1172KB/s, mint=13975msec, maxt=15717msec

Signed-off-by: Chao Yu <chao2.yu@samsung.com>
---
v2:
 - only serialize block allocation.
 - do not serialize small dio.
 fs/f2fs/data.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 90a2ffe..c01d113 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1566,7 +1566,10 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 	struct file *file = iocb->ki_filp;
 	struct address_space *mapping = file->f_mapping;
 	struct inode *inode = mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
 	size_t count = iov_iter_count(iter);
+	int rw = iov_iter_rw(iter);
+	bool serialized = (F2FS_BYTES_TO_BLK(count) >= 64);
 	int err;
 
 	/* we don't need to use inline_data strictly */
@@ -1583,10 +1586,14 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 	if (err)
 		return err;
 
-	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
+	trace_f2fs_direct_IO_enter(inode, offset, count, rw);
 
-	if (iov_iter_rw(iter) == WRITE) {
+	if (rw == WRITE) {
+		if (serialized)
+			mutex_lock(&sbi->writepages);
 		__allocate_data_blocks(inode, offset, count);
+		if (serialized)
+			mutex_unlock(&sbi->writepages);
 		if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
 			err = -EIO;
 			goto out;
@@ -1595,10 +1602,10 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 
 	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
 out:
-	if (err < 0 && iov_iter_rw(iter) == WRITE)
+	if (err < 0 && rw == WRITE)
 		f2fs_write_failed(mapping, offset + count);
 
-	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
+	trace_f2fs_direct_IO_exit(inode, offset, count, rw, err);
 
 	return err;
 }
-- 
2.6.3


> 
> >
> > Thanks,
> >>
> >> Thanks,
> >>
> >>> +	}
> >>>
> >>>   	err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
> >>> -	if (err < 0 && iov_iter_rw(iter) == WRITE)
> >>> -		f2fs_write_failed(mapping, offset + count);
> >>> +	if (rw == WRITE) {
> >>> +		mutex_unlock(&sbi->writepages);
> >>> +		if (err)
> >>> +			f2fs_write_failed(mapping, offset + count);
> >>> +	}
> >>>
> >>>   	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
> >>>
> >>> --
> >>> 2.4.2
> >
> >
> > ------------------------------------------------------------------------------
> > Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
> > Get real-time metrics from all of your servers, apps and tools
> > in one place.
> > SourceForge users - Click here to start your Free Trial of Datadog now!
> > http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140
> > _______________________________________________
> > Linux-f2fs-devel mailing list
> > Linux-f2fs-devel@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
> >
> > .
> >


^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2015-12-11 10:27 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-11  6:41 [PATCH 5/7] f2fs: enhance multithread dio write performance Chao Yu
2015-09-11  6:41 ` Chao Yu
2015-09-15 21:20 ` Jaegeuk Kim
2015-09-16 10:15   ` Chao Yu
2015-09-16 18:12     ` Jaegeuk Kim
2015-09-16 18:12       ` Jaegeuk Kim
2015-09-17 12:52       ` Chao Yu
2015-09-17 12:52         ` Chao Yu
2015-09-17 17:48         ` Jaegeuk Kim
2015-09-18  8:49           ` Chao Yu
2015-09-18  8:49             ` Chao Yu
2015-09-17  0:39     ` [f2fs-dev] " He YunLei
2015-09-17  0:39       ` He YunLei
2015-09-17 12:53       ` [f2fs-dev] " Chao Yu
2015-12-11 10:26       ` Chao Yu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.