diskio

package
v0.15.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 16, 2026 License: Apache-2.0 Imports: 37 Imported by: 0

Documentation

Index

Constants

View Source
const OrphanMountSweepGracePeriod = 2 * time.Minute

OrphanMountSweepGracePeriod is how old a disk_mount must be before the orphan sweeper will delete it for a missing backing volume. It guards against a race where a mount has just been created but its volume entity hasn't been observed yet.

Variables

This section is empty.

Functions

func DeletedVolumesPath added in v0.7.0

func DeletedVolumesPath(dataPath string) string

DeletedVolumesPath returns the path to the deleted-volumes directory.

func EnsureLbdDevices

func EnsureLbdDevices(log *slog.Logger) error

EnsureLbdDevices checks if the lbd kernel module and lbdctl are available.

func EnsureLoopDevices

func EnsureLoopDevices(log *slog.Logger) error

EnsureLoopDevices ensures /dev/loop-control and loop device nodes are available. In containers, /dev may be a fresh mount that doesn't include loop devices even when the kernel supports them. This function creates the device nodes via mknod if they're missing.

func LoopDeviceAvailable

func LoopDeviceAvailable() bool

LoopDeviceAvailable checks if loop devices can be used.

func SaveDeletedVolumeMetadata added in v0.7.0

func SaveDeletedVolumeMetadata(dir string, meta *DeletedVolumeMetadata) error

SaveDeletedVolumeMetadata writes metadata to a JSON file inside the given directory.

Types

type ActiveMount

type ActiveMount struct {
	Device    string
	MountPath string
}

ActiveMount describes a mount found on the running system.

type CloudDiskClient

type CloudDiskClient interface {
	AcquireLease(ctx context.Context, volumeID string) (nonce string, err error)
	ReleaseLease(ctx context.Context, volumeID string, nonce string) error
	// ListLogSegments returns the volume's log segments whose TAI64N label
	// sorts after `after`. Passing the caller's replay horizon keeps the server
	// from walking, and returning, a volume's entire backup history. An empty
	// `after` asks for everything.
	ListLogSegments(ctx context.Context, volumeID string, after string) ([]LogSegmentInfo, error)
	DownloadLogSegment(ctx context.Context, volumeID, segmentID string) (io.ReadCloser, error)
}

CloudDiskClient abstracts the cloud operations needed by the mount controller for volume lease management and log segment retrieval.

func NewCloudDiskClient

func NewCloudDiskClient(log *slog.Logger, baseURL string, authClient *cloudauth.AuthClient) CloudDiskClient

NewCloudDiskClient creates a new CloudDiskClient.

func NewCloudDiskClientWithUpdates added in v0.14.0

func NewCloudDiskClientWithUpdates(log *slog.Logger, baseURL string, authClient *cloudauth.AuthClient, updates CloudUpdatesClient) CloudDiskClient

NewCloudDiskClientWithUpdates builds a disk client over an existing updates client, so callers that already have one need not construct a second.

type CloudSegmentUploader

type CloudSegmentUploader struct {
	// contains filtered or unexported fields
}

CloudSegmentUploader implements LogSegmentUploader by uploading lbd log segments to miren.cloud as lbd_log volume updates.

A segment's TAI64N label becomes the update's ordering key, which is what replay sorts and horizon-compares on.

func NewCloudSegmentUploader

func NewCloudSegmentUploader(log *slog.Logger, baseURL string, authClient *cloudauth.AuthClient, state *State) *CloudSegmentUploader

func NewCloudSegmentUploaderWithClient added in v0.14.0

func NewCloudSegmentUploaderWithClient(log *slog.Logger, updates CloudUpdatesClient, state *State) *CloudSegmentUploader

NewCloudSegmentUploaderWithClient builds an uploader over an existing updates client, so callers that already have one need not construct a second.

func (*CloudSegmentUploader) UploadSegment

func (u *CloudSegmentUploader) UploadSegment(ctx context.Context, volumeID, segmentPath string) (string, error)

UploadSegment uploads a log segment file to the cloud and returns the cloud segment ID.

type CloudUpdatesClient added in v0.14.0

