diff options
| author | Roger Pau Monne <roger.pau@citrix.com> | 2013-06-21 06:56:53 -0400 |
|---|---|---|
| committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2013-06-21 15:58:44 -0400 |
| commit | 2d9105433ff471d2c688817e98804029c074a623 (patch) | |
| tree | 7794f24be80ffaad203616bf71162bc6b54c133f /drivers/block/xen-blkback | |
| parent | 8e3f8755545cc4a7f4da8e9ef76d6d32e0dca576 (diff) | |
xen-blkback: workaround compiler bug in gcc 4.1
The code generat with gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-54)
creates an unbound loop for the second foreach_grant_safe loop in
purge_persistent_gnt.
The workaround is to avoid having this second loop and instead
perform all the work inside the first loop by adding a new variable,
clean_used, that will be set when all the desired persistent grants
have been removed and we need to iterate over the remaining ones to
remove the WAS_ACTIVE flag.
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reported-by: Tom O'Neill <toneill@vmem.com>
Reported-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/block/xen-blkback')
| -rw-r--r-- | drivers/block/xen-blkback/blkback.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index ea158fe0c9a4..4662217c61be 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c | |||
| @@ -341,7 +341,7 @@ static void purge_persistent_gnt(struct xen_blkif *blkif) | |||
| 341 | struct persistent_gnt *persistent_gnt; | 341 | struct persistent_gnt *persistent_gnt; |
| 342 | struct rb_node *n; | 342 | struct rb_node *n; |
| 343 | unsigned int num_clean, total; | 343 | unsigned int num_clean, total; |
| 344 | bool scan_used = false; | 344 | bool scan_used = false, clean_used = false; |
| 345 | struct rb_root *root; | 345 | struct rb_root *root; |
| 346 | 346 | ||
| 347 | if (blkif->persistent_gnt_c < xen_blkif_max_pgrants || | 347 | if (blkif->persistent_gnt_c < xen_blkif_max_pgrants || |
| @@ -358,9 +358,8 @@ static void purge_persistent_gnt(struct xen_blkif *blkif) | |||
| 358 | num_clean = (xen_blkif_max_pgrants / 100) * LRU_PERCENT_CLEAN; | 358 | num_clean = (xen_blkif_max_pgrants / 100) * LRU_PERCENT_CLEAN; |
| 359 | num_clean = blkif->persistent_gnt_c - xen_blkif_max_pgrants + num_clean; | 359 | num_clean = blkif->persistent_gnt_c - xen_blkif_max_pgrants + num_clean; |
| 360 | num_clean = min(blkif->persistent_gnt_c, num_clean); | 360 | num_clean = min(blkif->persistent_gnt_c, num_clean); |
| 361 | if (num_clean > | 361 | if ((num_clean == 0) || |
| 362 | (blkif->persistent_gnt_c - | 362 | (num_clean > (blkif->persistent_gnt_c - atomic_read(&blkif->persistent_gnt_in_use)))) |
| 363 | atomic_read(&blkif->persistent_gnt_in_use))) | ||
| 364 | return; | 363 | return; |
| 365 | 364 | ||
| 366 | /* | 365 | /* |
| @@ -383,6 +382,11 @@ purge_list: | |||
| 383 | BUG_ON(persistent_gnt->handle == | 382 | BUG_ON(persistent_gnt->handle == |
| 384 | BLKBACK_INVALID_HANDLE); | 383 | BLKBACK_INVALID_HANDLE); |
| 385 | 384 | ||
| 385 | if (clean_used) { | ||
| 386 | clear_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags); | ||
| 387 | continue; | ||
| 388 | } | ||
| 389 | |||
| 386 | if (test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags)) | 390 | if (test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags)) |
| 387 | continue; | 391 | continue; |
| 388 | if (!scan_used && | 392 | if (!scan_used && |
| @@ -400,18 +404,18 @@ purge_list: | |||
| 400 | * grants that were used since last purge in order to cope | 404 | * grants that were used since last purge in order to cope |
| 401 | * with the requested num | 405 | * with the requested num |
| 402 | */ | 406 | */ |
| 403 | if (!scan_used) { | 407 | if (!scan_used && !clean_used) { |
| 404 | pr_debug(DRV_PFX "Still missing %u purged frames\n", num_clean); | 408 | pr_debug(DRV_PFX "Still missing %u purged frames\n", num_clean); |
| 405 | scan_used = true; | 409 | scan_used = true; |
| 406 | goto purge_list; | 410 | goto purge_list; |
| 407 | } | 411 | } |
| 408 | finished: | 412 | finished: |
| 409 | /* Remove the "used" flag from all the persistent grants */ | 413 | if (!clean_used) { |
| 410 | foreach_grant_safe(persistent_gnt, n, root, node) { | 414 | pr_debug(DRV_PFX "Finished scanning for grants to clean, removing used flag\n"); |
| 411 | BUG_ON(persistent_gnt->handle == | 415 | clean_used = true; |
| 412 | BLKBACK_INVALID_HANDLE); | 416 | goto purge_list; |
| 413 | clear_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags); | ||
| 414 | } | 417 | } |
| 418 | |||
| 415 | blkif->persistent_gnt_c -= (total - num_clean); | 419 | blkif->persistent_gnt_c -= (total - num_clean); |
| 416 | blkif->vbd.overflow_max_grants = 0; | 420 | blkif->vbd.overflow_max_grants = 0; |
| 417 | 421 | ||
