Linux NILFS development
 help / color / mirror / Atom feed
* [PATCH] nilfs2: shorten freeze period due to GC in write operation
@ 2009-08-29  8:54 Jiro SEKIBA
       [not found] ` <1251536070-12052-1-git-send-email-jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
  0 siblings, 1 reply; 4+ messages in thread
From: Jiro SEKIBA @ 2009-08-29  8:54 UTC (permalink / raw)
  To: users-JrjvKiOkagjYtjvyW6yDsg; +Cc: Jiro SEKIBA

Hi,

This is a patch to shorten freeze period.

When GC is runnning, GC moves live block to difference segments.
Copying live blocks into memory is done in a transaction,
but it is not necessarily to be in the transaction.
This patch will get the nilfs_ioctl_move_blocks() out from
transaction lock and put it before the transaction.

I ran sysbench fileio test against nilfs partition.
I copied some DVD/CD images and created snapshot to create live blocks
before starting the benchmark.

Followings are summary of rc8 and rc8 w/ the patch of per-request statistics,
which is min/max and avg.  I ran each test three times and bellow is
average of those numers.

According to this benchmark result, average time is slightly degrated.
However, worstcase (max) result is significantly improved.
This can address a few seconds write freeze.

- random write per-request performance of rc8
 min   0.843ms
 max 680.406ms
 avg   3.050ms
- random write per-request performance of rc8 w/ this patch
 min   0.833ms ->  98.80%
 max 354.606ms ->  52.10%
 avg   3.226ms -> 105.70%

- sequential write per-request performance of rc8
 min   0.736ms
 max 774.343ms 
 avg   2.883ms 
- sequential write per-request performance of rc8 w/ this patch
 min   0.740ms -> 100.50%
 max  563.780ms->  72.80%
 avg   3.113ms -> 107.90%

-----8<-----8<-----nilfs_cleanerd.conf-----8<-----8<-----
protection_period       150
selection_policy        timestamp       # timestamp in ascend order
nsegments_per_clean     2
cleaning_interval       2
retry_interval          60
use_mmap
log_priority            info
-----8<-----8<-----nilfs_cleanerd.conf-----8<-----8<-----


Signed-off-by: Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
---
 fs/nilfs2/ioctl.c     |   18 ++++++++++++------
 fs/nilfs2/the_nilfs.h |    2 ++
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 6ea5f87..2394353 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -442,12 +442,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
 	const char *msg;
 	int ret;
 
-	ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]);
-	if (ret < 0) {
-		msg = "cannot read source blocks";
-		goto failed;
-	}
-
 	ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
 	if (ret < 0) {
 		/*
@@ -521,6 +515,10 @@ static int nilfs_ioctl_clean_segmentsistruct inode5 einode, struct file *filp,
 
 	nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
 
+	if (nilfs_gc_running(nilfs))
+		return -EBUSY;
+	set_nilfs_gc_running(nilfs);
+
 	for (n = 0; n < 4; n++) {
 		ret = -EINVAL;
 		if (argv[n].v_size != argsz[n])
@@ -548,12 +546,20 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
 		}
 	}
 
+	ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]);
+	if (ret < 0) {
+		printk(KERN_ERR "NILFS: GC failed during preparation: "
+			"cannot read source blocks: err=%d\n", ret);
+		goto out_free;
+	}
+
 	ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
 
  out_free:
 	while (--n >= 0)
 		vfree(kbufs[n]);
 	kfree(kbufs[4]);
+	clear_nilfs_gc_running(nilfs);
 	return ret;
 }
 
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index 1b9caaf..97ee569 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -37,6 +37,7 @@ enum {
 	THE_NILFS_LOADED,       /* Roll-back/roll-forward has done and
 				   the latest checkpoint was loaded */
 	THE_NILFS_DISCONTINUED,	/* 'next' pointer chain has broken */
+	THE_NILFS_GC_RUNNING,	/* gc process is running */
 };
 
 /**
@@ -197,6 +198,7 @@ static inline int nilfs_##name(struct the_nilfs *nilfs)			\
 THE_NILFS_FNS(INIT, init)
 THE_NILFS_FNS(LOADED, loaded)
 THE_NILFS_FNS(DISCONTINUED, discontinued)
+THE_NILFS_FNS(GC_RUNNING, gc_running)
 
 /* Minimum interval of periodical update of superblocks (in seconds) */
 #define NILFS_SB_FREQ		10
-- 
1.5.6.5

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

* Re: [PATCH] nilfs2: shorten freeze period due to GC in write operation
       [not found] ` <1251536070-12052-1-git-send-email-jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
@ 2009-08-31  7:37   ` Ryusuke Konishi
       [not found]     ` <20090831.163729.22914775.ryusuke-sG5X7nlA6pw@public.gmane.org>
  0 siblings, 1 reply; 4+ messages in thread
From: Ryusuke Konishi @ 2009-08-31  7:37 UTC (permalink / raw)
  To: users-JrjvKiOkagjYtjvyW6yDsg, jir-hfpbi5WX9J54Eiagz67IpQ

Hi Sekiba-san,

