You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

346 lines
12 KiB

/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_INCREMENTAL_FILE_SYSTEM_NDK_H
#define ANDROID_INCREMENTAL_FILE_SYSTEM_NDK_H
#include <linux/incrementalfs.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
#define INCFS_LIBRARY_NAME "libincfs.so"
typedef struct {
union {
char data[16];
int64_t for_alignment;
};
} IncFsFileId;
static const IncFsFileId kIncFsInvalidFileId = {
{{(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1}}};
static const int kIncFsFileIdStringLength = sizeof(IncFsFileId) * 2;
typedef enum {
INCFS_FEATURE_NONE = 0,
INCFS_FEATURE_CORE = 1,
INCFS_FEATURE_V2 = 2,
} IncFsFeatures;
typedef int IncFsErrorCode;
typedef int64_t IncFsSize;
typedef int32_t IncFsBlockIndex;
typedef int IncFsFd;
typedef struct IncFsControl IncFsControl;
typedef int IncFsUid;
static const IncFsUid kIncFsNoUid = -1;
typedef struct {
const char* data;
IncFsSize size;
} IncFsSpan;
typedef enum {
CMD,
PENDING_READS,
LOGS,
BLOCKS_WRITTEN,
FDS_COUNT,
} IncFsFdType;
typedef enum {
INCFS_DEFAULT_READ_TIMEOUT_MS = 10000,
INCFS_DEFAULT_PENDING_READ_BUFFER_SIZE = 24,
INCFS_DEFAULT_PAGE_READ_BUFFER_PAGES = 4,
} IncFsDefaults;
typedef enum {
INCFS_MOUNT_CREATE_ONLY = 1,
INCFS_MOUNT_TRUNCATE = 2,
} IncFsMountFlags;
typedef enum {
INCFS_HASH_NONE,
INCFS_HASH_SHA256,
} IncFsHashAlgortithm;
typedef struct {
IncFsMountFlags flags;
int32_t defaultReadTimeoutMs;
int32_t readLogBufferPages;
int32_t readLogDisableAfterTimeoutMs;
const char* sysfsName;
} IncFsMountOptions;
typedef enum {
INCFS_COMPRESSION_KIND_NONE,
INCFS_COMPRESSION_KIND_LZ4,
INCFS_COMPRESSION_KIND_ZSTD,
} IncFsCompressionKind;
typedef enum {
INCFS_BLOCK_KIND_DATA,
INCFS_BLOCK_KIND_HASH,
} IncFsBlockKind;
typedef struct {
IncFsFd fileFd;
IncFsBlockIndex pageIndex;
IncFsCompressionKind compression;
IncFsBlockKind kind;
uint32_t dataSize;
const char* data;
} IncFsDataBlock;
typedef struct {
IncFsSize size;
IncFsSpan metadata;
IncFsSpan signature;
} IncFsNewFileParams;
typedef struct {
IncFsFileId sourceId;
IncFsSize sourceOffset;
IncFsSize size;
} IncFsNewMappedFileParams;
typedef struct {
IncFsFileId id;
uint64_t bootClockTsUs;
IncFsBlockIndex block;
uint32_t serialNo;
} IncFsReadInfo;
typedef struct {
IncFsFileId id;
uint64_t bootClockTsUs;
IncFsBlockIndex block;
uint32_t serialNo;
IncFsUid uid;
} IncFsReadInfoWithUid;
typedef struct {
IncFsBlockIndex begin;
IncFsBlockIndex end;
} IncFsBlockRange;
typedef struct {
IncFsBlockRange* dataRanges;
IncFsBlockRange* hashRanges;
int32_t dataRangesCount;
int32_t hashRangesCount;
IncFsBlockIndex endIndex;
} IncFsFilledRanges;
typedef struct {
IncFsSize totalDataBlocks;
IncFsSize filledDataBlocks;
IncFsSize totalHashBlocks;
IncFsSize filledHashBlocks;
} IncFsBlockCounts;
typedef struct {
IncFsUid uid;
uint32_t minTimeUs;
uint32_t minPendingTimeUs;
uint32_t maxPendingTimeUs;
} IncFsUidReadTimeouts;
typedef struct {
uint32_t readsDelayedMin;
uint64_t readsDelayedMinUs;
uint32_t readsDelayedPending;
uint64_t readsDelayedPendingUs;
uint32_t readsFailedHashVerification;
uint32_t readsFailedOther;
uint32_t readsFailedTimedOut;
uint64_t reserved;
uint64_t reserved1;
} IncFsMetrics;
typedef struct {
IncFsFileId id;
uint64_t timestampUs;
IncFsBlockIndex block;
uint32_t errorNo;
IncFsUid uid;
} IncFsLastReadError;
// All functions return -errno in case of failure.
// All IncFsFd functions return >=0 in case of success.
// All IncFsFileId functions return invalid IncFsFileId on error.
// All IncFsErrorCode functions return 0 in case of success.
bool IncFs_IsEnabled();
IncFsFeatures IncFs_Features();
bool IncFs_IsIncFsFd(int fd);
bool IncFs_IsIncFsPath(const char* path);
static inline bool IncFs_IsValidFileId(IncFsFileId fileId) {
return memcmp(&fileId, &kIncFsInvalidFileId, sizeof(fileId)) != 0;
}
int IncFs_FileIdToString(IncFsFileId id, char* out);
IncFsFileId IncFs_FileIdFromString(const char* in);
IncFsFileId IncFs_FileIdFromMetadata(IncFsSpan metadata);
IncFsControl* IncFs_Mount(const char* backingPath, const char* targetDir,
IncFsMountOptions options);
IncFsControl* IncFs_Open(const char* dir);
IncFsControl* IncFs_CreateControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs,
IncFsFd blocksWritten);
void IncFs_DeleteControl(IncFsControl* control);
IncFsFd IncFs_GetControlFd(const IncFsControl* control, IncFsFdType type);
IncFsSize IncFs_ReleaseControlFds(IncFsControl* control, IncFsFd out[], IncFsSize outSize);
IncFsErrorCode IncFs_SetOptions(const IncFsControl* control, IncFsMountOptions options);
IncFsErrorCode IncFs_BindMount(const char* sourceDir, const char* targetDir);
IncFsErrorCode IncFs_Unmount(const char* dir);
IncFsErrorCode IncFs_Root(const IncFsControl* control, char buffer[], size_t* bufferSize);
IncFsErrorCode IncFs_MakeFile(const IncFsControl* control, const char* path, int32_t mode,
IncFsFileId id, IncFsNewFileParams params);
IncFsErrorCode IncFs_MakeMappedFile(const IncFsControl* control, const char* path, int32_t mode,
IncFsNewMappedFileParams params);
IncFsErrorCode IncFs_MakeDir(const IncFsControl* control, const char* path, int32_t mode);
IncFsErrorCode IncFs_MakeDirs(const IncFsControl* control, const char* path, int32_t mode);
IncFsErrorCode IncFs_GetMetadataById(const IncFsControl* control, IncFsFileId id, char buffer[],
size_t* bufferSize);
IncFsErrorCode IncFs_GetMetadataByPath(const IncFsControl* control, const char* path, char buffer[],
size_t* bufferSize);
IncFsErrorCode IncFs_GetSignatureById(const IncFsControl* control, IncFsFileId id, char buffer[],
size_t* bufferSize);
IncFsErrorCode IncFs_GetSignatureByPath(const IncFsControl* control, const char* path,
char buffer[], size_t* bufferSize);
IncFsErrorCode IncFs_UnsafeGetSignatureByPath(const char* path, char buffer[], size_t* bufferSize);
IncFsFileId IncFs_GetId(const IncFsControl* control, const char* path);
IncFsErrorCode IncFs_Link(const IncFsControl* control, const char* sourcePath,
const char* targetPath);
IncFsErrorCode IncFs_Unlink(const IncFsControl* control, const char* path);
IncFsErrorCode IncFs_WaitForPendingReads(const IncFsControl* control, int32_t timeoutMs,
IncFsReadInfo buffer[], size_t* bufferSize);
IncFsErrorCode IncFs_WaitForPageReads(const IncFsControl* control, int32_t timeoutMs,
IncFsReadInfo buffer[], size_t* bufferSize);
IncFsErrorCode IncFs_WaitForPendingReadsWithUid(const IncFsControl* control, int32_t timeoutMs,
IncFsReadInfoWithUid buffer[], size_t* bufferSize);
IncFsErrorCode IncFs_WaitForPageReadsWithUid(const IncFsControl* control, int32_t timeoutMs,
IncFsReadInfoWithUid buffer[], size_t* bufferSize);
IncFsErrorCode IncFs_WaitForFsWrittenBlocksChange(const IncFsControl* control, int32_t timeoutMs,
IncFsSize* count);
IncFsFd IncFs_OpenForSpecialOpsByPath(const IncFsControl* control, const char* path);
IncFsFd IncFs_OpenForSpecialOpsById(const IncFsControl* control, IncFsFileId id);
IncFsErrorCode IncFs_WriteBlocks(const IncFsDataBlock blocks[], size_t blocksCount);
IncFsErrorCode IncFs_SetUidReadTimeouts(const IncFsControl* control,
const IncFsUidReadTimeouts timeouts[], size_t count);
IncFsErrorCode IncFs_GetUidReadTimeouts(const IncFsControl* control,
IncFsUidReadTimeouts timeoutsBuffer[], size_t* bufferSize);
IncFsErrorCode IncFs_GetFileBlockCountByPath(const IncFsControl* control, const char* path,
IncFsBlockCounts* blockCount);
IncFsErrorCode IncFs_GetFileBlockCountById(const IncFsControl* control, IncFsFileId id,
IncFsBlockCounts* blockCount);
IncFsErrorCode IncFs_ListIncompleteFiles(const IncFsControl* control, IncFsFileId ids[],
size_t* bufferSize);
// Calls a passed callback for each file on the mounted filesystem, or, in the second case,
// for each incomplete file (only for v2 IncFS).
// Callback can stop the iteration early by returning |false|.
// Return codes:
// >=0 - number of files iterated,
// <0 - -errno
typedef bool (*FileCallback)(void* context, const IncFsControl* control, IncFsFileId fileId);
IncFsErrorCode IncFs_ForEachFile(const IncFsControl* control, void* context, FileCallback cb);
IncFsErrorCode IncFs_ForEachIncompleteFile(const IncFsControl* control, void* context,
FileCallback cb);
IncFsErrorCode IncFs_WaitForLoadingComplete(const IncFsControl* control, int32_t timeoutMs);
// Gets a collection of filled ranges in the file from IncFS. Uses the |outBuffer| memory, it has
// to be big enough to fit all the ranges the caller is expecting.
// Return codes:
// 0 - success,
// -ERANGE - input buffer is too small. filledRanges are still valid up to the outBuffer.size,
// but there are more,
// <0 - error, |filledRanges| is not valid.
IncFsErrorCode IncFs_GetFilledRanges(int fd, IncFsSpan outBuffer, IncFsFilledRanges* filledRanges);
IncFsErrorCode IncFs_GetFilledRangesStartingFrom(int fd, int startBlockIndex, IncFsSpan outBuffer,
IncFsFilledRanges* filledRanges);
// Check if the file is fully loaded. Return codes:
// 0 - fully loaded,
// -ENODATA - some blocks are missing,
// <0 - error from the syscall.
IncFsErrorCode IncFs_IsFullyLoaded(int fd);
IncFsErrorCode IncFs_IsFullyLoadedByPath(const IncFsControl* control, const char* path);
IncFsErrorCode IncFs_IsFullyLoadedById(const IncFsControl* control, IncFsFileId fileId);
// Check if all files on the mount are fully loaded. Return codes:
// 0 - fully loaded,
// -ENODATA - some blocks are missing,
// <0 - error from the syscall.
IncFsErrorCode IncFs_IsEverythingFullyLoaded(const IncFsControl* control);
// Reserve |size| bytes for the file. Trims reserved space to the current file size when |size = -1|
static const IncFsSize kIncFsTrimReservedSpace = -1;
IncFsErrorCode IncFs_ReserveSpaceByPath(const IncFsControl* control, const char* path,
IncFsSize size);
IncFsErrorCode IncFs_ReserveSpaceById(const IncFsControl* control, IncFsFileId id, IncFsSize size);
// Gets the metrics of a mount by specifying the corresponding sysfs subpath.
// Return codes:
// =0 - success
// <0 - -errno
IncFsErrorCode IncFs_GetMetrics(const char* sysfsName, IncFsMetrics* metrics);
// Gets information about the last read error of a mount.
// Return codes:
// =0 - success
// <0 - -errno
// When there is no read error, still returns success. Fields in IncFsLastReadError will be all 0.
// Possible values of IncFsLastReadError.errorNo:
// -ETIME for read timeout;
// -EBADMSG for hash verification failure;
// Other negative values for other types of errors.
IncFsErrorCode IncFs_GetLastReadError(const IncFsControl* control,
IncFsLastReadError* lastReadError);
__END_DECLS
#endif // ANDROID_INCREMENTAL_FILE_SYSTEM_NDK_H