blob: 63805ead7faa753723121479a84c8df3faa1170a [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_STORAGE_F2FS_BITMAP_H_
#define SRC_STORAGE_F2FS_BITMAP_H_
#include <limits.h>
#include <stddef.h>
#include <zircon/types.h>
#include <bitmap/raw-bitmap.h>
#include <bitmap/storage.h>
#include <fbl/macros.h>
#include <fbl/ref_ptr.h>
#include <safemath/checked_math.h>
#include "src/storage/f2fs/common.h"
namespace f2fs {
constexpr size_t kLastNodeMask = 0x7;
using RawBitmap = bitmap::RawBitmapGeneric<bitmap::VmoStorage>;
using RawBitmapHeap = bitmap::RawBitmapGeneric<bitmap::DefaultStorage>;
class Page;
class PageBitmap {
public:
PageBitmap() = delete;
PageBitmap(const PageBitmap &bits) = delete;
PageBitmap &operator=(const PageBitmap &bits) = delete;
PageBitmap &operator=(PageBitmap &&bits) = delete;
PageBitmap(fbl::RefPtr<Page> page, void *bitmap, size_t size);
PageBitmap(void *bitmap, size_t size);
PageBitmap(PageBitmap &&bits) = default;
bool Set(size_t pos);
bool Clear(size_t pos);
bool Test(size_t pos) const;
size_t GetSize() const;
size_t FindNextZeroBit(size_t pos) const { return FindNextZeroBit(pos, size_); }
size_t FindNextZeroBit(size_t pos, size_t max_pos) const;
size_t FindNextBit(size_t pos) const { return FindNextBit(pos, size_); }
size_t FindNextBit(size_t pos, size_t max_pos) const;
private:
uint8_t &GetNode(size_t pos) { return bits_[pos >> kShiftForBitSize]; }
const uint8_t &GetNode(size_t pos) const { return bits_[pos >> kShiftForBitSize]; }
fbl::RefPtr<Page> page_;
uint8_t *const bits_ = nullptr;
const size_t size_ = 0;
};
template <typename T = uint8_t>
inline T GetMask(const T value, const size_t offset) {
return static_cast<T>(value << offset);
}
inline size_t GetBitSize(size_t size_in_byte) {
return safemath::CheckLsh(size_in_byte, kShiftForBitSize).ValueOrDie();
}
inline size_t GetByteSize(size_t num_bits) {
return CheckedDivRoundUp<size_t>(num_bits, kBitsPerByte);
}
inline size_t ToMsbFirst(size_t offset) {
size_t index_in_last_node = offset & kLastNodeMask;
return offset + 7 - 2 * index_in_last_node;
}
// It copies bits from [0, len) of |src| to [offset, offset + len) of |dst|.
// |offset| + |len| and |len| must be multiples of 8.
inline zx_status_t bitcpy(uint8_t *dst, const uint8_t *src, size_t offset, size_t len) {
size_t end = offset + len;
size_t start_in_byte = offset / kBitsPerByte;
size_t end_in_byte = GetByteSize(end);
if (offset & kLastNodeMask || end & kLastNodeMask || end_in_byte <= start_in_byte) {
return ZX_ERR_INVALID_ARGS;
}
memcpy(dst + start_in_byte, src, end_in_byte - start_in_byte);
return ZX_OK;
}
template <typename T = RawBitmap>
inline zx_status_t CloneBits(T &to, const T &from, size_t offset, size_t len) {
if (to.size() < offset + len || from.size() < len) {
return ZX_ERR_INVALID_ARGS;
}
uint8_t *dst = static_cast<uint8_t *>(to.StorageUnsafe()->GetData());
const uint8_t *src = static_cast<const uint8_t *>(from.StorageUnsafe()->GetData());
bitcpy(dst, src, offset, len);
return ZX_OK;
}
template <typename T = RawBitmap>
inline zx_status_t CloneBits(T &to, const void *from, size_t offset, size_t len) {
if (to.size() < offset + len) {
return ZX_ERR_INVALID_ARGS;
}
uint8_t *dst = static_cast<uint8_t *>(to.StorageUnsafe()->GetData());
const uint8_t *src = static_cast<const uint8_t *>(from);
bitcpy(dst, src, offset, len);
return ZX_OK;
}
template <typename T = RawBitmap>
inline zx_status_t CloneBits(void *to, const T &from, size_t offset, size_t len) {
if (from.size() < len) {
return ZX_ERR_INVALID_ARGS;
}
uint8_t *dst = static_cast<uint8_t *>(to);
const uint8_t *src = static_cast<const uint8_t *>(from.StorageUnsafe()->GetData());
bitcpy(dst, src, offset, len);
return ZX_OK;
}
size_t CountBits(const RawBitmap &bits, size_t offset, size_t len);
} // namespace f2fs
#endif // SRC_STORAGE_F2FS_BITMAP_H_