extent_ranges.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. //
  2. // Copyright (C) 2010 The Android Open Source Project
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #include "update_engine/payload_generator/extent_ranges.h"
  17. #include <algorithm>
  18. #include <set>
  19. #include <utility>
  20. #include <vector>
  21. #include <base/logging.h>
  22. #include "update_engine/common/utils.h"
  23. #include "update_engine/payload_consumer/payload_constants.h"
  24. #include "update_engine/payload_generator/extent_utils.h"
  25. using std::set;
  26. using std::vector;
  27. namespace chromeos_update_engine {
  28. bool ExtentRanges::ExtentsOverlapOrTouch(const Extent& a, const Extent& b) {
  29. if (a.start_block() == b.start_block())
  30. return true;
  31. if (a.start_block() == kSparseHole || b.start_block() == kSparseHole)
  32. return false;
  33. if (a.start_block() < b.start_block()) {
  34. return a.start_block() + a.num_blocks() >= b.start_block();
  35. } else {
  36. return b.start_block() + b.num_blocks() >= a.start_block();
  37. }
  38. }
  39. bool ExtentRanges::ExtentsOverlap(const Extent& a, const Extent& b) {
  40. if (a.start_block() == b.start_block())
  41. return true;
  42. if (a.start_block() == kSparseHole || b.start_block() == kSparseHole)
  43. return false;
  44. if (a.start_block() < b.start_block()) {
  45. return a.start_block() + a.num_blocks() > b.start_block();
  46. } else {
  47. return b.start_block() + b.num_blocks() > a.start_block();
  48. }
  49. }
  50. void ExtentRanges::AddBlock(uint64_t block) {
  51. AddExtent(ExtentForRange(block, 1));
  52. }
  53. void ExtentRanges::SubtractBlock(uint64_t block) {
  54. SubtractExtent(ExtentForRange(block, 1));
  55. }
  56. namespace {
  57. Extent UnionOverlappingExtents(const Extent& first, const Extent& second) {
  58. CHECK_NE(kSparseHole, first.start_block());
  59. CHECK_NE(kSparseHole, second.start_block());
  60. uint64_t start = std::min(first.start_block(), second.start_block());
  61. uint64_t end = std::max(first.start_block() + first.num_blocks(),
  62. second.start_block() + second.num_blocks());
  63. return ExtentForRange(start, end - start);
  64. }
  65. } // namespace
  66. void ExtentRanges::AddExtent(Extent extent) {
  67. if (extent.start_block() == kSparseHole || extent.num_blocks() == 0)
  68. return;
  69. ExtentSet::iterator begin_del = extent_set_.end();
  70. ExtentSet::iterator end_del = extent_set_.end();
  71. uint64_t del_blocks = 0;
  72. for (ExtentSet::iterator it = extent_set_.begin(), e = extent_set_.end();
  73. it != e;
  74. ++it) {
  75. if (ExtentsOverlapOrTouch(*it, extent)) {
  76. end_del = it;
  77. ++end_del;
  78. del_blocks += it->num_blocks();
  79. if (begin_del == extent_set_.end())
  80. begin_del = it;
  81. extent = UnionOverlappingExtents(extent, *it);
  82. }
  83. }
  84. extent_set_.erase(begin_del, end_del);
  85. extent_set_.insert(extent);
  86. blocks_ -= del_blocks;
  87. blocks_ += extent.num_blocks();
  88. }
  89. namespace {
  90. // Returns base - subtractee (set subtraction).
  91. ExtentRanges::ExtentSet SubtractOverlappingExtents(const Extent& base,
  92. const Extent& subtractee) {
  93. ExtentRanges::ExtentSet ret;
  94. if (subtractee.start_block() > base.start_block()) {
  95. ret.insert(ExtentForRange(base.start_block(),
  96. subtractee.start_block() - base.start_block()));
  97. }
  98. uint64_t base_end = base.start_block() + base.num_blocks();
  99. uint64_t subtractee_end = subtractee.start_block() + subtractee.num_blocks();
  100. if (base_end > subtractee_end) {
  101. ret.insert(ExtentForRange(subtractee_end, base_end - subtractee_end));
  102. }
  103. return ret;
  104. }
  105. } // namespace
  106. void ExtentRanges::SubtractExtent(const Extent& extent) {
  107. if (extent.start_block() == kSparseHole || extent.num_blocks() == 0)
  108. return;
  109. ExtentSet::iterator begin_del = extent_set_.end();
  110. ExtentSet::iterator end_del = extent_set_.end();
  111. uint64_t del_blocks = 0;
  112. ExtentSet new_extents;
  113. for (ExtentSet::iterator it = extent_set_.begin(), e = extent_set_.end();
  114. it != e;
  115. ++it) {
  116. if (!ExtentsOverlap(*it, extent))
  117. continue;
  118. if (begin_del == extent_set_.end())
  119. begin_del = it;
  120. end_del = it;
  121. ++end_del;
  122. del_blocks += it->num_blocks();
  123. ExtentSet subtraction = SubtractOverlappingExtents(*it, extent);
  124. for (ExtentSet::iterator jt = subtraction.begin(), je = subtraction.end();
  125. jt != je;
  126. ++jt) {
  127. new_extents.insert(*jt);
  128. del_blocks -= jt->num_blocks();
  129. }
  130. }
  131. extent_set_.erase(begin_del, end_del);
  132. extent_set_.insert(new_extents.begin(), new_extents.end());
  133. blocks_ -= del_blocks;
  134. }
  135. void ExtentRanges::AddRanges(const ExtentRanges& ranges) {
  136. for (ExtentSet::const_iterator it = ranges.extent_set_.begin(),
  137. e = ranges.extent_set_.end();
  138. it != e;
  139. ++it) {
  140. AddExtent(*it);
  141. }
  142. }
  143. void ExtentRanges::SubtractRanges(const ExtentRanges& ranges) {
  144. for (ExtentSet::const_iterator it = ranges.extent_set_.begin(),
  145. e = ranges.extent_set_.end();
  146. it != e;
  147. ++it) {
  148. SubtractExtent(*it);
  149. }
  150. }
  151. void ExtentRanges::AddExtents(const vector<Extent>& extents) {
  152. for (vector<Extent>::const_iterator it = extents.begin(), e = extents.end();
  153. it != e;
  154. ++it) {
  155. AddExtent(*it);
  156. }
  157. }
  158. void ExtentRanges::SubtractExtents(const vector<Extent>& extents) {
  159. for (vector<Extent>::const_iterator it = extents.begin(), e = extents.end();
  160. it != e;
  161. ++it) {
  162. SubtractExtent(*it);
  163. }
  164. }
  165. void ExtentRanges::AddRepeatedExtents(
  166. const ::google::protobuf::RepeatedPtrField<Extent>& exts) {
  167. for (int i = 0, e = exts.size(); i != e; ++i) {
  168. AddExtent(exts.Get(i));
  169. }
  170. }
  171. void ExtentRanges::SubtractRepeatedExtents(
  172. const ::google::protobuf::RepeatedPtrField<Extent>& exts) {
  173. for (int i = 0, e = exts.size(); i != e; ++i) {
  174. SubtractExtent(exts.Get(i));
  175. }
  176. }
  177. bool ExtentRanges::ContainsBlock(uint64_t block) const {
  178. auto lower = extent_set_.lower_bound(ExtentForRange(block, 1));
  179. // The block could be on the extent before the one in |lower|.
  180. if (lower != extent_set_.begin())
  181. lower--;
  182. // Any extent starting at block+1 or later is not interesting, so this is the
  183. // upper limit.
  184. auto upper = extent_set_.lower_bound(ExtentForRange(block + 1, 0));
  185. for (auto iter = lower; iter != upper; ++iter) {
  186. if (iter->start_block() <= block &&
  187. block < iter->start_block() + iter->num_blocks()) {
  188. return true;
  189. }
  190. }
  191. return false;
  192. }
  193. void ExtentRanges::Dump() const {
  194. LOG(INFO) << "ExtentRanges Dump. blocks: " << blocks_;
  195. for (ExtentSet::const_iterator it = extent_set_.begin(),
  196. e = extent_set_.end();
  197. it != e;
  198. ++it) {
  199. LOG(INFO) << "{" << it->start_block() << ", " << it->num_blocks() << "}";
  200. }
  201. }
  202. Extent ExtentForRange(uint64_t start_block, uint64_t num_blocks) {
  203. Extent ret;
  204. ret.set_start_block(start_block);
  205. ret.set_num_blocks(num_blocks);
  206. return ret;
  207. }
  208. Extent ExtentForBytes(uint64_t block_size,
  209. uint64_t start_bytes,
  210. uint64_t size_bytes) {
  211. uint64_t start_block = start_bytes / block_size;
  212. uint64_t end_block = utils::DivRoundUp(start_bytes + size_bytes, block_size);
  213. return ExtentForRange(start_block, end_block - start_block);
  214. }
  215. vector<Extent> ExtentRanges::GetExtentsForBlockCount(uint64_t count) const {
  216. vector<Extent> out;
  217. if (count == 0)
  218. return out;
  219. uint64_t out_blocks = 0;
  220. CHECK(count <= blocks_);
  221. for (ExtentSet::const_iterator it = extent_set_.begin(),
  222. e = extent_set_.end();
  223. it != e;
  224. ++it) {
  225. const uint64_t blocks_needed = count - out_blocks;
  226. const Extent& extent = *it;
  227. out.push_back(extent);
  228. out_blocks += extent.num_blocks();
  229. if (extent.num_blocks() < blocks_needed)
  230. continue;
  231. if (extent.num_blocks() == blocks_needed)
  232. break;
  233. // If we get here, we just added the last extent needed, but it's too big
  234. out_blocks -= extent.num_blocks();
  235. out_blocks += blocks_needed;
  236. out.back().set_num_blocks(blocks_needed);
  237. break;
  238. }
  239. CHECK(out_blocks == utils::BlocksInExtents(out));
  240. return out;
  241. }
  242. vector<Extent> FilterExtentRanges(const vector<Extent>& extents,
  243. const ExtentRanges& ranges) {
  244. vector<Extent> result;
  245. const ExtentRanges::ExtentSet& extent_set = ranges.extent_set();
  246. for (Extent extent : extents) {
  247. // The extents are sorted by the start_block. We want to iterate all the
  248. // Extents in the ExtentSet possibly overlapping the current |extent|. This
  249. // is achieved by looking from the extent whose start_block is *lower* than
  250. // the extent.start_block() up to the greatest extent whose start_block is
  251. // lower than extent.start_block() + extent.num_blocks().
  252. auto lower = extent_set.lower_bound(extent);
  253. // We need to decrement the lower_bound to look at the extent that could
  254. // overlap the beginning of the current |extent|.
  255. if (lower != extent_set.begin())
  256. lower--;
  257. auto upper = extent_set.lower_bound(
  258. ExtentForRange(extent.start_block() + extent.num_blocks(), 0));
  259. for (auto iter = lower; iter != upper; ++iter) {
  260. if (!ExtentRanges::ExtentsOverlap(extent, *iter))
  261. continue;
  262. if (iter->start_block() <= extent.start_block()) {
  263. // We need to cut blocks from the beginning of the |extent|.
  264. uint64_t cut_blocks =
  265. iter->start_block() + iter->num_blocks() - extent.start_block();
  266. if (cut_blocks >= extent.num_blocks()) {
  267. extent.set_num_blocks(0);
  268. break;
  269. }
  270. extent = ExtentForRange(extent.start_block() + cut_blocks,
  271. extent.num_blocks() - cut_blocks);
  272. } else {
  273. // We need to cut blocks on the middle of the extent, possible up to the
  274. // end of it.
  275. result.push_back(ExtentForRange(
  276. extent.start_block(), iter->start_block() - extent.start_block()));
  277. uint64_t new_start = iter->start_block() + iter->num_blocks();
  278. uint64_t old_end = extent.start_block() + extent.num_blocks();
  279. if (new_start >= old_end) {
  280. extent.set_num_blocks(0);
  281. break;
  282. }
  283. extent = ExtentForRange(new_start, old_end - new_start);
  284. }
  285. }
  286. if (extent.num_blocks() > 0)
  287. result.push_back(extent);
  288. }
  289. return result;
  290. }
  291. } // namespace chromeos_update_engine