blob: 32e198dfb5320ed84b368cd5a00844a4ac1b2c23 [file] [log] [blame]
/*
* Copyright (c) 2023 Antmicro <www.antmicro.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __EXT2_IMPL_H__
#define __EXT2_IMPL_H__
#include <zephyr/fs/fs.h>
#include <zephyr/fs/ext2.h>
#include "ext2_struct.h"
extern struct k_heap direntry_heap;
void error_behavior(struct ext2_data *fs, const char *msg);
/* Memory allocation for ext2 implementation */
void *ext2_heap_alloc(size_t size);
void ext2_heap_free(void *ptr);
/* Initialization of disk storage. */
int ext2_init_disk_access_backend(struct ext2_data *fs, const void *storage_dev, int flags);
/**
* @brief Get block from the disk.
*/
struct ext2_block *ext2_get_block(struct ext2_data *fs, uint32_t block);
struct ext2_block *ext2_get_empty_block(struct ext2_data *fs);
/**
* @brief Free the block structure.
*/
void ext2_drop_block(struct ext2_block *b);
/**
* @brief Write block to the disk.
*
* NOTICE: to ensure that all writes has ended the sync of disk must be triggered
* (fs::sync function).
*/
int ext2_write_block(struct ext2_data *fs, struct ext2_block *b);
void ext2_init_blocks_slab(struct ext2_data *fs);
/**
* @brief Write block to the disk.
*
* NOTICE: to ensure that all writes has ended the sync of disk must be triggered
* (fs::sync function).
*/
int ext2_write_block(struct ext2_data *fs, struct ext2_block *b);
int ext2_assign_block_num(struct ext2_data *fs, struct ext2_block *b);
/* FS operations */
/**
* @brief Initialize structure with data needed to access the storage device
*
* @param fs File system data structure to initialize
* @param storage_dev Pointer to storage
* @param flags Additional flags (e.g. RO flag)
*
* @retval 0 on success
* @retval -EINVAL when superblock of ext2 was not detected
* @retval -ENOTSUP when described file system is not supported
* @retval <0 other error
*/
int ext2_init_storage(struct ext2_data **fsp, const void *storage_dev, int flags);
/**
* @brief Verify superblock of file system
*
* Checks if file system is supported by the implementation.
* @retval 0 when superblock is valid
* @retval -EROFS when superblock is not valid but file system may be mounted read only
* @retval -EINVAL when superblock is not valid and file system cannot be mounted at all
* @retval -ENOTSUP when superblock has some field set to value that we don't support
*/
int ext2_verify_disk_superblock(struct ext2_disk_superblock *sb);
/**
* @brief Initialize all data needed to perform operations on file system
*
* Fetches the superblock. Initializes structure fields.
*/
int ext2_init_fs(struct ext2_data *fs);
/**
* @brief Clear the data used by file system implementation
*
*/
int ext2_close_fs(struct ext2_data *fs);
/**
* @brief Clear the data used to communicate with storage device
*
*/
int ext2_close_struct(struct ext2_data *fs);
/**
* @brief Create the ext2 file system
*
* This function uses functions stored in `ext2_data` structure to create new
* file system on storage device.
*
* NOTICE: fs structure must be first initialized with `ext2_init_fs` function.
*
* After this function succeeds the `ext2_clean` function must be called.
*
* @param fs File system data (must be initialized before)
*
* @retval 0 on success
* @retval -ENOSPC when storage device is too small for ext2 file system
* @retval -ENOTSUP when storage device is too big (file systems with more than
* 8192 blocks are not supported)
*/
int ext2_format(struct ext2_data *fs, struct ext2_cfg *cfg);
/* Lookup flags */
#define LOOKUP_ARG_OPEN BIT(0)
#define LOOKUP_ARG_CREATE BIT(1)
#define LOOKUP_ARG_STAT BIT(2)
#define LOOKUP_ARG_UNLINK BIT(3)
/* Structure for lookup arguments and results.
*
* Required fields (must be filled when lookup function is invoked):
* - path
* - flags
*
* Fields that hold the result:
* - inode
* - parent
* - offset
* - name_pos
* - name_len
*
* Some of these fields have a meaning only for a specific function.
* (E.g. during stat only the fields parent and offset are used)
*
* Field is marked with these labels when lookup is used from other function:
* OP -- open
* CR -- create
* ST -- stat
* UN -- unlink
*/
struct ext2_lookup_args {
const char *path; /* path of inode */
struct ext2_inode *inode; /* (OP, CR, ST, UN) found inode */
struct ext2_inode *parent; /* (CR, ST, UN) parent of found inode */
uint32_t offset; /* (CR, ST, UN) offset of entry in directory */
uint32_t name_pos; /* (CR) position of name in input path */
uint32_t name_len; /* (CR) length of name */
uint8_t flags; /* indicates from which function lookup is invoked */
};
/**
* @brief Look for an inode.
*
* @param fs File system data
* @param args All needed arguments for lookup
*
* @retval 0 on success
* @retval -ENOENT inode or path component not found
* @retval -ENOTDIR path component not a directory
* @retval <0 other error
*/
int ext2_lookup_inode(struct ext2_data *fs, struct ext2_lookup_args *args);
/* Inode operations */
/**
* @brief Read from inode at given offset
*
* @param inode Inode
* @param buf Buffer to hold read data
* @param offset Offset in inode
* @param nbytes Number of bytes to read
*
* @retval >=0 number of bytes read on success
* @retval <0 error code
*/
ssize_t ext2_inode_read(struct ext2_inode *inode, void *buf, uint32_t offset,
size_t nbytes);
/**
* @brief Write to inode at given offset
*
* @param inode Inode
* @param buf Buffer with data to write
* @param offset Offset in inode
* @param nbytes Number of bytes to write
*
* @retval >=0 number of bytes read on success
* @retval <0 error code
*/
ssize_t ext2_inode_write(struct ext2_inode *inode, const void *buf,
uint32_t offset, size_t nbytes);
/**
* @brief Truncate the inode
*
* @param inode Inode
* @param size New size for inode
*
* @retval 0 on success
* @retval -ENOTSUP when requested size is too big
* @retval <0 other error
*/
int ext2_inode_trunc(struct ext2_inode *inode, off_t size);
/**
* @brief Sync currently fetched blocks
*
* @param inode Inode
*
*/
int ext2_inode_sync(struct ext2_inode *inode);
/* Directory operations */
/**
* @brief Get directory entry
*
* Reads directory entry that is at offset specified in `ext2_file` structure.
*
* @param dir Read directory
* @param ent Directory entry to fill in
*
* @retval 0 on success
* @retval <0 on error
*/
int ext2_get_direntry(struct ext2_file *dir, struct fs_dirent *ent);
/**
* @brief Create a directory entry with given attributes
*
* Automatically calculates and sets de_rec_len field.
*
* NOTE: if you need to adjust the size (e.g. when this entry is the last one in the block)
* then just update the size after this function returns.
*
* @param name Name of direntry
* @param namelen Length of name
* @param ino Inode associated with that entry
* @param filetype File type of that entry
*
* @returns structure allocated on direntry_heap filled with given data
*/
struct ext2_direntry *ext2_create_direntry(const char *name, uint8_t namelen, uint32_t ino,
uint8_t filetype);
/**
* @brief Create a file
*
* @param parent Parent directory
* @param inode Pointer to inode structure that will be filled with new inode
* @param args Lookup arguments that describe file to create
*
* @retval 0 on success
* @retval -ENOSPC there is not enough memory on storage device to create a file
* @retval <0 on error
*/
int ext2_create_file(struct ext2_inode *parent, struct ext2_inode *inode,
struct ext2_lookup_args *args);
/**
* @brief Create a directory
*
* @param parent Parent directory
* @param inode Pointer to inode structure that will be filled with new inode
* @param args Lookup arguments that describe directory to create
*
* @retval 0 on success
* @retval -ENOSPC there is not enough memory on storage device to create a file
* @retval <0 on error
*/
int ext2_create_dir(struct ext2_inode *parent, struct ext2_inode *inode,
struct ext2_lookup_args *args);
/**
* @brief Unlink the directory entry at given offset in parent directory
*
* @param parent Parent directory
* @param inode File to unlink
* @param offset Offset of unlinked file in the parent directory
*
* @retval 0 on success
* @retval -ENOTEMPTY when directory to unlink is not empty
* @retval <0 other error
*/
int ext2_inode_unlink(struct ext2_inode *parent, struct ext2_inode *inode,
uint32_t offset);
/**
* @brief Move a file
*
* Invoked when rename destination entry doesn't exist.
*
* @param args_from Describe source file
* @param args_to Describe destination
*
* @retval 0 on success
* @retval <0 on error
*/
int ext2_move_file(struct ext2_lookup_args *args_from, struct ext2_lookup_args *args_to);
/**
* @brief Replace the file with another
*
* Invoked when rename destination entry does exist
*
* @param args_from Describe source file
* @param args_to Describe destination file
*
* @retval 0 on success
* @retval <0 on error
*/
int ext2_replace_file(struct ext2_lookup_args *args_from, struct ext2_lookup_args *args_to);
/* Inode pool operations */
/**
* @brief Get the inode
*
* Retrieves inode structure and stores it in the inode pool. The inode is
* filled with data of requested inode.
*
* @param fs File system data
* @param ino Inode number
* @param ret Pointer to place where to store new inode pointer
*
* @retval 0 on success
* @retval -ENOMEM when there is no memory to hold the requested inode
* @retval <0 on error
*/
int ext2_inode_get(struct ext2_data *fs, uint32_t ino, struct ext2_inode **ret);
/**
* @brief Remove reference to the inode structure
*
* When removed reference is the last reference to that inode then it is freed.
*
* @param inode Dropped inode
*
* @retval 0 on success
* @retval -EINVAL the dropped inode is not stored in the inode pool
* @retval <0 on error
*/
int ext2_inode_drop(struct ext2_inode *inode);
/* Drop blocks fetched in inode structure. */
void ext2_inode_drop_blocks(struct ext2_inode *inode);
/**
* @brief Remove all blocks starting with some block
*
* @param first First block to remove
*
* @retval >=0 number of removed blocks
* @retval <0 error code
*/
int64_t ext2_inode_remove_blocks(struct ext2_inode *inode, uint32_t first);
#endif /* __EXT2_IMPL_H__ */