blob: 69748a1bb8dbbc6a97157507fb4f16b5dc546665 [file] [log] [blame] [edit]
// Copyright 2020 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_MINFS_LAZY_READER_H_
#define SRC_STORAGE_MINFS_LAZY_READER_H_
#include <lib/zx/status.h>
#include <memory>
#include <vector>
#include <bitmap/rle-bitmap.h>
#include <fbl/algorithm.h>
#include <fs/transaction/buffered_operations_builder.h>
#include <fs/transaction/transaction_handler.h>
#include "src/storage/minfs/block_utils.h"
#include "src/storage/minfs/format.h"
#include "src/storage/minfs/writeback.h"
namespace minfs {
// LazyReader helps with lazily reading blocks in a file.
class LazyReader {
public:
LazyReader() = default;
LazyReader(const LazyReader&) = delete;
LazyReader& operator=(const LazyReader&) = delete;
// An interface for reading blocks. An instance is passed to the Read method.
class ReaderInterface {
public:
ReaderInterface() = default;
// Not copyable or movable.
ReaderInterface(ReaderInterface&) = delete;
ReaderInterface& operator=(ReaderInterface&) = delete;
virtual ~ReaderInterface() = default;
// Queue a read for |range| blocks. Returns the number of blocks enqueued. The remainder will be
// pased to a subsequent call.
[[nodiscard]] virtual zx::status<uint64_t> Enqueue(BlockRange range) = 0;
// Issues the queued reads and returns the result.
[[nodiscard]] virtual zx_status_t RunRequests() = 0;
virtual uint32_t BlockSize() const = 0;
};
// Reads |length| bytes at offset |offset| into the buffer (if it isn't already pressent) using
// the provided ReaderInterface. The actual reads will be blocks and so |range| will be aligned to
// the nearest block boundaries that encompass |range|.
[[nodiscard]] zx_status_t Read(ByteRange range, ReaderInterface* reader);
// Marks the given block range as loaded or not according to |set|.
void SetLoaded(BlockRange range, bool set);
private:
bitmap::RleBitmapBase<uint64_t> mapped_;
};
// An interface for mapping file blocks to device blocks.
class MapperInterface {
public:
MapperInterface() = default;
// Not copyable or movable.
MapperInterface(MapperInterface&) = delete;
MapperInterface& operator=(MapperInterface&) = delete;
virtual ~MapperInterface() = default;
// Maps from file block to device block.
[[nodiscard]] virtual zx::status<DeviceBlockRange> Map(BlockRange file_range) = 0;
// Same as Map, but if |allocated| is non-null, blocks should be allocated if necessary and
// |allocated| will be updated to indicate whether an allocation took place.
[[nodiscard]] virtual zx::status<DeviceBlockRange> MapForWrite(PendingWork* transaction,
BlockRange file_range,
bool* allocated) = 0;
};
// MappedFileReader is a reader that can be used with LazyReader to read files that are mapped with
// an instance of MapperInterface.
class MappedFileReader : public LazyReader::ReaderInterface {
public:
MappedFileReader(fs::TransactionHandler* handler, MapperInterface* mapper,
storage::BlockBuffer* buffer)
: handler_(*handler), mapper_(*mapper), buffer_(*buffer) {}
uint32_t BlockSize() const override { return buffer_.BlockSize(); }
zx::status<uint64_t> Enqueue(BlockRange range) override;
[[nodiscard]] zx_status_t RunRequests() override {
return handler_.RunRequests(builder_.TakeOperations());
}
MapperInterface& mapper() { return mapper_; }
private:
fs::TransactionHandler& handler_;
MapperInterface& mapper_;
storage::BlockBuffer& buffer_;
fs::BufferedOperationsBuilder builder_;
};
} // namespace minfs
#endif // SRC_STORAGE_MINFS_LAZY_READER_H_