1 /*
2 * Copyright (C) 2015-2016 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
17 #pragma once
18
19 #include "block_device.h" /* for data_block_t */
20
21 /**
22 * struct block_range - Struct describing a range of blocks
23 * @start: First block in range.
24 * @end: Last block in range plus one.
25 */
26 struct block_range {
27 data_block_t start;
28 data_block_t end;
29 };
30 #define BLOCK_RANGE_INITIAL_VALUE(block_range) \
31 { 0, 0 }
32
33 /**
34 * block_range_empty - Check if block range is empty
35 * @range: Block range to check.
36 *
37 * Return: %true if @range is empty, %false otherwise.
38 */
block_range_empty(const struct block_range range)39 static inline bool block_range_empty(const struct block_range range) {
40 assert(range.end >= range.start);
41
42 return range.start == range.end;
43 }
44
45 /*
46 * block_in_range - Check if block is in range
47 * @range: Block range to check.
48 * @block: Block to check.
49 *
50 * Return: %true if @block is in @range, %false otherwise.
51 */
block_in_range(const struct block_range range,data_block_t block)52 static inline bool block_in_range(const struct block_range range,
53 data_block_t block) {
54 assert(range.end >= range.start);
55
56 return (block >= range.start && block < range.end);
57 }
58
59 /**
60 * block_in_range - Check if two block ranges have any overlap
61 * @a: Block range to check.
62 * @b: Block range to check.
63 *
64 * Return: %true if @a and @b share any blocks, %false otherwise.
65 */
block_range_overlap(const struct block_range a,const struct block_range b)66 static inline bool block_range_overlap(const struct block_range a,
67 const struct block_range b) {
68 return block_in_range(a, b.start) || block_in_range(b, a.start);
69 }
70
71 /**
72 * block_range_before - Check if a block range start before another block range
73 * @a: Block range to check.
74 * @b: Block range to check.
75 *
76 * Return: %true if @a starts at a lower block number than @b where the start
77 * block number of an empty block range is considered infinite, %false
78 * otherwise.
79 */
block_range_before(const struct block_range a,const struct block_range b)80 static inline bool block_range_before(const struct block_range a,
81 const struct block_range b) {
82 return !block_range_empty(a) && (block_range_empty(b) || a.start < b.start);
83 }
84
85 /**
86 * block_range_is_sub_range - Check if a block range is a subset of another
87 * range
88 * @range: Block range to check.
89 * @sub_range: Block range to check.
90 *
91 * Return: %true if every block in @sub_range is also in @range, %false
92 * otherwise. @sub_range is not allowed to be be empty.
93 */
block_range_is_sub_range(const struct block_range range,const struct block_range sub_range)94 static inline bool block_range_is_sub_range(
95 const struct block_range range,
96 const struct block_range sub_range) {
97 assert(!block_range_empty(sub_range));
98 return block_in_range(range, sub_range.start) &&
99 block_in_range(range, sub_range.end - 1);
100 }
101
102 /**
103 * block_range_eq - Check if two block ranges are identical
104 * @a: Block range to check.
105 * @b: Block range to check.
106 *
107 * Return: %true if @a and @b are identical, %false otherwise.
108 */
block_range_eq(const struct block_range a,const struct block_range b)109 static inline bool block_range_eq(const struct block_range a,
110 const struct block_range b) {
111 assert(a.end >= a.start);
112 assert(b.end >= b.start);
113
114 return a.start == b.start && a.end == b.end;
115 }
116
117 /**
118 * block_range_init_single - Initialize a block range containing a single block
119 * @range: Block range object to initialize.
120 * @block: Block that should be in @range.
121 */
block_range_init_single(struct block_range * range,data_block_t block)122 static inline void block_range_init_single(struct block_range* range,
123 data_block_t block) {
124 range->start = block;
125 range->end = block + 1;
126 }
127
128 /**
129 * block_range_clear - Remove all blocks from a block range
130 * @range: Block range object to clear.
131 */
block_range_clear(struct block_range * range)132 static inline void block_range_clear(struct block_range* range) {
133 range->start = 0;
134 range->end = 0;
135 }
136