/* * Copyright (C) 2015-2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "block_device.h" /* for data_block_t */ /** * struct block_range - Struct describing a range of blocks * @start: First block in range. * @end: Last block in range plus one. */ struct block_range { data_block_t start; data_block_t end; }; #define BLOCK_RANGE_INITIAL_VALUE(block_range) \ { 0, 0 } /** * block_range_empty - Check if block range is empty * @range: Block range to check. * * Return: %true if @range is empty, %false otherwise. */ static inline bool block_range_empty(const struct block_range range) { assert(range.end >= range.start); return range.start == range.end; } /* * block_in_range - Check if block is in range * @range: Block range to check. * @block: Block to check. * * Return: %true if @block is in @range, %false otherwise. */ static inline bool block_in_range(const struct block_range range, data_block_t block) { assert(range.end >= range.start); return (block >= range.start && block < range.end); } /** * block_in_range - Check if two block ranges have any overlap * @a: Block range to check. * @b: Block range to check. * * Return: %true if @a and @b share any blocks, %false otherwise. */ static inline bool block_range_overlap(const struct block_range a, const struct block_range b) { return block_in_range(a, b.start) || block_in_range(b, a.start); } /** * block_range_before - Check if a block range start before another block range * @a: Block range to check. * @b: Block range to check. * * Return: %true if @a starts at a lower block number than @b where the start * block number of an empty block range is considered infinite, %false * otherwise. */ static inline bool block_range_before(const struct block_range a, const struct block_range b) { return !block_range_empty(a) && (block_range_empty(b) || a.start < b.start); } /** * block_range_is_sub_range - Check if a block range is a subset of another * range * @range: Block range to check. * @sub_range: Block range to check. * * Return: %true if every block in @sub_range is also in @range, %false * otherwise. @sub_range is not allowed to be be empty. */ static inline bool block_range_is_sub_range( const struct block_range range, const struct block_range sub_range) { assert(!block_range_empty(sub_range)); return block_in_range(range, sub_range.start) && block_in_range(range, sub_range.end - 1); } /** * block_range_eq - Check if two block ranges are identical * @a: Block range to check. * @b: Block range to check. * * Return: %true if @a and @b are identical, %false otherwise. */ static inline bool block_range_eq(const struct block_range a, const struct block_range b) { assert(a.end >= a.start); assert(b.end >= b.start); return a.start == b.start && a.end == b.end; } /** * block_range_init_single - Initialize a block range containing a single block * @range: Block range object to initialize. * @block: Block that should be in @range. */ static inline void block_range_init_single(struct block_range* range, data_block_t block) { range->start = block; range->end = block + 1; } /** * block_range_clear - Remove all blocks from a block range * @range: Block range object to clear. */ static inline void block_range_clear(struct block_range* range) { range->start = 0; range->end = 0; }