type CloudUpdatesClient interface {
	// Upload sends one update and returns the cloud's ID for it. size must be
	// the exact byte length of body.
	Upload(ctx context.Context, volumeID string, req UploadRequest, body io.Reader, size int64) (string, error)

	// List returns a volume's active updates in replay order.
	List(ctx context.Context, volumeID string, opts ListOptions) ([]UpdateInfo, error)

	// Download opens an update's payload. The caller closes it.
	Download(ctx context.Context, volumeID, updateID string) (io.ReadCloser, error)
}

CloudUpdatesClient is the runtime's view of the cloud's volume update API.

func NewCloudUpdatesClient added in v0.14.0

func NewCloudUpdatesClient(log *slog.Logger, baseURL string, authClient *cloudauth.AuthClient) CloudUpdatesClient

NewCloudUpdatesClient creates a client for the cloud's volume update API.

type CloudVolumeRegistrar added in v0.14.0

type CloudVolumeRegistrar interface {
	// EnsureVolume registers the volume and returns its cloud identifier. It is
	// safe to call repeatedly: the same local volume always resolves to the
	// same cloud volume.
	EnsureVolume(ctx context.Context, req RegisterVolumeRequest) (string, error)
}

CloudVolumeRegistrar creates a volume in miren.cloud for a local disk, so the backup paths have something to address.

Without this a volume only exists on the node, and every cloud call carries a local id the cloud has never heard of.

func NewCloudVolumeRegistrar added in v0.14.0

func NewCloudVolumeRegistrar(log *slog.Logger, baseURL string, authClient *cloudauth.AuthClient) CloudVolumeRegistrar

NewCloudVolumeRegistrar creates a registrar against the given cloud.

type DeletedVolumeEntry added in v0.7.0

type DeletedVolumeEntry struct {
	Metadata *DeletedVolumeMetadata
	Path     string
}

DeletedVolumeEntry combines metadata with its directory path.

func ListDeletedVolumes added in v0.7.0

func ListDeletedVolumes(dataPath string) ([]DeletedVolumeEntry, error)

ListDeletedVolumes scans the deleted-volumes directory and returns all entries with valid metadata.

type DeletedVolumeGC added in v0.7.0

type DeletedVolumeGC struct {
	Log      *slog.Logger
	DataPath string
	Config   DeletedVolumeGCConfig
	// contains filtered or unexported fields
}

DeletedVolumeGC periodically purges soft-deleted disk volumes that have exceeded the retention period.

func (*DeletedVolumeGC) RunGC added in v0.7.0

RunGC scans the deleted-volumes directory and removes entries that have exceeded the retention period.

func (*DeletedVolumeGC) Start added in v0.7.0

func (g *DeletedVolumeGC) Start(ctx context.Context)

Start begins the periodic GC process.

func (*DeletedVolumeGC) Stop added in v0.7.0

func (g *DeletedVolumeGC) Stop()

Stop gracefully stops the controller.

type DeletedVolumeGCConfig added in v0.7.0

type DeletedVolumeGCConfig struct {
	CheckInterval time.Duration
	RetentionDays int
}

DeletedVolumeGCConfig holds configuration for deleted volume garbage collection.

func DefaultDeletedVolumeGCConfig added in v0.7.0

func DefaultDeletedVolumeGCConfig() DeletedVolumeGCConfig

DefaultDeletedVolumeGCConfig returns the default GC configuration.

type DeletedVolumeGCResult added in v0.7.0

type DeletedVolumeGCResult struct {
	Purged   int
	Retained int
	Errors   int
}

DeletedVolumeGCResult contains information about volumes processed during GC.

type DeletedVolumeMetadata added in v0.7.0

type DeletedVolumeMetadata struct {
	DiskID     string         `json:"disk_id"`
	DiskName   string         `json:"disk_name"`
	SizeGb     int64          `json:"size_gb"`
	Filesystem string         `json:"filesystem"`
	VolumeID   string         `json:"volume_id"`
	VolumeMode string         `json:"volume_mode"`
	CreatedBy  string         `json:"created_by,omitempty"`
	NodeID     compute.NodeId `json:"node_id"`
	DeletedAt  time.Time      `json:"deleted_at"`
}

DeletedVolumeMetadata stores information about a soft-deleted disk volume so it can be restored via the undelete command.

func LoadDeletedVolumeMetadata added in v0.7.0

func LoadDeletedVolumeMetadata(dir string) (*DeletedVolumeMetadata, error)

