md/raid5: resize stripe_head when reshape array
authorYufen Yu <yuyufen@huawei.com>
Thu, 20 Aug 2020 13:22:13 +0000 (09:22 -0400)
committerSong Liu <songliubraving@fb.com>
Thu, 24 Sep 2020 23:44:45 +0000 (16:44 -0700)
When reshape array, we try to reuse shared pages of old stripe_head,
and allocate more for the new one if needed.

Signed-off-by: Yufen Yu <yuyufen@huawei.com>
Signed-off-by: Song Liu <songliubraving@fb.com>
drivers/md/raid5.c

index ea1e56e..c23e408 100644 (file)
@@ -2535,6 +2535,12 @@ static int resize_stripes(struct r5conf *conf, int newsize)
                osh = get_free_stripe(conf, hash);
                unlock_device_hash_lock(conf, hash);
 
+#if PAGE_SIZE != DEFAULT_STRIPE_SIZE
+       for (i = 0; i < osh->nr_pages; i++) {
+               nsh->pages[i] = osh->pages[i];
+               osh->pages[i] = NULL;
+       }
+#endif
                for(i=0; i<conf->pool_size; i++) {
                        nsh->dev[i].page = osh->dev[i].page;
                        nsh->dev[i].orig_page = osh->dev[i].page;
@@ -2589,6 +2595,23 @@ static int resize_stripes(struct r5conf *conf, int newsize)
                nsh = list_entry(newstripes.next, struct stripe_head, lru);
                list_del_init(&nsh->lru);
 
+#if PAGE_SIZE != DEFAULT_STRIPE_SIZE
+               for (i = 0; i < nsh->nr_pages; i++) {
+                       if (nsh->pages[i])
+                               continue;
+                       nsh->pages[i] = alloc_page(GFP_NOIO);
+                       if (!nsh->pages[i])
+                               err = -ENOMEM;
+               }
+
+               for (i = conf->raid_disks; i < newsize; i++) {
+                       if (nsh->dev[i].page)
+                               continue;
+                       nsh->dev[i].page = raid5_get_dev_page(nsh, i);
+                       nsh->dev[i].orig_page = nsh->dev[i].page;
+                       nsh->dev[i].offset = raid5_get_page_offset(nsh, i);
+               }
+#else
                for (i=conf->raid_disks; i < newsize; i++)
                        if (nsh->dev[i].page == NULL) {
                                struct page *p = alloc_page(GFP_NOIO);
@@ -2598,6 +2621,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
                                if (!p)
                                        err = -ENOMEM;
                        }
+#endif
                raid5_release_stripe(nsh);
        }
        /* critical section pass, GFP_NOIO no longer needed */