blob: d19ae3a925a691d3145a75658624a53afda37426 [file] [log] [blame] [edit]
// Copyright 2021 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_F2FS_LIB_H_
#define SRC_STORAGE_F2FS_F2FS_LIB_H_
#include <safemath/checked_math.h>
namespace f2fs {
// Checkpoint
inline bool VerAfter(uint64_t a, uint64_t b) { return a > b; }
// CRC
inline uint32_t F2fsCalCrc32(uint32_t crc, void *buff, uint32_t len) {
unsigned char *p = static_cast<unsigned char *>(buff);
while (len-- > 0) {
crc ^= *p++;
for (int i = 0; i < 8; ++i)
crc = (crc >> 1) ^ ((crc & 1) ? kCrcPolyLe : 0);
}
return crc;
}
inline uint32_t F2fsCrc32(void *buff, uint32_t len) {
return F2fsCalCrc32(kF2fsSuperMagic, static_cast<unsigned char *>(buff), len);
}
inline bool F2fsCrcValid(uint32_t blk_crc, void *buff, uint32_t buff_size) {
return F2fsCrc32(buff, buff_size) == blk_crc;
}
// Bitmap operations
inline void SetBit(uint32_t nr, void *addr) {
uint8_t *bitmap = static_cast<uint8_t *>(addr);
uint32_t size_per_iter = kBitsPerByte;
uint32_t iter = nr / size_per_iter;
uint32_t offset_in_iter = nr % size_per_iter;
bitmap[iter] |= static_cast<uint8_t>(1U << offset_in_iter);
}
inline void ClearBit(uint32_t nr, void *addr) {
uint8_t *bitmap = static_cast<uint8_t *>(addr);
uint32_t size_per_iter = kBitsPerByte;
uint32_t iter = nr / size_per_iter;
uint32_t offset_in_iter = nr % size_per_iter;
bitmap[iter] &= ~static_cast<uint8_t>(1U << offset_in_iter);
}
inline bool TestBit(uint32_t nr, const void *addr) {
const uint8_t *bitmap = static_cast<const uint8_t *>(addr);
uint32_t size_per_iter = kBitsPerByte;
uint32_t iter = nr / size_per_iter;
uint32_t offset_in_iter = nr % size_per_iter;
bool ret = ((bitmap[iter] & static_cast<uint8_t>(1U << offset_in_iter)) != 0);
return ret;
}
inline uint32_t FindNextZeroBit(const void *addr, uint32_t size, uint32_t offset) {
const uint8_t *bitmap = static_cast<const uint8_t *>(addr);
uint32_t size_per_iter = kBitsPerByte;
while (offset < size) {
uint32_t iter = offset / size_per_iter;
uint32_t offset_in_iter = offset % size_per_iter;
uint8_t mask = static_cast<uint8_t>(~0U << offset_in_iter);
uint8_t res = bitmap[iter] & mask;
if (res != mask) { // found
for (; offset_in_iter < size_per_iter; ++offset_in_iter) {
if ((bitmap[iter] & static_cast<uint8_t>(1U << offset_in_iter)) == 0) {
return std::min(iter * size_per_iter + offset_in_iter, size);
}
}
}
offset = (iter + 1) * size_per_iter;
}
return size;
}
inline uint32_t FindNextBit(const void *addr, uint32_t size, uint32_t offset) {
const uint8_t *bitmap = static_cast<const uint8_t *>(addr);
uint32_t size_per_iter = kBitsPerByte;
while (offset < size) {
uint32_t iter = offset / size_per_iter;
uint32_t offset_in_iter = offset % size_per_iter;
uint8_t mask = static_cast<uint8_t>(~0U << offset_in_iter);
uint8_t res = bitmap[iter] & mask;
if (res != 0) { // found
for (; offset_in_iter < size_per_iter; ++offset_in_iter) {
if ((bitmap[iter] & static_cast<uint8_t>(1U << offset_in_iter)) != 0) {
return std::min(iter * size_per_iter + offset_in_iter, size);
}
}
}
offset = (iter + 1) * size_per_iter;
}
return size;
}
inline bool TestAndSetBit(uint32_t nr, void *addr) {
uint8_t *bitmap = static_cast<uint8_t *>(addr);
uint32_t size_per_iter = kBitsPerByte;
uint32_t iter = nr / size_per_iter;
uint32_t offset_in_iter = nr % size_per_iter;
bool ret = ((bitmap[iter] & static_cast<uint8_t>(1U << offset_in_iter)) != 0);
bitmap[iter] |= static_cast<uint8_t>(1U << offset_in_iter);
return ret;
}
inline bool TestAndClearBit(uint32_t nr, void *addr) {
uint8_t *bitmap = static_cast<uint8_t *>(addr);
uint32_t size_per_iter = kBitsPerByte;
uint32_t iter = nr / size_per_iter;
uint32_t offset_in_iter = nr % size_per_iter;
bool ret = ((bitmap[iter] & static_cast<uint8_t>(1U << offset_in_iter)) != 0);
bitmap[iter] &= ~static_cast<uint8_t>((1U << offset_in_iter));
return ret;
}
inline uint32_t CountBits(const void *addr, uint32_t offset, uint32_t len) {
uint32_t end = offset + len, sum = 0;
for (; offset < end; ++offset) {
if (TestBit(offset, addr)) {
++sum;
}
}
return sum;
}
inline bool IsDotOrDotDot(std::string_view name) { return (name == "." || name == ".."); }
template <typename T>
inline T CheckedDivRoundUp(const T n, const T d) {
return safemath::CheckDiv<T>(fbl::round_up(n, d), d).ValueOrDie();
}
inline size_t BitsToLongs(size_t nr) {
return CheckedDivRoundUp<size_t>(nr, kBitsPerByte * sizeof(long));
}
constexpr uint32_t kBlockSize = 4096; // F2fs block size in byte
template <typename T = uint8_t>
class FsBlock {
public:
FsBlock() { memset(data_, 0, kBlockSize); }
FsBlock(uint8_t (&block)[kBlockSize]) { std::memcpy(data_, block, kBlockSize); }
FsBlock(const FsBlock &block) = delete;
FsBlock &operator=(const FsBlock &block) = delete;
FsBlock &operator=(const uint8_t (&block)[kBlockSize]) {
std::memcpy(data_, block, kBlockSize);
return *this;
}
template <typename U = void>
U *get() {
return reinterpret_cast<U *>(data_);
}
T *operator->() { return get<T>(); }
T *operator&() { return get<T>(); }
T &operator*() { return *get<T>(); }
private:
uint64_t data_[kBlockSize / sizeof(uint64_t)];
};
} // namespace f2fs
#endif // SRC_STORAGE_F2FS_F2FS_LIB_H_