// Copyright 2022 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.

#include "src/storage/f2fs/f2fs.h"

namespace f2fs {

Writer::Writer(BcacheMapper *bcache_mapper, size_t capacity) : bcache_mapper_(bcache_mapper) {
  write_buffer_ =
      std::make_unique<StorageBuffer>(bcache_mapper, capacity, kBlockSize, "WriteBuffer");
}

Writer::~Writer() {
  sync_completion_t completion;
  ScheduleWriteBlocks(&completion);
  ZX_ASSERT(sync_completion_wait(&completion, ZX_TIME_INFINITE) == ZX_OK);
  executor_.Terminate();
  writeback_executor_.Terminate();
}

StorageOperations Writer::MakeStorageOperations(PageList &to_submit) {
  {
    std::lock_guard lock(mutex_);
    while (!pages_.is_empty()) {
      auto page = pages_.pop_front();
      auto num_pages_or = write_buffer_->ReserveWriteOperation(*page);
      if (num_pages_or.is_error()) {
        if (num_pages_or.status_value() == ZX_ERR_UNAVAILABLE) {
          // No available buffers. Need to submit pending StorageOperations to free buffers.
          pages_.push_front(std::move(page));
          break;
        }
        // If |page| has an invalid addr, just drop it.
        to_submit.push_back(std::move(page));
      } else {
        to_submit.push_back(std::move(page));
        if (num_pages_or.value() >= kDefaultBlocksPerSegment) {
          // Merged enough StorageOperations. Submit it.
          break;
        }
      }
    }
  }
  return write_buffer_->TakeWriteOperations();
}

fpromise::promise<> Writer::GetTaskForWriteIO(sync_completion_t *completion) {
  return fpromise::make_promise([this, completion]() mutable {
    while (true) {
      PageList pages;
      auto operations = MakeStorageOperations(pages);
      if (operations.IsEmpty()) {
        break;
      }
      // No need to release vmo buffers of |operations| in the same order they are reserved in
      // StorageBuffer.
      zx_status_t io_status = bcache_mapper_->RunRequests(operations.TakeOperations());
      if (auto ret = operations.Completion(
              io_status,
              [pages = std::move(pages)](const StorageOperations &operation,
                                         zx_status_t io_status) mutable {
                while (!pages.is_empty()) {
                  auto page = pages.pop_front();
                  if (io_status != ZX_OK) {
                    LockedPage locked_page(page);
                    if (locked_page->IsUptodate()) {
                      if (locked_page->GetVnode().IsMeta() || io_status == ZX_ERR_UNAVAILABLE ||
                          io_status == ZX_ERR_PEER_CLOSED) {
                        // When it fails to write metadata or the block device is not available,
                        // set kCpErrorFlag to enter read-only mode.
                        locked_page->fs()->GetSuperblockInfo().SetCpFlags(CpFlag::kCpErrorFlag);
                      } else {
                        // When IO errors occur with node and data Pages, just set a dirty flag
                        // to retry it with another LBA.
                        locked_page.SetDirty();
                      }
                    }
                  }
                  page->ClearSync();
                  page->ClearCommit();
                  page->ClearColdData();
                  page->ClearWriteback();
                }
              });
          ret != ZX_OK) {
        FX_LOGS(WARNING) << "failed to write blocks. " << zx_status_get_string(ret);
      }
    }
    if (completion) {
      sync_completion_signal(completion);
    }
    return fpromise::ok();
  });
}

void Writer::ScheduleTask(fpromise::promise<> task) {
  executor_.schedule_task(sequencer_.wrap(std::move(task)));
}

void Writer::ScheduleWriteback(fpromise::promise<> task) {
  writeback_executor_.schedule_task(std::move(task));
}

void Writer::ScheduleWriteBlocks(sync_completion_t *completion, PageList pages, bool flush) {
  if (!pages.is_empty()) {
    std::lock_guard lock(mutex_);
    pages_.splice(pages_.end(), pages);
  }
  if (flush || completion) {
    auto task = GetTaskForWriteIO(completion);
    ScheduleTask(std::move(task));
  }
}

}  // namespace f2fs