On Sat, 29 Aug 2009 17:54:30 +0900, Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org> wrote:
> Hi,
> 
> This is a patch to shorten freeze period.
<snip> 
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 6ea5f87..2394353 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -442,12 +442,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
>  	const char *msg;
>  	int ret;
>  
> -	ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]);
> -	if (ret < 0) {
> -		msg = "cannot read source blocks";
> -		goto failed;
> -	}
> -
>  	ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
>  	if (ret < 0) {
>  		/*
> @@ -521,6 +515,10 @@ static int nilfs_ioctl_clean_segmentsistruct inode5 einode, struct file *filp,
>  
>  	nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
>  
> +	if (nilfs_gc_running(nilfs))
> +		return -EBUSY;
> +	set_nilfs_gc_running(nilfs);
> +

Well, I have two comments here on this patch:

This check and the error return should be done before memory
allocation of kbufs[4] to avoid memory leak.

And, logically these bit operations must be atomic by use of
test_and_set_bit().  So, it should be like:

	if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags))
		return -EBUSY;

I think we don't have to expand THE_NILFS_FNS macro for this.

Could you revise the patch once more?

Thank you,
Ryusuke Konishi

>  	for (n = 0; n < 4; n++) {
>  		ret = -EINVAL;
>  		if (argv[n].v_size != argsz[n])
> @@ -548,12 +546,20 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
>  		}
>  	}
>  
> +	ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]);
> +	if (ret < 0) {
> +		printk(KERN_ERR "NILFS: GC failed during preparation: "
> +			"cannot read source blocks: err=%d\n", ret);
> +		goto out_free;
> +	}
> +
>  	ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
>  
>   out_free:
>  	while (--n >= 0)
>  		vfree(kbufs[n]);
>  	kfree(kbufs[4]);
> +	clear_nilfs_gc_running(nilfs);
>  	return ret;
>  }
>  
> diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
> index 1b9caaf..97ee569 100644
> --- a/fs/nilfs2/the_nilfs.h
> +++ b/fs/nilfs2/the_nilfs.h
> @@ -37,6 +37,7 @@ enum {
>  	THE_NILFS_LOADED,       /* Roll-back/roll-forward has done and
>  				   the latest checkpoint was loaded */
>  	THE_NILFS_DISCONTINUED,	/* 'next' pointer chain has broken */
> +	THE_NILFS_GC_RUNNING,	/* gc process is running */
>  };
>  
>  /**
> @@ -197,6 +198,7 @@ static inline int nilfs_##name(struct the_nilfs *nilfs)			\
>  THE_NILFS_FNS(INIT, init)
>  THE_NILFS_FNS(LOADED, loaded)
>  THE_NILFS_FNS(DISCONTINUED, discontinued)
> +THE_NILFS_FNS(GC_RUNNING, gc_running)
>  
>  /* Minimum interval of periodical update of superblocks (in seconds) */
>  #define NILFS_SB_FREQ		10
> -- 
> 1.5.6.5
> 
> _______________________________________________
> users mailing list
> users-JrjvKiOkagjYtjvyW6yDsg@public.gmane.org
> https://www.nilfs.org/mailman/listinfo/users

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

