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