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 | ||