Revision 212a5a8f block.c

b/block.c
5094 5094
    return bs->drv->bdrv_amend_options(bs, options);
5095 5095
}
5096 5096

  
5097
ExtSnapshotPerm bdrv_check_ext_snapshot(BlockDriverState *bs)
5097
/* Used to recurse on single child block filters.
5098
 * Single child block filter will store their child in bs->file.
5099
 */
5100
bool bdrv_generic_is_first_non_filter(BlockDriverState *bs,
5101
                                      BlockDriverState *candidate)
5098 5102
{
5099
    if (bs->drv->bdrv_check_ext_snapshot) {
5100
        return bs->drv->bdrv_check_ext_snapshot(bs);
5103
    if (!bs->drv) {
5104
        return false;
5105
    }
5106

  
5107
    if (!bs->drv->authorizations[BS_IS_A_FILTER]) {
5108
        if (bs == candidate) {
5109
            return true;
5110
        } else {
5111
            return false;
5112
        }
5113
    }
5114

  
5115
    if (!bs->drv->authorizations[BS_FILTER_PASS_DOWN]) {
5116
        return false;
5101 5117
    }
5102 5118

  
5103
    if (bs->file && bs->file->drv && bs->file->drv->bdrv_check_ext_snapshot) {
5104
        return bs->file->drv->bdrv_check_ext_snapshot(bs);
5119
    if (!bs->file) {
5120
        return false;
5121
    }
5122

  
5123
    return bdrv_recurse_is_first_non_filter(bs->file, candidate);
5124
}
5125

  
5126
bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs,
5127
                                      BlockDriverState *candidate)
5128
{
5129
    if (bs->drv && bs->drv->bdrv_recurse_is_first_non_filter) {
5130
        return bs->drv->bdrv_recurse_is_first_non_filter(bs, candidate);
5105 5131
    }
5106 5132

  
5107
    /* external snapshots are allowed by default */
5108
    return EXT_SNAPSHOT_ALLOWED;
5133
    return bdrv_generic_is_first_non_filter(bs, candidate);
5109 5134
}
5110 5135

  
5111
ExtSnapshotPerm bdrv_check_ext_snapshot_forbidden(BlockDriverState *bs)
5136
/* This function checks if the candidate is the first non filter bs down it's
5137
 * bs chain. Since we don't have pointers to parents it explore all bs chains
5138
 * from the top. Some filters can choose not to pass down the recursion.
5139
 */
5140
bool bdrv_is_first_non_filter(BlockDriverState *candidate)
5112 5141
{
5113
    return EXT_SNAPSHOT_FORBIDDEN;
5142
    BlockDriverState *bs;
5143

  
5144
    /* walk down the bs forest recursively */
5145
    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
5146
        bool perm;
5147

  
5148
        if (!bs->file) {
5149
            continue;
5150
        }
5151

  
5152
        perm = bdrv_recurse_is_first_non_filter(bs->file, candidate);
5153

  
5154
        /* candidate is the first non filter */
5155
        if (perm) {
5156
            return true;
5157
        }
5158
    }
5159

  
5160
    return false;
5114 5161
}

Also available in: Unified diff