Revision f214978a block/qcow2-cluster.c
b/block/qcow2-cluster.c | ||
---|---|---|
684 | 684 |
int l2_index, ret; |
685 | 685 |
uint64_t l2_offset, *l2_table, cluster_offset; |
686 | 686 |
int nb_clusters, i = 0; |
687 |
QCowL2Meta *old_alloc; |
|
687 | 688 |
|
688 | 689 |
ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index); |
689 | 690 |
if (ret == 0) |
... | ... | |
732 | 733 |
} |
733 | 734 |
nb_clusters = i; |
734 | 735 |
|
736 |
/* |
|
737 |
* Check if there already is an AIO write request in flight which allocates |
|
738 |
* the same cluster. In this case we need to wait until the previous |
|
739 |
* request has completed and updated the L2 table accordingly. |
|
740 |
*/ |
|
741 |
LIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) { |
|
742 |
|
|
743 |
uint64_t end_offset = offset + nb_clusters * s->cluster_size; |
|
744 |
uint64_t old_offset = old_alloc->offset; |
|
745 |
uint64_t old_end_offset = old_alloc->offset + |
|
746 |
old_alloc->nb_clusters * s->cluster_size; |
|
747 |
|
|
748 |
if (end_offset < old_offset || offset > old_end_offset) { |
|
749 |
/* No intersection */ |
|
750 |
} else { |
|
751 |
if (offset < old_offset) { |
|
752 |
/* Stop at the start of a running allocation */ |
|
753 |
nb_clusters = (old_offset - offset) >> s->cluster_bits; |
|
754 |
} else { |
|
755 |
nb_clusters = 0; |
|
756 |
} |
|
757 |
|
|
758 |
if (nb_clusters == 0) { |
|
759 |
/* Set dependency and wait for a callback */ |
|
760 |
m->depends_on = old_alloc; |
|
761 |
m->nb_clusters = 0; |
|
762 |
*num = 0; |
|
763 |
return 0; |
|
764 |
} |
|
765 |
} |
|
766 |
} |
|
767 |
|
|
768 |
if (!nb_clusters) { |
|
769 |
abort(); |
|
770 |
} |
|
771 |
|
|
772 |
LIST_INSERT_HEAD(&s->cluster_allocs, m, next_in_flight); |
|
773 |
|
|
735 | 774 |
/* allocate a new cluster */ |
736 | 775 |
|
737 | 776 |
cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size); |
Also available in: Unified diff