From: NeilBrown <neilb@suse.de>
To: Andrew Morton <akpm@osdl.org>
Cc: linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 002 of 6] md: Documentation and tidy up for resize_stripes
Date: Fri, 17 Mar 2006 18:21:30 +1100 [thread overview]
Message-ID: <1060317072130.28626@suse.de> (raw)
In-Reply-To: 20060317181912.28543.patches@notabene
Explain the stages of resize_stripes so that it is clear what it
happening, why GFP_NOIO is needed, and how -ENOMEM is handled.
Also move the releasing of old stripes and the old kmem_cache
earlier and lose the need for 'oldstripes'.
Signed-off-by: Neil Brown <neilb@suse.de>
### Diffstat output
./drivers/md/raid5.c | 51 ++++++++++++++++++++++++++++++++-------------------
1 file changed, 32 insertions(+), 19 deletions(-)
diff ./drivers/md/raid5.c~current~ ./drivers/md/raid5.c
--- ./drivers/md/raid5.c~current~ 2006-03-17 18:18:19.000000000 +1100
+++ ./drivers/md/raid5.c 2006-03-17 18:18:32.000000000 +1100
@@ -334,19 +334,31 @@ static int grow_stripes(raid5_conf_t *co
}
static int resize_stripes(raid5_conf_t *conf, int newsize)
{
- /* make all the stripes able to hold 'newsize' devices.
+ /* Make all the stripes able to hold 'newsize' devices.
* New slots in each stripe get 'page' set to a new page.
- * We allocate all the new stripes first, then if that succeeds,
- * copy everything across.
- * Finally we add new pages. This could fail, but we leave
- * the stripe cache at it's new size, just with some pages empty.
*
- * We use GFP_NOIO allocations as IO to the raid5 is blocked
- * at some points in this operation.
+ * This happens in stages:
+ * 1/ create a new kmem_cache and allocate the required number of
+ * stripe_heads.
+ * 2/ gather all the old stripe_heads and tranfer the pages across
+ * to the new stripe_heads. This will have the side effect of
+ * freezing the array as once all stripe_heads have been collected,
+ * no IO will be possible. Old stripe heads are freed once their
+ * pages have been transferred over, and the old kmem_cache is
+ * freed when all stripes are done.
+ * 3/ reallocate conf->disks to be suitable bigger. If this fails,
+ * we simple return a failre status - no need to clean anything up.
+ * 4/ allocate new pages for the new slots in the new stripe_heads.
+ * If this fails, we don't bother trying the shrink the
+ * stripe_heads down again, we just leave them as they are.
+ * As each stripe_head is processed the new one is released into
+ * active service.
+ *
+ * Once step2 is started, we cannot afford to wait for a write,
+ * so we use GFP_NOIO allocations.
*/
struct stripe_head *osh, *nsh;
LIST_HEAD(newstripes);
- LIST_HEAD(oldstripes);
struct disk_info *ndisks;
int err = 0;
kmem_cache_t *sc;
@@ -355,6 +367,7 @@ static int resize_stripes(raid5_conf_t *
if (newsize <= conf->pool_size)
return 0; /* never bother to shrink */
+ /* Step 1 */
sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
0, 0, NULL, NULL);
@@ -362,7 +375,7 @@ static int resize_stripes(raid5_conf_t *
return -ENOMEM;
for (i = conf->max_nr_stripes; i; i--) {
- nsh = kmem_cache_alloc(sc, GFP_NOIO);
+ nsh = kmem_cache_alloc(sc, GFP_KERNEL);
if (!nsh)
break;
@@ -383,7 +396,8 @@ static int resize_stripes(raid5_conf_t *
kmem_cache_destroy(sc);
return -ENOMEM;
}
- /* OK, we have enough stripes, start collecting inactive
+ /* Step 2 - Must use GFP_NOIO now.
+ * OK, we have enough stripes, start collecting inactive
* stripes and copying them over
*/
list_for_each_entry(nsh, &newstripes, lru) {
@@ -400,10 +414,11 @@ static int resize_stripes(raid5_conf_t *
nsh->dev[i].page = osh->dev[i].page;
for( ; i<newsize; i++)
nsh->dev[i].page = NULL;
- list_add(&osh->lru, &oldstripes);
+ kmem_cache_free(conf->slab_cache, osh);
}
- /* Got them all.
- * Return the new ones and free the old ones.
+ kmem_cache_destroy(conf->slab_cache);
+
+ /* Step 3.
* At this point, we are holding all the stripes so the array
* is completely stalled, so now is a good time to resize
* conf->disks.
@@ -416,6 +431,8 @@ static int resize_stripes(raid5_conf_t *
conf->disks = ndisks;
} else
err = -ENOMEM;
+
+ /* Step 4, return new stripes to service */
while(!list_empty(&newstripes)) {
nsh = list_entry(newstripes.next, struct stripe_head, lru);
list_del_init(&nsh->lru);
@@ -428,12 +445,8 @@ static int resize_stripes(raid5_conf_t *
}
release_stripe(nsh);
}
- while(!list_empty(&oldstripes)) {
- osh = list_entry(oldstripes.next, struct stripe_head, lru);
- list_del(&osh->lru);
- kmem_cache_free(conf->slab_cache, osh);
- }
- kmem_cache_destroy(conf->slab_cache);
+ /* critical section pass, GFP_NOIO no longer needed */
+
conf->slab_cache = sc;
conf->active_name = 1-conf->active_name;
conf->pool_size = newsize;
next prev parent reply other threads:[~2006-03-17 7:21 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-03-17 7:21 [PATCH 000 of 6] md: Introduction - patching those patches NeilBrown
2006-03-17 7:21 ` [PATCH 001 of 6] md: INIT_LIST_HEAD to LIST_HEAD conversions NeilBrown
2006-03-17 7:21 ` NeilBrown [this message]
2006-03-17 7:21 ` [PATCH 003 of 6] md: Remove an unused variable NeilBrown
2006-03-17 7:21 ` [PATCH 004 of 6] md: Improve comments about locking situation in raid5 make_request NeilBrown
2006-03-17 7:21 ` [PATCH 005 of 6] md: Remove some stray semi-colons after functions called in macro NeilBrown
2006-03-17 7:21 ` [PATCH 006 of 6] md: Make new function stripe_to_pdidx static NeilBrown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1060317072130.28626@suse.de \
--to=neilb@suse.de \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-raid@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).