All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] md/raid5: avoid races when changing cache size.
  2015-09-24  1:48 [PATCH 0/2] md patches for 3.1-stable NeilBrown
@ 2015-09-24  1:48 ` NeilBrown
  2015-09-24  1:48 ` [PATCH 2/2] md/raid5: don't let shrink_slab shrink too far NeilBrown
  2015-09-24 23:39 ` [PATCH 0/2] md patches for 3.1-stable Greg KH
  2 siblings, 0 replies; 4+ messages in thread
From: NeilBrown @ 2015-09-24  1:48 UTC (permalink / raw)
  To: stable

commit 2d5b569b665ea6d0b15c52529ff06300de81a7ce upstream.

Cache size can grow or shrink due to various pressures at
any time.  So when we resize the cache as part of a 'grow'
operation (i.e. change the size to allow more devices) we need
to blocks that automatic growing/shrinking.

So introduce a mutex.  auto grow/shrink uses mutex_trylock()
and just doesn't bother if there is a blockage.
Resizing the whole cache holds the mutex to ensure that
the correct number of new stripes is allocated.

This bug can result in some stripes not being freed when an
array is stopped.  This leads to the kmem_cache not being
freed and a subsequent array can try to use the same kmem_cache
and get confused.

Fixes: edbe83ab4c27 ("md/raid5: allow the stripe_cache to grow and shrink.")
Cc: stable@vger.kernel.org (4.1 - please delay until 2 weeks after release of 4.2)
Signed-off-by: NeilBrown <neilb@suse.com>
---
 drivers/md/raid5.c |   31 +++++++++++++++++++++++++------
 drivers/md/raid5.h |    3 ++-
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index b6793d2e051f..b369cbea4e54 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2151,6 +2151,9 @@ static int resize_stripes(struct r5conf *conf, int newsize)
 	if (!sc)
 		return -ENOMEM;
 
+	/* Need to ensure auto-resizing doesn't interfere */
+	mutex_lock(&conf->cache_size_mutex);
+
 	for (i = conf->max_nr_stripes; i; i--) {
 		nsh = alloc_stripe(sc, GFP_KERNEL);
 		if (!nsh)
@@ -2167,6 +2170,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
 			kmem_cache_free(sc, nsh);
 		}
 		kmem_cache_destroy(sc);
+		mutex_unlock(&conf->cache_size_mutex);
 		return -ENOMEM;
 	}
 	/* Step 2 - Must use GFP_NOIO now.
@@ -2213,6 +2217,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
 	} else
 		err = -ENOMEM;
 
+	mutex_unlock(&conf->cache_size_mutex);
 	/* Step 4, return new stripes to service */
 	while(!list_empty(&newstripes)) {
 		nsh = list_entry(newstripes.next, struct stripe_head, lru);
@@ -5846,12 +5851,14 @@ static void raid5d(struct md_thread *thread)
 	pr_debug("%d stripes handled\n", handled);
 
 	spin_unlock_irq(&conf->device_lock);
-	if (test_and_clear_bit(R5_ALLOC_MORE, &conf->cache_state)) {
+	if (test_and_clear_bit(R5_ALLOC_MORE, &conf->cache_state) &&
+	    mutex_trylock(&conf->cache_size_mutex)) {
 		grow_one_stripe(conf, __GFP_NOWARN);
 		/* Set flag even if allocation failed.  This helps
 		 * slow down allocation requests when mem is short
 		 */
 		set_bit(R5_DID_ALLOC, &conf->cache_state);
+		mutex_unlock(&conf->cache_size_mutex);
 	}
 
 	async_tx_issue_pending_all();
@@ -5883,18 +5890,22 @@ raid5_set_cache_size(struct mddev *mddev, int size)
 		return -EINVAL;
 
 	conf->min_nr_stripes = size;
+	mutex_lock(&conf->cache_size_mutex);
 	while (size < conf->max_nr_stripes &&
 	       drop_one_stripe(conf))
 		;
+	mutex_unlock(&conf->cache_size_mutex);
 
 
 	err = md_allow_write(mddev);
 	if (err)
 		return err;
 
+	mutex_lock(&conf->cache_size_mutex);
 	while (size > conf->max_nr_stripes)
 		if (!grow_one_stripe(conf, GFP_KERNEL))
 			break;
+	mutex_unlock(&conf->cache_size_mutex);
 
 	return 0;
 }
@@ -6360,11 +6371,18 @@ static unsigned long raid5_cache_scan(struct shrinker *shrink,
 				      struct shrink_control *sc)
 {
 	struct r5conf *conf = container_of(shrink, struct r5conf, shrinker);
-	int ret = 0;
-	while (ret < sc->nr_to_scan) {
-		if (drop_one_stripe(conf) == 0)
-			return SHRINK_STOP;
-		ret++;
+	unsigned long ret = SHRINK_STOP;
+
+	if (mutex_trylock(&conf->cache_size_mutex)) {
+		ret= 0;
+		while (ret < sc->nr_to_scan) {
+			if (drop_one_stripe(conf) == 0) {
+				ret = SHRINK_STOP;
+				break;
+			}
+			ret++;
+		}
+		mutex_unlock(&conf->cache_size_mutex);
 	}
 	return ret;
 }
@@ -6433,6 +6451,7 @@ static struct r5conf *setup_conf(struct mddev *mddev)
 		goto abort;
 	spin_lock_init(&conf->device_lock);
 	seqcount_init(&conf->gen_lock);
+	mutex_init(&conf->cache_size_mutex);
 	init_waitqueue_head(&conf->wait_for_stripe);
 	init_waitqueue_head(&conf->wait_for_overlap);
 	INIT_LIST_HEAD(&conf->handle_list);
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 896d603ad0da..03472fbbd882 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -482,7 +482,8 @@ struct r5conf {
 	 */
 	int			active_name;
 	char			cache_name[2][32];
-	struct kmem_cache		*slab_cache; /* for allocating stripes */
+	struct kmem_cache	*slab_cache; /* for allocating stripes */
+	struct mutex		cache_size_mutex; /* Protect changes to cache size */
 
 	int			seq_flush, seq_write;
 	int			quiesce;



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

* [PATCH 2/2] md/raid5: don't let shrink_slab shrink too far.
  2015-09-24  1:48 [PATCH 0/2] md patches for 3.1-stable NeilBrown
  2015-09-24  1:48 ` [PATCH 1/2] md/raid5: avoid races when changing cache size NeilBrown
