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