LoadDeletedVolumeMetadata reads metadata from a JSON file inside the given directory.

type DiskMountController

type DiskMountController struct {
	// contains filtered or unexported fields
}

DiskMountController watches disk_mount entities and manages loop-device mounts.

func NewDiskMountController

func NewDiskMountController(log *slog.Logger, dataPath string, nodeId compute.NodeId, state *State, ops DiskMountOps) *DiskMountController

func (*DiskMountController) Index

func (c *DiskMountController) Index() entity.Attr

func (*DiskMountController) Init

func (*DiskMountController) Reconcile

func (c *DiskMountController) Reconcile(ctx context.Context, mount *storage_v1alpha.DiskMount, meta *entity.Meta) error

func (*DiskMountController) ReconcileOrphanMounts added in v0.12.0

func (c *DiskMountController) ReconcileOrphanMounts(ctx context.Context, minMountAge time.Duration) error

ReconcileOrphanMounts deletes disk_mount entities on this node whose backing disk_volume no longer exists. Such a mount can never reach its desired state and, before writes are deduped, self-retriggers reconcile indefinitely (MIR-1345). Deleting the entity via the entity server also removes its secondary-index keys, which a raw etcd delete would leave dangling.

minMountAge guards against deleting a just-created mount whose volume entity hasn't been observed yet; pass OrphanMountSweepGracePeriod in production.

func (*DiskMountController) ReconcileWithEntities

func (c *DiskMountController) ReconcileWithEntities(ctx context.Context) error

ReconcileWithEntities reconciles local state with entity server

func (*DiskMountController) RestoreImageIfMissing added in v0.14.0

func (c *DiskMountController) RestoreImageIfMissing(ctx context.Context, volState *VolumeState, imagePath string) error

RestoreImageIfMissing rebuilds a universal-mode volume's backing image from the newest loop_image snapshot in the cloud, when the host no longer has one.

Universal volumes are mounted by the volume controller rather than the mount controller, so this wrapper exists for the accelerator-shaped path and for callers that already hold a mount controller; the volume controller has its own.

func (*DiskMountController) SetCloudClient

func (c *DiskMountController) SetCloudClient(client CloudDiskClient)

SetCloudClient sets the cloud client for lease management and segment replay.

func (*DiskMountController) SetEAC

func (*DiskMountController) SetKeepMounts

func (c *DiskMountController) SetKeepMounts(v bool)

SetKeepMounts tells the controller to skip unmounting during Shutdown. Used during reload so the replacement process inherits the mounts.

func (*DiskMountController) SetUpdatesClient added in v0.14.0

func (c *DiskMountController) SetUpdatesClient(client CloudUpdatesClient)

SetUpdatesClient wires the generic volume update client, used to recover a universal-mode volume's backing image from the cloud.

func (*DiskMountController) SetWriteTracker added in v0.12.0

func (c *DiskMountController) SetWriteTracker(wt writeTracker)

SetWriteTracker wires the reconcile controller's write tracker so that entity writes this controller makes directly (via updateMountState) are recorded and their watch events are skipped, preventing a self-retriggering reconcile loop.

func (*DiskMountController) Shutdown

func (c *DiskMountController) Shutdown()

Shutdown releases cloud leases. Mount/detach cleanup is handled by DiskVolumeController.Shutdown which owns all mount lifecycle. If keepMounts is set (reload), everything is skipped.

type DiskMountOps

type DiskMountOps interface {
	CreateDir(path string, perm os.FileMode) error
	LoopAttach(imagePath string) (devicePath string, err error)
	LoopDetach(devicePath string) error
	// FindLoopByBacking returns the loop device path (e.g. /dev/loop3) currently
	// backing the given image file, or "" if no loop device is attached to it.
	// Used to detect stale/double attachments of the same disk image.
	FindLoopByBacking(imagePath string) (devicePath string, err error)
	// FindAllLoopBackings returns a map of loop device path to the backing
	// file currently attached to it, for every loop device in the kernel.
	// Used by boot-time orphan reconciliation to find stale attachments.
	FindAllLoopBackings() (map[string]string, error)
	LbdAttach(ctx context.Context, imagePath, logDir string) (devicePath string, err error)
	LbdDetach(ctx context.Context, devicePath string) error
	Mount(device, mountPath, filesystem string, readOnly bool) error
	Unmount(path string) error
	IsMounted(path string) bool
	// IsDeviceMounted reports whether device is currently mounted at any
	// path in the kernel mount table. Used as a safety check before
	// running fsck, which must never run against a live filesystem.
	// Returns an error if the mount table cannot be read — callers must
	// treat that as "unknown" and refuse the destructive operation they
	// were gating on this check.
	IsDeviceMounted(device string) (bool, error)
	IsFormatted(ctx context.Context, device, filesystem string) (bool, error)
	FormatDevice(ctx context.Context, device, filesystem string) error
	// Fsck runs a filesystem check-and-repair on device. The device must
	// not be mounted anywhere when this is called. Used to recover from
	// EUCLEAN ("Structure needs cleaning") mount failures after an
	// unclean shutdown.
	Fsck(ctx context.Context, device, filesystem string) error

	// FindMounts returns all mounts whose mount path starts with the given prefix.
	FindMounts(pathPrefix string) []ActiveMount
}

