md: req/comp logic for async write operations
PATCH 5/12 md: req/comp logic for async write operations
The RAID-6 driver shares handle_write_operations() with RAID-5. For this
purpose, some modifications to handle_write_operations5() had been made. The function itself was renamed as well. The handle_write_operations() is being triggered either from handle_stripe6() or handle_stripe5().
This patch introduces one more RAID-5/6 shared function, it ishandle_completed_postxor_requests(), to be called when either handle_stripe5() or handle_stripe6() discover the completeness of a post-xor operation for the stripe.
Signed-off-by Yuri Tikhonov <[email protected]>
Signed-off-by Mikhail Cherkashin <[email protected]>
--
drivers/md/raid5.c +84 -50
@@ -2447,11 +2447,12 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) }static int -handle_write_operations5 (struct stripe_head *sh,int rcw,int expand) +handle_write_operations (struct stripe_head *sh,int rcw,int expand) {int locked =0 ;struct stripe_queue *sq = sh->sq;int i, pd_idx = sq->pd_idx, disks = sq->disks; +int level = sq->raid_conf->level;if (rcw) {/* if we are not expanding this is a proper write request, and
@@ -2478,6 +2479,7 @@ handle_write_operations5(struct stripe_head *sh, int rcw, int expand) } } }else { +BUG_ON (level ==6 );BUG_ON (!(test_bit (R5_UPTODATE , &sh->dev[pd_idx].flags) ||test_bit (R5_Wantcompute, &sh->dev[pd_idx].flags)));
@@ -2510,13 +2512,20 @@ handle_write_operations5(struct stripe_head *sh, int rcw, int expand) } } -/* keep the parity disk locked while asynchronous operations +/* keep the parity disks locked while asynchronous operations * are in flight */ set_bit (R5_LOCKED , &sh->dev[pd_idx].flags);clear_bit (R5_UPTODATE , &sh->dev[pd_idx].flags); locked++; +if (level ==6 ) { +int qd_idx =raid6_next_disk (pd_idx, disks); +set_bit (R5_LOCKED , &sh->dev[qd_idx].flags); +clear_bit (R5_UPTODATE , &sh->dev[qd_idx].flags); + locked++; + } +pr_debug ("%s: stripe %llu locked: %d pending: %lx\n" , __FUNCTION__, (unsigned long long )sh->sector, locked, sh->ops.pending);
@@ -2881,6 +2890,47 @@ static void handle_issuing_new_read_requests6(struct stripe_head *sh,set_bit (STRIPE_HANDLE , &sh->state); } +static void handle_completed_postxor_requests (struct stripe_head *sh, +struct stripe_head_state *s,int disks) +{ +struct stripe_queue *sq = sh->sq; +int i, pd_idx = sq->pd_idx; +int qd_idx = (sq->raid_conf->level !=6 ) ?-1 : +raid6_next_disk (pd_idx, disks); +struct r5dev *dev; + +clear_bit (STRIPE_OP_BIODRAIN , &sh->ops.complete); +clear_bit (STRIPE_OP_BIODRAIN , &sh->ops.ack); +clear_bit (STRIPE_OP_BIODRAIN , &sh->ops.pending); + +clear_bit (STRIPE_OP_POSTXOR , &sh->ops.complete); +clear_bit (STRIPE_OP_POSTXOR , &sh->ops.ack); +clear_bit (STRIPE_OP_POSTXOR , &sh->ops.pending); + +/* All the 'written' buffers and the parity block are ready to be +* written back to disk +*/ +BUG_ON (!test_bit (R5_UPTODATE , &sh->dev[pd_idx].flags)); +if (!(qd_idx <0 )) +BUG_ON (!test_bit (R5_UPTODATE , &sh->dev[qd_idx].flags)); + +for (i = disks; i--;) { +struct r5_queue_dev *dev_q = &sq->dev[i]; + + dev = &sh->dev[i]; +if (test_bit (R5_LOCKED , &dev->flags) && + (i == pd_idx || i == qd_idx || dev_q->written)) { +pr_debug ("Writing block %d\n" , i); +set_bit (R5_Wantwrite, &dev->flags); +if (!test_and_set_bit (STRIPE_OP_IO , &sh->ops.pending)) + sh->ops.count++; +if (!test_bit (R5_Insync, &dev->flags) || + ((i == pd_idx || i == qd_idx) && + s->failed ==0 )) +set_bit (STRIPE_INSYNC , &sh->state); + } + } +}/* handle_completed_write_requests * any written block on an uptodate or failed drive can be returned.
@@ -3016,7 +3066,7 @@ static void handle_issuing_new_write_requests5(raid5_conf_t *conf,if ((s->req_compute || !test_bit (STRIPE_OP_COMPUTE_BLK , &sh->ops.pending)) && (s->locked ==0 && (rcw ==0 || rmw ==0 ))) - s->locked +=handle_write_operations5 (sh, rcw ==0 ,0 ); + s->locked +=handle_write_operations (sh, rcw ==0 ,0 ); } static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
@@ -3066,6 +3116,14 @@ static void handle_issuing_new_write_requests6(raid5_conf_t *conf,/* now if nothing is locked, and if we have enough data, we can start a * write request */ +/* since handle_stripe can be called at any time we need to handle the case +* where a compute block operation has been submitted and then a subsequent +* call wants to start a write request. raid_run_ops only handles the case where +* compute block and postxor are requested simultaneously. If this +* is not the case then new writes need to be held off until the compute +* completes. +*/ +if (s->locked ==0 && rcw ==0 ) {if (must_compute >0 ) {/* We have failed blocks and need to compute them */
@@ -3084,19 +3142,9 @@ static void handle_issuing_new_write_requests6(raid5_conf_t *conf, } } -pr_debug ("Computing parity for stripe %llu\n" , - (unsigned long long )sh->sector); -compute_parity6 (sh,RECONSTRUCT_WRITE ); -/* now every locked buffer is ready to be written */ -for (i = disks; i--; ) -if (test_bit (R5_LOCKED , &sh->dev[i].flags)) { -pr_debug ("Writing stripe %llu block %d\n" , - (unsigned long long )sh->sector, i); - s->locked++; -set_bit (R5_Wantwrite, &sh->dev[i].flags); - } -/* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */ -set_bit (STRIPE_INSYNC , &sh->state); +if (s->req_compute || + !test_bit (STRIPE_OP_COMPUTE_BLK , &sh->ops.pending)) + s->locked +=handle_write_operations (sh, rcw ==0 ,0 ); } }
@@ -3514,37 +3562,8 @@ static void handle_stripe5(struct stripe_head *sh)/* if only POSTXOR is set then this is an 'expand' postxor */ if (test_bit (STRIPE_OP_BIODRAIN , &sh->ops.complete) && -test_bit (STRIPE_OP_POSTXOR , &sh->ops.complete)) { - -clear_bit (STRIPE_OP_BIODRAIN , &sh->ops.complete); -clear_bit (STRIPE_OP_BIODRAIN , &sh->ops.ack); -clear_bit (STRIPE_OP_BIODRAIN , &sh->ops.pending); - -clear_bit (STRIPE_OP_POSTXOR , &sh->ops.complete); -clear_bit (STRIPE_OP_POSTXOR , &sh->ops.ack); -clear_bit (STRIPE_OP_POSTXOR , &sh->ops.pending); - -/* All the 'written' buffers and the parity block are ready to -* be written back to disk -*/ -BUG_ON (!test_bit (R5_UPTODATE , &sh->dev[sq->pd_idx].flags)); -for (i = disks; i--; ) { -struct r5_queue_dev *dev_q = &sq->dev[i]; - - dev = &sh->dev[i]; -if (test_bit (R5_LOCKED , &dev->flags) && - (i == sq->pd_idx || dev_q->written)) { -pr_debug ("Writing block %d\n" , i); -set_bit (R5_Wantwrite, &dev->flags); -if (!test_and_set_bit ( -STRIPE_OP_IO , &sh->ops.pending)) - sh->ops.count++; -if (!test_bit (R5_Insync, &dev->flags) || - (i == sq->pd_idx && s.failed ==0 )) -set_bit (STRIPE_INSYNC , &sh->state); - } - } - } +test_bit (STRIPE_OP_POSTXOR , &sh->ops.complete)) +handle_completed_postxor_requests (sh, &s, disks);/* Now to consider new write requests and what else, if anything * should be read. We do not handle new writes when:
@@ -3624,7 +3643,7 @@ static void handle_stripe5(struct stripe_head *sh) sq->disks = conf->raid_disks; sq->pd_idx =stripe_to_pdidx (sh->sector, conf, conf->raid_disks); - s.locked +=handle_write_operations5 (sh,1 ,1 ); + s.locked +=handle_write_operations (sh,1 ,1 ); }else if (s.expanded && !test_bit (STRIPE_OP_POSTXOR , &sh->ops.pending)) {clear_bit (STRIPE_EXPAND_READY , &sh->state);
@@ -3787,8 +3806,23 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) (s.syncing && (s.uptodate < disks)) || s.expanding)handle_issuing_new_read_requests6 (sh, &s, &r6s, disks); -/* now to consider writing and what else, if anything should be read */ -if (s.to_write) +/* Now we check to see if any write operations have recently +* completed +*/ + +/* if only POSTXOR is set then this is an 'expand' postxor */ +if (test_bit (STRIPE_OP_BIODRAIN , &sh->ops.complete) && +test_bit (STRIPE_OP_POSTXOR , &sh->ops.complete)) +handle_completed_postxor_requests (sh, &s, disks); + +/* 1/ Now to consider new write requests and what else, +* if anything shuold be read +* 2/ Check operations clobber the parity block so do not start +* new writes while a check is in flight +* 3/ Write operations do not stack +*/ +if (s.to_write && !test_bit (STRIPE_OP_POSTXOR , &sh->ops.pending) && + !test_bit (STRIPE_OP_CHECK , &sh->ops.pending))handle_issuing_new_write_requests6 (conf, sh, &s, &r6s, disks);/* maybe we need to check and possibly fix the parity for this stripe
Signature · 2 lines
Yuri Tikhonov, Senior Software Engineer Emcraft Systems, www.emcraft.com