@ 2015-09-24  1:48 ` NeilBrown
  2015-09-24 23:39 ` [PATCH 0/2] md patches for 3.1-stable Greg KH
  2 siblings, 0 replies; 4+ messages in thread
From: NeilBrown @ 2015-09-24  1:48 UTC (permalink / raw)
  To: stable

commit 49895bcc7e566ba455eb2996607d6fbd3447ce16 upstream.

I have a report of drop_one_stripe() called from
raid5_cache_scan() apparently finding ->max_nr_stripes == 0.

This should not be allowed.

So add a test to keep max_nr_stripes above min_nr_stripes.

Also use a 'mask' rather than a 'mod' in drop_one_stripe
to ensure 'hash' is valid even if max_nr_stripes does reach zero.


Fixes: edbe83ab4c27 ("md/raid5: allow the stripe_cache to grow and shrink.")
Cc: stable@vger.kernel.org (4.1 - please release with 2d5b569b665)
Reported-by: Tomas Papan <tomas.papan@gmail.com>
Signed-off-by: NeilBrown <neilb@suse.com>
---
 drivers/md/raid5.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index b369cbea4e54..23af6772f146 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2245,7 +2245,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
 static int drop_one_stripe(struct r5conf *conf)
 {
 	struct stripe_head *sh;
-	int hash = (conf->max_nr_stripes - 1) % NR_STRIPE_HASH_LOCKS;
+	int hash = (conf->max_nr_stripes - 1) & STRIPE_HASH_LOCKS_MASK;
 
 	spin_lock_irq(conf->hash_locks + hash);
 	sh = get_free_stripe(conf, hash);
@@ -6375,7 +6375,8 @@ static unsigned long raid5_cache_scan(struct shrinker *shrink,
 
 	if (mutex_trylock(&conf->cache_size_mutex)) {
 		ret= 0;
-		while (ret < sc->nr_to_scan) {
+		while (ret < sc->nr_to_scan &&
+		       conf->max_nr_stripes > conf->min_nr_stripes) {
 			if (drop_one_stripe(conf) == 0) {
 				ret = SHRINK_STOP;
 				break;



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

* [PATCH 0/2] md patches for 3.1-stable
@ 2015-09-24  1:48 NeilBrown
  2015-09-24  1:48 ` [PATCH 1/2] md/raid5: avoid races when changing cache size NeilBrown
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: NeilBrown @ 2015-09-24  1:48 UTC (permalink / raw)
  To: stable

Hi,
 upstream patches:

Commit: 2d5b569b665e ("md/raid5: avoid races when changing cache size.")
Commit: 49895bcc7e56 ("md/raid5: don't let shrink_slab shrink too far.")

were tagged for -stable, but with a request they be delayed a bit:
    Cc: stable@vger.kernel.org (4.1 - please delay until 2 weeks after release of 4.2)
    Cc: stable@vger.kernel.org (4.1 - please release with 2d5b569b665)

Those two weeks have now passed but they didn't make it into 4.1.8.
I checked and the first patch has an easily resolved conflict.  So to
make it as easy as possible the two patches based on 4.1.8 follow this
email.

Thanks,
NeilBrown


---

NeilBrown (2):
      md/raid5: avoid races when changing cache size.
      md/raid5: don't let shrink_slab shrink too far.


 drivers/md/raid5.c |   34 +++++++++++++++++++++++++++-------
 drivers/md/raid5.h |    3 ++-
 2 files changed, 29 insertions(+), 8 deletions(-)

--
Signature


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

* Re: [PATCH 0/2] md patches for 3.1-stable
  2015-09-24  1:48 [PATCH 0/2] md patches for 3.1-stable NeilBrown
  2015-09-24  1:48 ` [PATCH 1/2] md/raid5: avoid races when changing cache size NeilBrown
  2015-09-24  1:48 ` [PATCH 2/2] md/raid5: don't let shrink_slab shrink too far NeilBrown
@ 2015-09-24 23:39 ` Greg KH
  2 siblings, 0 replies; 4+ messages in thread
From: Greg KH @ 2015-09-24 23:39 UTC (permalink / raw)
  To: NeilBrown; +Cc: stable

On Thu, Sep 24, 2015 at 11:48:11AM +1000, NeilBrown wrote:
> Hi,
>  upstream patches:
> 
> Commit: 2d5b569b665e ("md/raid5: avoid races when changing cache size.")
> Commit: 49895bcc7e56 ("md/raid5: don't let shrink_slab shrink too far.")
> 
> were tagged for -stable, but with a request they be delayed a bit:
>     Cc: stable@vger.kernel.org (4.1 - please delay until 2 weeks after release of 4.2)
>     Cc: stable@vger.kernel.org (4.1 - please release with 2d5b569b665)
> 
> Those two weeks have now passed but they didn't make it into 4.1.8.
> I checked and the first patch has an easily resolved conflict.  So to
> make it as easy as possible the two patches based on 4.1.8 follow this
> email.

Thanks, the originals are still way back in my patch queue, they will be
handled eventually...

greg k-h

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

end of thread, other threads:[~2015-09-24 23:40 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-24  1:48 [PATCH 0/2] md patches for 3.1-stable NeilBrown
2015-09-24  1:48 ` [PATCH 1/2] md/raid5: avoid races when changing cache size NeilBrown
2015-09-24  1:48 ` [PATCH 2/2] md/raid5: don't let shrink_slab shrink too far NeilBrown
2015-09-24 23:39 ` [PATCH 0/2] md patches for 3.1-stable Greg KH

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.