DiskMountOps abstracts OS operations for disk mount management. This interface enables testing without requiring actual loop device or mount operations.

func NewRealDiskMountOps

func NewRealDiskMountOps(log *slog.Logger) DiskMountOps

type DiskVolumeController

type DiskVolumeController struct {
	// contains filtered or unexported fields
}

DiskVolumeController watches disk_volume entities and manages sparse disk images using loop devices.

func NewDiskVolumeController

func NewDiskVolumeController(log *slog.Logger, dataPath string, nodeId compute.NodeId, state *State, ops DiskVolumeOps, mntOps DiskMountOps) *DiskVolumeController

func (*DiskVolumeController) Index

func (c *DiskVolumeController) Index() entity.Attr

func (*DiskVolumeController) Init

func (*DiskVolumeController) Reconcile

func (c *DiskVolumeController) Reconcile(ctx context.Context, volume *storage_v1alpha.DiskVolume, meta *entity.Meta) error

func (*DiskVolumeController) ReconcileWithEntities

func (c *DiskVolumeController) ReconcileWithEntities(ctx context.Context) error

ReconcileWithEntities reconciles local state with entity server

func (*DiskVolumeController) SetCloudVolumeRegistrar added in v0.14.0

func (c *DiskVolumeController) SetCloudVolumeRegistrar(registrar CloudVolumeRegistrar, clusterID string)

SetCloudVolumeRegistrar wires cloud registration. Without it, volumes are created locally and never appear in miren.cloud.

func (*DiskVolumeController) SetEAC

func (*DiskVolumeController) SetKeepMounts

func (c *DiskVolumeController) SetKeepMounts(v bool)

SetKeepMounts tells the controller to skip unmounting during Shutdown. Used during reload so the replacement process inherits the mounts.

func (*DiskVolumeController) SetUpdatesClient added in v0.14.0

func (c *DiskVolumeController) SetUpdatesClient(client CloudUpdatesClient)

SetUpdatesClient wires the client used to restore a missing backing image.

func (*DiskVolumeController) Shutdown

func (c *DiskVolumeController) Shutdown()

Shutdown unmounts all disk volumes and detaches their backing devices. It uses the actual kernel mount table rather than trusting persisted state, finding all mounts under diskMountBasePath and tearing them down. If keepMounts is set (reload), everything is left in place for the new process.

type DiskVolumeOps

type DiskVolumeOps interface {
	CreateVolumeDir(path string) error
	RemoveVolumeDir(path string) error
	MoveVolumeDir(src, dst string) error
	VolumePathExists(path string) bool
	CreateDiskImage(path string, sizeBytes int64) error
}

DiskVolumeOps abstracts OS operations for disk volume management. This interface enables testing without requiring actual filesystem operations.

func NewRealDiskVolumeOps

func NewRealDiskVolumeOps(log *slog.Logger) DiskVolumeOps

type ImageSnapshotter added in v0.14.0

type ImageSnapshotter struct {
	// contains filtered or unexported fields
}

ImageSnapshotter uploads a compressed snapshot of a universal-mode volume's backing image to the cloud as a loop_image update.

This is deliberately on demand only. Snapshotting a mounted, actively-written image means reading a file while its single writer -- the loop device -- keeps changing it, so the head and tail of the read come from different moments. The result is not crash-consistent; it is a state that never existed on the disk at any instant, which a journalling filesystem and Postgres's WAL are both entitled to be confused by. Taking that automatically on a timer and filing the result as a restore point would be worse than not backing up at all, because it looks like protection.

So the decision that it is safe -- the disk is idle, or unmounted, or the operator accepts the risk -- belongs to a person, not a ticker. Accelerator mode is the answer for continuous backup: lbd captures writes in order inside the kernel, so its log segments cannot smear.

func NewImageSnapshotter added in v0.14.0

func NewImageSnapshotter(log *slog.Logger, updates CloudUpdatesClient) *ImageSnapshotter

NewImageSnapshotter creates a snapshotter over the given updates client.

func (*ImageSnapshotter) Snapshot added in v0.14.0

func (s *ImageSnapshotter) Snapshot(ctx context.Context, req SnapshotRequest) (string, error)

Snapshot compresses the image and uploads it, returning the cloud's update ID.

type ListOptions added in v0.14.0

type ListOptions struct {
	Kind  UpdateKind
	After string
	Until string

	// Descending returns newest first instead of replay order. Paired with
	// Limit 1 it answers "what is the most recent update" in one round trip,
	// rather than paging a volume's whole history to keep the last row.
	Descending bool

	// Limit caps how many updates come back. Zero walks every page, which is
	// what replay wants; a positive value stops as soon as it has enough.
	Limit int
}

ListOptions filters a volume's update stream.

After is exclusive and must be paired with a Kind: ordering keys are only comparable within one kind, so the cloud refuses the pair otherwise.

type LogSegmentInfo

type LogSegmentInfo struct {
	SegmentID string
	Label     string
}

LogSegmentInfo describes a remote log segment with its cloud ID and TAI64N label.

type LogSegmentUploader

type LogSegmentUploader interface {
	// UploadSegment uploads a log segment and returns the cloud segment ID.
	UploadSegment(ctx context.Context, volumeID, segmentPath string) (segmentID string, err error)
}

LogSegmentUploader uploads completed log segments to cloud storage.

type LogWatcher

type LogWatcher struct {
	// contains filtered or unexported fields
}

LogWatcher monitors accelerator volume log directories for completed segments. When an uploader is configured, segments are uploaded then removed. When no uploader is configured (cloud not available), segments are simply deleted.

func NewLogWatcher

func NewLogWatcher(log *slog.Logger, state *State, uploader LogSegmentUploader, interval time.Duration) *LogWatcher

NewLogWatcher creates a new LogWatcher that scans at the given interval. Pass nil for uploader to just delete logs without uploading.

func (*LogWatcher) Run

func (w *LogWatcher) Run(ctx context.Context) error

Run starts the log watcher loop. It blocks until the context is cancelled.

func (*LogWatcher) Wait

func (w *LogWatcher) Wait()

Wait blocks until the watcher's Run method has returned.

type MountState

type MountState struct {
	// EntityId is the ID of the disk_mount entity
	EntityId string `json:"entity_id"`

	// VolumeId is the ID of the disk_volume entity
	VolumeId string `json:"volume_id"`

	// CloudVolumeId is the backing volume's miren.cloud identifier, captured
	// when the mount is created. Every cloud lease call keys off it, and
	// recording it here means lease release still works after the volume's
	// VolumeState is gone (e.g. orphan cleanup). Empty for mounts persisted
	// before this field existed, or volumes never registered with the cloud.
	CloudVolumeId string `json:"cloud_volume_id,omitempty"`

	// DevicePath is the path to the loop device node
	DevicePath string `json:"device_path"`

	// MountPath is where the volume is mounted
	MountPath string `json:"mount_path"`

	// Mounted indicates if the volume is currently mounted
	Mounted bool `json:"mounted"`

	// ReadOnly indicates if the mount is read-only
	ReadOnly bool `json:"read_only"`

	// Mode is the disk I/O mode used for this mount (universal or accelerator)
	Mode storage_v1alpha.DiskVolumeVolumeMode `json:"mode,omitempty"`

	// LeaseNonce is the volume lease nonce from remote Disk API
	LeaseNonce string `json:"lease_nonce,omitempty"`
}

MountState represents the state of a disk mount

type RegisterVolumeRequest added in v0.14.0

type RegisterVolumeRequest struct {
	// LocalVolumeID is the node's identifier for the volume. It seeds the
	// cloud volume's name and UUID, which is what makes registration
	// idempotent across retries.
	LocalVolumeID string
	// ClusterID scopes the name, so two clusters in one organization that each
	// hold a disk called "data" do not land on the same cloud volume and
	// interleave their backups.
	ClusterID string
	// DisplayName is the operator-facing disk name, recorded as metadata.
	DisplayName string
	SizeBytes   int64
	Filesystem  string
}

RegisterVolumeRequest describes a local volume to register.

type SnapshotRequest added in v0.14.0

type SnapshotRequest struct {
	// VolumeID is the cloud volume the update belongs to.
	VolumeID string
	// ImagePath is the backing file to snapshot.
	ImagePath string
	// Name and Filesystem are recorded in the snapshot header so a restore
	// knows what it is rebuilding.
	Name       string
	Filesystem string
	// SnapshotName optionally pins this as a named restore point.
	SnapshotName string
	// LeaseNonce is required when the volume has an active lease.
	LeaseNonce string
	// StagingDir is where the compressed snapshot is written before upload.
	// Defaults to the image's own directory.
	StagingDir string
}

SnapshotRequest describes one image to snapshot and upload.

type State

type State struct {
	Volumes map[string]*VolumeState `json:"volumes"`
	Mounts  map[string]*MountState  `json:"mounts"`
	// contains filtered or unexported fields
}

State represents the persisted state of disk volumes and mounts

func LoadState

func LoadState(dataPath string) (*State, error)

LoadState loads state from the data path.

func NewState

func NewState() *State

NewState creates a new empty state

func (*State) DeleteMount

func (s *State) DeleteMount(entityId string)

DeleteMount removes a mount state

func (*State) DeleteMountAndSave

func (s *State) DeleteMountAndSave(entityId string) error

DeleteMountAndSave atomically removes a mount state and persists to disk.

func (*State) DeleteVolume

func (s *State) DeleteVolume(entityId string)

DeleteVolume removes a volume state

func (*State) DeleteVolumeAndSave

func (s *State) DeleteVolumeAndSave(entityId string) error

DeleteVolumeAndSave atomically removes a volume state and persists to disk.

func (*State) GetMount

func (s *State) GetMount(entityId string) *MountState

GetMount returns a copy of a mount state by entity ID

func (*State) GetVolume

func (s *State) GetVolume(entityId string) *VolumeState

GetVolume returns a copy of a volume state by entity ID

func (*State) GetVolumeByVolumeId

func (s *State) GetVolumeByVolumeId(volumeId string) *VolumeState

GetVolumeByVolumeId returns a copy of a volume state by volume ID

func (*State) LeaseNonceForCloudVolume added in v0.14.0

func (s *State) LeaseNonceForCloudVolume(cloudVolumeId string) string

LeaseNonceForCloudVolume returns the lease nonce held by a mount whose backing volume has the given cloud volume id, or "" if none is held.

The uploader is handed a volume's cloud id, but mount state keys off the local disk_volume entity id, so the two cannot be compared directly. This resolves cloud id -> volume entity id -> mount under a single read lock.

func (*State) ListMounts

func (s *State) ListMounts() []*MountState

ListMounts returns copies of all mount states

func (*State) ListVolumes

func (s *State) ListVolumes() []*VolumeState

ListVolumes returns copies of all volume states

func (*State) Save

func (s *State) Save() error

Save persists the state to disk atomically. Callers that need to mutate and save atomically should use the combined methods (SetVolumeAndSave, SetMountAndSave, etc.) instead.

func (*State) SetCloudVolumeId added in v0.14.0

func (s *State) SetCloudVolumeId(entityId, cloudVolumeId string) error

SetCloudVolumeId records a volume's miren.cloud identifier and persists it. It mutates the stored volume in place under the lock rather than taking a whole VolumeState, so it cannot clobber mount fields another path set while the caller was talking to the cloud.

func (*State) SetMount

func (s *State) SetMount(entityId string, mount *MountState)

SetMount sets a mount state

func (*State) SetMountAndSave

func (s *State) SetMountAndSave(entityId string, mount *MountState) error

SetMountAndSave atomically sets a mount state and persists to disk.

func (*State) SetMountFromVolume

func (s *State) SetMountFromVolume(volumeId string, mount *MountState) (devicePath, mountPath string, err error)

SetMountFromVolume atomically reads the current volume state and, if the volume is mounted, creates a mount entry using the volume's live device and mount paths. This avoids a TOCTOU race where the volume controller could update mount fields between a GetVolume call and a SetMount call. Returns the volume's DevicePath and MountPath on success, or an error if the volume is not found or not mounted.

func (*State) SetPath

func (s *State) SetPath(dataPath string)

SetPath sets the path for the state file

func (*State) SetVolume

func (s *State) SetVolume(entityId string, volume *VolumeState)

SetVolume sets a volume state

func (*State) SetVolumeAndSave

func (s *State) SetVolumeAndSave(entityId string, volume *VolumeState) error

SetVolumeAndSave atomically sets a volume state and persists to disk.

type UpdateInfo added in v0.14.0

type UpdateInfo struct {
	UpdateID     string `json:"update_id"`
	Kind         string `json:"kind"`
	OrderingKey  string `json:"ordering_key"`
	EndKey       string `json:"end_key,omitempty"`
	Size         int64  `json:"size"`
	SnapshotName string `json:"snapshot_name,omitempty"`
}

UpdateInfo describes one update the cloud is holding.

type UpdateKind added in v0.14.0

type UpdateKind string

UpdateKind names a producer format in the cloud's volume update stream.

Every kind shares the same transport and the same ordering model: each update carries an ordering key that sorts lexicographically against its siblings of the same kind. What differs is the shape of that key.

const (
	// KindLBDLog is a log segment written by the lbd kernel module in
	// accelerator mode. Its ordering key is the TAI64N label from the segment
	// filename, disk.<label>.log.
	KindLBDLog UpdateKind = "lbd_log"

	// KindLoopImage is a compressed snapshot of a universal-mode volume's
	// backing image. Its ordering key is a zero-padded 16-hex snapshot
	// sequence.
	KindLoopImage UpdateKind = "loop_image"
)

type UploadRequest added in v0.14.0

type UploadRequest struct {
	Kind        UpdateKind
	OrderingKey string
	// EndKey bounds range-valued kinds. Neither kind here uses it; the cloud
	// rejects it for lbd_log and loop_image.
	EndKey string
	// SnapshotName names a restore point, pinning the update against cleanup.
	// It must be unique per volume among live updates.
	SnapshotName string
	// Metadata is kind-specific payload detail. The cloud writes it to a
	// sidecar object beside the payload rather than indexing it.
	Metadata map[string]any
	// LeaseNonce is required when the volume has an active lease.
	LeaseNonce string
}

UploadRequest describes one update to be uploaded.

type VolumeState

type VolumeState struct {
	// EntityId is the ID of the disk_volume entity
	EntityId string `json:"entity_id"`

	// VolumeId is the local volume identifier. It names the mount point, so it
	// is deliberately not the cloud's id: repointing it would relocate a live
	// mount out from under whatever is using it.
	VolumeId string `json:"volume_id"`

	// CloudVolumeId is this volume's identifier in miren.cloud, empty until it
	// has been registered there. Every cloud call keys off it, so empty means
	// "not backed up yet" rather than "fall back to the local id", which the
	// cloud would only reject.
	CloudVolumeId string `json:"cloud_volume_id,omitempty"`

	// Name is the human-readable name (from parent disk)
	Name string `json:"name,omitempty"`

	// DiskPath is the path to the volume data directory
	DiskPath string `json:"disk_path"`

	// SizeBytes is the volume size
	SizeBytes int64 `json:"size_bytes"`

	// Filesystem type (ext4, xfs, btrfs)
	Filesystem string `json:"filesystem"`

	// RemoteOnly indicates if this uses only remote storage
	RemoteOnly bool `json:"remote_only"`

	// Mode is the disk I/O mode (universal or accelerator)
	Mode storage_v1alpha.DiskVolumeVolumeMode `json:"mode,omitempty"`

	// DevicePath is the loop device backing this volume (alwaysMount modes only)
	DevicePath string `json:"device_path,omitempty"`

	// MountPath is where the volume is mounted (alwaysMount modes only)
	MountPath string `json:"mount_path,omitempty"`

	// Mounted indicates if the volume is currently mounted (alwaysMount modes only)
	Mounted bool `json:"mounted,omitempty"`
}

VolumeState represents the state of a disk volume

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL