Commit 7aba13b7 authored by Yufen Yu's avatar Yufen Yu Committed by Song Liu

md/raid5: add a new member of offset into r5dev

Add a new member of offset into struct r5dev. It indicates the
offset of related dev[i].page. For now, since each device have a
privated page, the value is always 0. Thus, we set offset as 0
when allcate page in grow_buffers() and resize_stripes().

To support following different page offset, we try to use the page
offset rather than '0' directly for async_memcpy() and ops_run_io().

We try to support different page offset for xor compution functions
in the following. To avoid repeatly allocate a new array each time,
we add a memory region into scribble buffer to record offset.

No functional change.
Signed-off-by: default avatarYufen Yu <yuyufen@huawei.com>
Signed-off-by: default avatarSong Liu <songliubraving@fb.com>
parent 313b825f
...@@ -477,6 +477,7 @@ static int grow_buffers(struct stripe_head *sh, gfp_t gfp) ...@@ -477,6 +477,7 @@ static int grow_buffers(struct stripe_head *sh, gfp_t gfp)
} }
sh->dev[i].page = page; sh->dev[i].page = page;
sh->dev[i].orig_page = page; sh->dev[i].orig_page = page;
sh->dev[i].offset = 0;
} }
return 0; return 0;
...@@ -1130,7 +1131,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) ...@@ -1130,7 +1131,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
sh->dev[i].vec.bv_page = sh->dev[i].page; sh->dev[i].vec.bv_page = sh->dev[i].page;
bi->bi_vcnt = 1; bi->bi_vcnt = 1;
bi->bi_io_vec[0].bv_len = RAID5_STRIPE_SIZE(conf); bi->bi_io_vec[0].bv_len = RAID5_STRIPE_SIZE(conf);
bi->bi_io_vec[0].bv_offset = 0; bi->bi_io_vec[0].bv_offset = sh->dev[i].offset;
bi->bi_iter.bi_size = RAID5_STRIPE_SIZE(conf); bi->bi_iter.bi_size = RAID5_STRIPE_SIZE(conf);
bi->bi_write_hint = sh->dev[i].write_hint; bi->bi_write_hint = sh->dev[i].write_hint;
if (!rrdev) if (!rrdev)
...@@ -1184,7 +1185,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) ...@@ -1184,7 +1185,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
sh->dev[i].rvec.bv_page = sh->dev[i].page; sh->dev[i].rvec.bv_page = sh->dev[i].page;
rbi->bi_vcnt = 1; rbi->bi_vcnt = 1;
rbi->bi_io_vec[0].bv_len = RAID5_STRIPE_SIZE(conf); rbi->bi_io_vec[0].bv_len = RAID5_STRIPE_SIZE(conf);
rbi->bi_io_vec[0].bv_offset = 0; rbi->bi_io_vec[0].bv_offset = sh->dev[i].offset;
rbi->bi_iter.bi_size = RAID5_STRIPE_SIZE(conf); rbi->bi_iter.bi_size = RAID5_STRIPE_SIZE(conf);
rbi->bi_write_hint = sh->dev[i].write_hint; rbi->bi_write_hint = sh->dev[i].write_hint;
sh->dev[i].write_hint = RWH_WRITE_LIFE_NOT_SET; sh->dev[i].write_hint = RWH_WRITE_LIFE_NOT_SET;
...@@ -1404,14 +1405,25 @@ static addr_conv_t *to_addr_conv(struct stripe_head *sh, ...@@ -1404,14 +1405,25 @@ static addr_conv_t *to_addr_conv(struct stripe_head *sh,
return (void *) (to_addr_page(percpu, i) + sh->disks + 2); return (void *) (to_addr_page(percpu, i) + sh->disks + 2);
} }
/*
* Return a pointer to record offset address.
*/
static unsigned int *
to_addr_offs(struct stripe_head *sh, struct raid5_percpu *percpu)
{
return (unsigned int *) (to_addr_conv(sh, percpu, 0) + sh->disks + 2);
}
static struct dma_async_tx_descriptor * static struct dma_async_tx_descriptor *
ops_run_compute5(struct stripe_head *sh, struct raid5_percpu *percpu) ops_run_compute5(struct stripe_head *sh, struct raid5_percpu *percpu)
{ {
int disks = sh->disks; int disks = sh->disks;
struct page **xor_srcs = to_addr_page(percpu, 0); struct page **xor_srcs = to_addr_page(percpu, 0);
unsigned int *off_srcs = to_addr_offs(sh, percpu);
int target = sh->ops.target; int target = sh->ops.target;
struct r5dev *tgt = &sh->dev[target]; struct r5dev *tgt = &sh->dev[target];
struct page *xor_dest = tgt->page; struct page *xor_dest = tgt->page;
unsigned int off_dest = tgt->offset;
int count = 0; int count = 0;
struct dma_async_tx_descriptor *tx; struct dma_async_tx_descriptor *tx;
struct async_submit_ctl submit; struct async_submit_ctl submit;
...@@ -1423,16 +1435,19 @@ ops_run_compute5(struct stripe_head *sh, struct raid5_percpu *percpu) ...@@ -1423,16 +1435,19 @@ ops_run_compute5(struct stripe_head *sh, struct raid5_percpu *percpu)
__func__, (unsigned long long)sh->sector, target); __func__, (unsigned long long)sh->sector, target);
BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags)); BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
for (i = disks; i--; ) for (i = disks; i--; ) {
if (i != target) if (i != target) {
off_srcs[count] = sh->dev[i].offset;
xor_srcs[count++] = sh->dev[i].page; xor_srcs[count++] = sh->dev[i].page;
}
}
atomic_inc(&sh->count); atomic_inc(&sh->count);
init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, NULL, init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, NULL,
ops_complete_compute, sh, to_addr_conv(sh, percpu, 0)); ops_complete_compute, sh, to_addr_conv(sh, percpu, 0));
if (unlikely(count == 1)) if (unlikely(count == 1))
tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, tx = async_memcpy(xor_dest, xor_srcs[0], off_dest, off_srcs[0],
RAID5_STRIPE_SIZE(sh->raid_conf), &submit); RAID5_STRIPE_SIZE(sh->raid_conf), &submit);
else else
tx = async_xor(xor_dest, xor_srcs, 0, count, tx = async_xor(xor_dest, xor_srcs, 0, count,
...@@ -1854,9 +1869,11 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu, ...@@ -1854,9 +1869,11 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu,
{ {
int disks = sh->disks; int disks = sh->disks;
struct page **xor_srcs; struct page **xor_srcs;
unsigned int *off_srcs;
struct async_submit_ctl submit; struct async_submit_ctl submit;
int count, pd_idx = sh->pd_idx, i; int count, pd_idx = sh->pd_idx, i;
struct page *xor_dest; struct page *xor_dest;
unsigned int off_dest;
int prexor = 0; int prexor = 0;
unsigned long flags; unsigned long flags;
int j = 0; int j = 0;
...@@ -1881,24 +1898,31 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu, ...@@ -1881,24 +1898,31 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu,
again: again:
count = 0; count = 0;
xor_srcs = to_addr_page(percpu, j); xor_srcs = to_addr_page(percpu, j);
off_srcs = to_addr_offs(sh, percpu);
/* check if prexor is active which means only process blocks /* check if prexor is active which means only process blocks
* that are part of a read-modify-write (written) * that are part of a read-modify-write (written)
*/ */
if (head_sh->reconstruct_state == reconstruct_state_prexor_drain_run) { if (head_sh->reconstruct_state == reconstruct_state_prexor_drain_run) {
prexor = 1; prexor = 1;
off_dest = off_srcs[count] = sh->dev[pd_idx].offset;
xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page; xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
for (i = disks; i--; ) { for (i = disks; i--; ) {
struct r5dev *dev = &sh->dev[i]; struct r5dev *dev = &sh->dev[i];
if (head_sh->dev[i].written || if (head_sh->dev[i].written ||
test_bit(R5_InJournal, &head_sh->dev[i].flags)) test_bit(R5_InJournal, &head_sh->dev[i].flags)) {
off_srcs[count] = dev->offset;
xor_srcs[count++] = dev->page; xor_srcs[count++] = dev->page;
}
} }
} else { } else {
xor_dest = sh->dev[pd_idx].page; xor_dest = sh->dev[pd_idx].page;
off_dest = sh->dev[pd_idx].offset;
for (i = disks; i--; ) { for (i = disks; i--; ) {
struct r5dev *dev = &sh->dev[i]; struct r5dev *dev = &sh->dev[i];
if (i != pd_idx) if (i != pd_idx) {
off_srcs[count] = dev->offset;
xor_srcs[count++] = dev->page; xor_srcs[count++] = dev->page;
}
} }
} }
...@@ -1924,7 +1948,7 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu, ...@@ -1924,7 +1948,7 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu,
} }
if (unlikely(count == 1)) if (unlikely(count == 1))
tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, tx = async_memcpy(xor_dest, xor_srcs[0], off_dest, off_srcs[0],
RAID5_STRIPE_SIZE(sh->raid_conf), &submit); RAID5_STRIPE_SIZE(sh->raid_conf), &submit);
else else
tx = async_xor(xor_dest, xor_srcs, 0, count, tx = async_xor(xor_dest, xor_srcs, 0, count,
...@@ -2253,8 +2277,9 @@ static int scribble_alloc(struct raid5_percpu *percpu, ...@@ -2253,8 +2277,9 @@ static int scribble_alloc(struct raid5_percpu *percpu,
int num, int cnt) int num, int cnt)
{ {
size_t obj_size = size_t obj_size =
sizeof(struct page *) * (num+2) + sizeof(struct page *) * (num + 2) +
sizeof(addr_conv_t) * (num+2); sizeof(addr_conv_t) * (num + 2) +
sizeof(unsigned int) * (num + 2);
void *scribble; void *scribble;
/* /*
...@@ -2389,6 +2414,7 @@ static int resize_stripes(struct r5conf *conf, int newsize) ...@@ -2389,6 +2414,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
for(i=0; i<conf->pool_size; i++) { for(i=0; i<conf->pool_size; i++) {
nsh->dev[i].page = osh->dev[i].page; nsh->dev[i].page = osh->dev[i].page;
nsh->dev[i].orig_page = osh->dev[i].page; nsh->dev[i].orig_page = osh->dev[i].page;
nsh->dev[i].offset = osh->dev[i].offset;
} }
nsh->hash_lock_index = hash; nsh->hash_lock_index = hash;
free_stripe(conf->slab_cache, osh); free_stripe(conf->slab_cache, osh);
...@@ -2444,6 +2470,7 @@ static int resize_stripes(struct r5conf *conf, int newsize) ...@@ -2444,6 +2470,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
struct page *p = alloc_page(GFP_NOIO); struct page *p = alloc_page(GFP_NOIO);
nsh->dev[i].page = p; nsh->dev[i].page = p;
nsh->dev[i].orig_page = p; nsh->dev[i].orig_page = p;
nsh->dev[i].offset = 0;
if (!p) if (!p)
err = -ENOMEM; err = -ENOMEM;
} }
...@@ -4369,7 +4396,8 @@ static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh) ...@@ -4369,7 +4396,8 @@ static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh)
/* place all the copies on one channel */ /* place all the copies on one channel */
init_async_submit(&submit, 0, tx, NULL, NULL, NULL); init_async_submit(&submit, 0, tx, NULL, NULL, NULL);
tx = async_memcpy(sh2->dev[dd_idx].page, tx = async_memcpy(sh2->dev[dd_idx].page,
sh->dev[i].page, 0, 0, RAID5_STRIPE_SIZE(conf), sh->dev[i].page, sh2->dev[dd_idx].offset,
sh->dev[i].offset, RAID5_STRIPE_SIZE(conf),
&submit); &submit);
set_bit(R5_Expanded, &sh2->dev[dd_idx].flags); set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
......
...@@ -253,6 +253,7 @@ struct stripe_head { ...@@ -253,6 +253,7 @@ struct stripe_head {
struct bio req, rreq; struct bio req, rreq;
struct bio_vec vec, rvec; struct bio_vec vec, rvec;
struct page *page, *orig_page; struct page *page, *orig_page;
unsigned int offset; /* offset of the page */
struct bio *toread, *read, *towrite, *written; struct bio *toread, *read, *towrite, *written;
sector_t sector; /* sector of this page */ sector_t sector; /* sector of this page */
unsigned long flags; unsigned long flags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment