// Copyright 2018 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_SUPERBLOCK_H_
#define SRC_STORAGE_MINFS_SUPERBLOCK_H_

#include <cstdint>
#include <memory>

#include <fbl/macros.h>

#include "src/storage/minfs/format.h"
#include "src/storage/minfs/fsck.h"
#include "src/storage/minfs/minfs.h"
#include "src/storage/minfs/pending_work.h"

#ifdef __Fuchsia__
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/zx/vmo.h>

#include <block-client/cpp/block-device.h>
#endif

namespace minfs {

// SuperblockManager contains all filesystem-global metadata.
//
// It also contains mechanisms for updating this information
// on persistent storage. Although these fields may be
// updated from multiple threads (and |Write| may be invoked
// to push a snapshot of the superblock to persistent storage),
// caution should be taken to avoid Writing a snapshot of the
// superblock to disk while another thread has only partially
// updated the superblock.

#ifdef __Fuchsia__

class SuperblockManager {
 public:
  SuperblockManager() = delete;

  // Not copyable or movable
  SuperblockManager(const SuperblockManager&) = delete;
  SuperblockManager& operator=(const SuperblockManager&) = delete;
  SuperblockManager(SuperblockManager&&) = delete;
  SuperblockManager& operator=(SuperblockManager&&) = delete;

  ~SuperblockManager();

  static zx_status_t Create(block_client::BlockDevice* device, const Superblock* info,
                            uint32_t max_blocks, IntegrityCheck checks,
                            std::unique_ptr<SuperblockManager>* out);

  bool is_dirty() const { return dirty_; }

  const Superblock& Info() const { return *reinterpret_cast<const Superblock*>(mapping_.start()); }

  uint32_t BlockSize() const {
    // Either intentionally or unintenttionally, we do not want to change block
    // size to anything other than kMinfsBlockSize yet. This is because changing
    // block size might lead to format change and also because anything other
    // than 8k is not well tested. So assert when we find block size other
    // than 8k.
    ZX_ASSERT(Info().BlockSize() == kMinfsBlockSize);
    return Info().BlockSize();
  }
  // Acquire a pointer to the superblock, such that any
  // modifications will be carried out to persistent storage
  // the next time "Write" is invoked.
  Superblock* MutableInfo() {
    dirty_ = true;
    return reinterpret_cast<Superblock*>(mapping_.start());
  }

  // Write the superblock/backup superblock back to persistent storage at respective locations.
  // If write_backup is kUpdate, also update the backup superblock.
  void Write(PendingWork* transaction, UpdateBackupSuperblock write_backup);

 private:
  SuperblockManager(const Superblock* info, fzl::OwnedVmoMapper mapper);

  fzl::OwnedVmoMapper mapping_;
  bool dirty_ = false;
};

#else  // __Fuchsia__

class SuperblockManager {
 public:
  SuperblockManager() = delete;

  // Not copyable or movable
  SuperblockManager(const SuperblockManager&) = delete;
  SuperblockManager& operator=(const SuperblockManager&) = delete;
  SuperblockManager(SuperblockManager&&) = delete;
  SuperblockManager& operator=(SuperblockManager&&) = delete;

  ~SuperblockManager();

  static zx_status_t Create(const Superblock* info, uint32_t max_blocks, IntegrityCheck checks,
                            std::unique_ptr<SuperblockManager>* out);

  bool is_dirty() const { return dirty_; }

  const Superblock& Info() const { return *reinterpret_cast<const Superblock*>(&info_blk_[0]); }

  uint32_t BlockSize() const {
    // Either intentionally or unintenttionally, we do not want to change block
    // size to anything other than kMinfsBlockSize yet. This is because changing
    // block size might lead to format change and also because anything other
    // than 8k is not well tested. So assert when we find block size other
    // than 8k.
    ZX_ASSERT(Info().BlockSize() == kMinfsBlockSize);
    return Info().BlockSize();
  }
  // Acquire a pointer to the superblock, such that any
  // modifications will be carried out to persistent storage
  // the next time "Write" is invoked.
  Superblock* MutableInfo() {
    dirty_ = true;
    return reinterpret_cast<Superblock*>(&info_blk_[0]);
  }

  // Write the superblock/backup superblock back to persistent storage at respective locations.
  // If write_backup is kUpdate, also update the backup superblock.
  void Write(PendingWork* transaction, UpdateBackupSuperblock write_backup);

 private:
  SuperblockManager(const Superblock* info);

  uint8_t info_blk_[kMinfsBlockSize];
  bool dirty_ = false;
};

#endif

}  // namespace minfs

#endif  // SRC_STORAGE_MINFS_SUPERBLOCK_H_