* Re: [PATCH] nilfs2: shorten freeze period due to GC in write operation
       [not found]     ` <20090831.163729.22914775.ryusuke-sG5X7nlA6pw@public.gmane.org>
@ 2009-08-31  8:05       ` Jiro SEKIBA
  2009-08-31  8:14       ` Ryusuke Konishi
  1 sibling, 0 replies; 4+ messages in thread
From: Jiro SEKIBA @ 2009-08-31  8:05 UTC (permalink / raw)
  To: NILFS Users mailing list

Hi,

At Mon, 31 Aug 2009 16:37:29 +0900 (JST),
Ryusuke Konishi wrote:
> 
> Hi Sekiba-san,
> 
> On Sat, 29 Aug 2009 17:54:30 +0900, Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org> wrote:
> > Hi,
> > 
> > This is a patch to shorten freeze period.
> <snip> 
> > diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> > index 6ea5f87..2394353 100644
> > --- a/fs/nilfs2/ioctl.c
> > +++ b/fs/nilfs2/ioctl.c
> > @@ -442,12 +442,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
> >  	const char *msg;
> >  	int ret;
> >  
> > -	ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]);
> > -	if (ret < 0) {
> > -		msg = "cannot read source blocks";
> > -		goto failed;
> > -	}
> > -
> >  	ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
> >  	if (ret < 0) {
> >  		/*
> > @@ -521,6 +515,10 @@ static int nilfs_ioctl_clean_segmentsistruct inode5 einode, struct file *filp,
> >  
> >  	nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
> >  
> > +	if (nilfs_gc_running(nilfs))
> > +		return -EBUSY;
> > +	set_nilfs_gc_running(nilfs);
> > +
> 
> Well, I have two comments here on this patch:
> 
> This check and the error return should be done before memory
> allocation of kbufs[4] to avoid memory leak.

grr, that's right.  Sorry for the careless miss.
I was trying to modify the logic as little as possible.

> And, logically these bit operations must be atomic by use of
> test_and_set_bit().  So, it should be like:
> 
> 	if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags))
> 		return -EBUSY;

Ah, that's the one.  Thank you.

> I think we don't have to expand THE_NILFS_FNS macro for this.
>
> Could you revise the patch once more?

 I'll revise it.  Thank you for the comments.

> Thank you,
> Ryusuke Konishi
> 
> >  	for (n = 0; n < 4; n++) {
> >  		ret = -EINVAL;
> >  		if (argv[n].v_size != argsz[n])
> > @@ -548,12 +546,20 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
> >  		}
> >  	}
> >  
> > +	ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]);
> > +	if (ret < 0) {
> > +		printk(KERN_ERR "NILFS: GC failed during preparation: "
> > +			"cannot read source blocks: err=%d\n", ret);
> > +		goto out_free;
> > +	}
> > +
> >  	ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
> >  
> >   out_free:
> >  	while (--n >= 0)
> >  		vfree(kbufs[n]);
> >  	kfree(kbufs[4]);
> > +	clear_nilfs_gc_running(nilfs);
> >  	return ret;
> >  }
> >  
> > diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
> > index 1b9caaf..97ee569 100644
> > --- a/fs/nilfs2/the_nilfs.h
> > +++ b/fs/nilfs2/the_nilfs.h
> > @@ -37,6 +37,7 @@ enum {
> >  	THE_NILFS_LOADED,       /* Roll-back/roll-forward has done and
> >  				   the latest checkpoint was loaded */
> >  	THE_NILFS_DISCONTINUED,	/* 'next' pointer chain has broken */
> > +	THE_NILFS_GC_RUNNING,	/* gc process is running */
> >  };
> >  
> >  /**
> > @@ -197,6 +198,7 @@ static inline int nilfs_##name(struct the_nilfs *nilfs)			\
> >  THE_NILFS_FNS(INIT, init)
> >  THE_NILFS_FNS(LOADED, loaded)
> >  THE_NILFS_FNS(DISCONTINUED, discontinued)
> > +THE_NILFS_FNS(GC_RUNNING, gc_running)
> >  
> >  /* Minimum interval of periodical update of superblocks (in seconds) */
> >  #define NILFS_SB_FREQ		10
> > -- 
> > 1.5.6.5
> > 
> > _______________________________________________
> > users mailing list
> > users-JrjvKiOkagjYtjvyW6yDsg@public.gmane.org
> > https://www.nilfs.org/mailman/listinfo/users
> _______________________________________________
> users mailing list
> users-JrjvKiOkagjYtjvyW6yDsg@public.gmane.org
> https://www.nilfs.org/mailman/listinfo/users
> 
> 
> 


-- 
Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>

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

* Re: [PATCH] nilfs2: shorten freeze period due to GC in write operation
       [not found]     ` <20090831.163729.22914775.ryusuke-sG5X7nlA6pw@public.gmane.org>
  2009-08-31  8:05       ` Jiro SEKIBA
@ 2009-08-31  8:14       ` Ryusuke Konishi
  1 sibling, 0 replies; 4+ messages in thread
From: Ryusuke Konishi @ 2009-08-31  8:14 UTC (permalink / raw)
  To: jir-hfpbi5WX9J54Eiagz67IpQ; +Cc: users-JrjvKiOkagjYtjvyW6yDsg

On Mon, 31 Aug 2009 16:37:29 +0900 (JST), Ryusuke Konishi wrote:
> On Sat, 29 Aug 2009 17:54:30 +0900, Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org> wrote:
> >  	nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
> >  
> > +	if (nilfs_gc_running(nilfs))
> > +		return -EBUSY;
> > +	set_nilfs_gc_running(nilfs);
> > +
> 
> Well, I have two comments here on this patch:
> 
> This check and the error return should be done before memory
> allocation of kbufs[4] to avoid memory leak.
> 
> And, logically these bit operations must be atomic by use of
> test_and_set_bit().  So, it should be like:
> 
> 	if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags))
> 		return -EBUSY;
> 
> I think we don't have to expand THE_NILFS_FNS macro for this.

I mean we don't have to add the following template:

static inline void test_and_set_nilfs_##name(struct the_nilfs *nilfs)   \
{                                                                       \
        return test_and_set_bit(THE_NILFS_##bit, &(nilfs)->ns_flags);   \
}

But, it's OK if you prefer this.

Just in case, the use of "THE_NILFS_FNS(GC_RUNNING, gc_running)" looks
proper; you don't have to change clear_nilfs_gc_running() to
"clear_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)".

Thanks,
Ryusuke Konishi

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

end of thread, other threads:[~2009-08-31  8:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-29  8:54 [PATCH] nilfs2: shorten freeze period due to GC in write operation Jiro SEKIBA
     [not found] ` <1251536070-12052-1-git-send-email-jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
2009-08-31  7:37   ` Ryusuke Konishi
     [not found]     ` <20090831.163729.22914775.ryusuke-sG5X7nlA6pw@public.gmane.org>
2009-08-31  8:05       ` Jiro SEKIBA
2009-08-31  8:14       ` Ryusuke Konishi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox