Revision f9749f28 block/stream.c
b/block/stream.c | ||
---|---|---|
101 | 101 |
/* |
102 | 102 |
* Given an image chain: [BASE] -> [INTER1] -> [INTER2] -> [TOP] |
103 | 103 |
* |
104 |
* Return true if the given sector is allocated in top.
|
|
105 |
* Return false if the given sector is allocated in intermediate images.
|
|
106 |
* Return true otherwise.
|
|
104 |
* Return true if the given sector is allocated in any image between
|
|
105 |
* BASE and TOP (inclusive). BASE can be NULL to check if the given
|
|
106 |
* sector is allocated in any image of the chain. Return false otherwise.
|
|
107 | 107 |
* |
108 | 108 |
* 'pnum' is set to the number of sectors (including and immediately following |
109 | 109 |
* the specified sector) that are known to be in the same |
110 | 110 |
* allocated/unallocated state. |
111 | 111 |
* |
112 | 112 |
*/ |
113 |
static int coroutine_fn is_allocated_base(BlockDriverState *top,
|
|
114 |
BlockDriverState *base, |
|
115 |
int64_t sector_num, |
|
116 |
int nb_sectors, int *pnum) |
|
113 |
static int coroutine_fn is_allocated_above(BlockDriverState *top,
|
|
114 |
BlockDriverState *base,
|
|
115 |
int64_t sector_num,
|
|
116 |
int nb_sectors, int *pnum)
|
|
117 | 117 |
{ |
118 | 118 |
BlockDriverState *intermediate; |
119 |
int ret, n; |
|
120 |
|
|
121 |
ret = bdrv_co_is_allocated(top, sector_num, nb_sectors, &n); |
|
122 |
if (ret) { |
|
123 |
*pnum = n; |
|
124 |
return ret; |
|
125 |
} |
|
126 |
|
|
127 |
/* |
|
128 |
* Is the unallocated chunk [sector_num, n] also |
|
129 |
* unallocated between base and top? |
|
130 |
*/ |
|
131 |
intermediate = top->backing_hd; |
|
119 |
int ret, n = nb_sectors; |
|
132 | 120 |
|
121 |
intermediate = top; |
|
133 | 122 |
while (intermediate != base) { |
134 | 123 |
int pnum_inter; |
135 |
|
|
136 | 124 |
ret = bdrv_co_is_allocated(intermediate, sector_num, nb_sectors, |
137 | 125 |
&pnum_inter); |
138 | 126 |
if (ret < 0) { |
139 | 127 |
return ret; |
140 | 128 |
} else if (ret) { |
141 | 129 |
*pnum = pnum_inter; |
142 |
return 0;
|
|
130 |
return 1;
|
|
143 | 131 |
} |
144 | 132 |
|
145 | 133 |
/* |
... | ... | |
156 | 144 |
} |
157 | 145 |
|
158 | 146 |
*pnum = n; |
159 |
return 1;
|
|
147 |
return 0;
|
|
160 | 148 |
} |
161 | 149 |
|
162 | 150 |
static void coroutine_fn stream_run(void *opaque) |
... | ... | |
189 | 177 |
|
190 | 178 |
for (sector_num = 0; sector_num < end; sector_num += n) { |
191 | 179 |
uint64_t delay_ns = 0; |
180 |
bool copy; |
|
192 | 181 |
|
193 | 182 |
wait: |
194 | 183 |
/* Note that even when no rate limit is applied we need to yield |
... | ... | |
199 | 188 |
break; |
200 | 189 |
} |
201 | 190 |
|
202 |
ret = is_allocated_base(bs, base, sector_num, |
|
203 |
STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n); |
|
191 |
ret = bdrv_co_is_allocated(bs, sector_num, |
|
192 |
STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n); |
|
193 |
if (ret == 1) { |
|
194 |
/* Allocated in the top, no need to copy. */ |
|
195 |
copy = false; |
|
196 |
} else { |
|
197 |
/* Copy if allocated in the intermediate images. Limit to the |
|
198 |
* known-unallocated area [sector_num, sector_num+n). */ |
|
199 |
ret = is_allocated_above(bs->backing_hd, base, sector_num, n, &n); |
|
200 |
copy = (ret == 1); |
|
201 |
} |
|
202 |
|
|
204 | 203 |
trace_stream_one_iteration(s, sector_num, n, ret); |
205 |
if (ret == 0) {
|
|
204 |
if (ret >= 0 && copy) {
|
|
206 | 205 |
if (s->common.speed) { |
207 | 206 |
delay_ns = ratelimit_calculate_delay(&s->limit, n); |
208 | 207 |
if (delay_ns > 0) { |
Also available in: Unified diff