blob: 118f7b60d38fc176bb1121533a14257f2d1aa0ec [file] [log] [blame]
// Copyright 2017 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.
#pragma once
#include <fbl/macros.h>
#include <fbl/mutex.h>
#include <lib/zx/vmo.h>
#include "vnode.h"
namespace fs {
// A file node backed by a range of bytes in a VMO.
//
// The file has a fixed size specified at creating time; it does not grow or
// shrink even when written into.
//
// This class is thread-safe.
class VmoFile : public Vnode {
public:
// Specifies the desired behavior when a client asks for the file's
// underlying VMO.
enum class VmoSharing {
// The VMO is not shared with the client.
NONE,
// The VMO handle is duplicated for each client.
//
// This is appropriate when it is okay for clients to access the entire
// contents of the VMO, possibly extending beyond the pages spanned by the file.
//
// This mode is significantly more efficient than |CLONE| and |CLONE_COW|
// and should be preferred when file spans the whole VMO or when the VMO's
// entire content is safe for clients to read.
DUPLICATE,
// The VMO range spanned by the file is cloned on demand, using copy-on-write
// semantics to isolate modifications of clients which open the file in
// a writable mode.
//
// This is appropriate when clients need to be restricted from accessing
// portions of the VMO outside of the range of the file and when file
// modifications by clients should not be visible to each other.
CLONE_COW,
};
// Creates a file node backed an VMO owned by the creator.
// The creator retains ownership of |unowned_vmo| which must outlive this object.
VmoFile(const zx::vmo& unowned_vmo,
size_t offset,
size_t length,
bool writable = false,
VmoSharing vmo_sharing = VmoSharing::DUPLICATE);
~VmoFile() override;
// The underlying VMO handle.
zx_handle_t vmo_handle() const { return vmo_handle_; }
// The offset of the start of the file within the VMO in bytes.
size_t offset() const { return offset_; }
// The length of the file in bytes.
size_t length() const { return length_; }
// True if the file is writable.
// If false, attempts to open the file for write will fail.
bool is_writable() const { return writable_; }
// The VMO sharing mode of the file.
VmoSharing vmo_sharing() const { return vmo_sharing_; }
// |Vnode| implementation:
zx_status_t ValidateFlags(uint32_t flags) final;
zx_status_t Getattr(vnattr_t* a) final;
zx_status_t Read(void* data, size_t length, size_t offset, size_t* out_actual) final;
zx_status_t Write(const void* data, size_t length, size_t offset, size_t* out_actual) final;
zx_status_t GetNodeInfo(uint32_t flags, fuchsia_io_NodeInfo* info) final;
bool IsDirectory() const final;
private:
zx_status_t AcquireVmo(zx_rights_t rights, zx::vmo* out_vmo, size_t* out_offset);
zx_status_t DuplicateVmo(zx_rights_t rights, zx::vmo* out_vmo, size_t* out_offset);
zx_status_t CloneVmo(zx_rights_t rights, zx::vmo* out_vmo, size_t* out_offset);
zx_handle_t const vmo_handle_;
size_t const offset_;
size_t const length_;
bool const writable_;
VmoSharing const vmo_sharing_;
fbl::Mutex mutex_;
// Clone of the portion of the VMO which contains the file's data.
// In |CLONE_COW| mode, this is shared among read-only clients.
zx::vmo shared_clone_ __TA_GUARDED(mutex_);
DISALLOW_COPY_ASSIGN_AND_MOVE(VmoFile);
};
} // namespace fs