merge fs changes.
This commit is contained in:
@@ -36,10 +36,9 @@ History:
|
||||
1. Date: 2024-01-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. support inode create and delete
|
||||
3. remove inode lock and unlock
|
||||
4. remove inode cache
|
||||
5. rename function names(DirInodeAddEntry,DirInodeLookup, InodeAlloc, InodeFree, PathElementExtract, InodeBlockMapping, Seek, InodeSeek, InodeParentSeek, InodeRead, InodeWrite) to fit XIZI_AIoT use sceneries
|
||||
1. remove inode lock and unlock
|
||||
2. remove inode cache
|
||||
3. rewrite skipelem function to PathElementExtract to fit XIZI_AIoT use sceneries
|
||||
*************************************************/
|
||||
|
||||
#include <string.h>
|
||||
@@ -48,22 +47,15 @@ Modification:
|
||||
#include "fs.h"
|
||||
#include "libserial.h"
|
||||
|
||||
static void Error(char* s)
|
||||
{
|
||||
printf("Error: %s\n", s);
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define MIN_LENGTH(len1, len2) ((len1) < (len2) ? (len1) : (len2))
|
||||
|
||||
static int DirInodeAddEntry(struct Inode* dp, char* name, uint32_t inum);
|
||||
static struct Inode* DirInodeLookup(struct Inode* dp, char* name, uint32_t* poff);
|
||||
static struct Inode* InodeAlloc(short type);
|
||||
static int InodeFree(struct Inode* ip);
|
||||
static int DirInodeDelEntry(struct Inode* parent_inode, char* name);
|
||||
static struct Inode* DirInodeLookup(struct Inode* dp, char* name);
|
||||
static struct Inode* InodeAlloc(int type);
|
||||
static int InodeFreeRecursive(struct Inode* dp);
|
||||
static char* PathElementExtract(char* path, char* name);
|
||||
static uint32_t InodeBlockMapping(struct Inode* ip, uint32_t block_num);
|
||||
static uint32_t InodeBlockMapping(struct Inode* inode, uint32_t block_num);
|
||||
|
||||
#define MAX_SUPPORT_FD 1024
|
||||
static struct FileDescriptor fd_table[MAX_SUPPORT_FD];
|
||||
@@ -80,83 +72,236 @@ void MemFsInit(uintptr_t _binary_fs_img_start, uint32_t fs_img_len)
|
||||
/// @brief Read the super block.
|
||||
void ReadSuperBlock(struct SuperBlock* sb)
|
||||
{
|
||||
uint8_t* data = BlockRead(ROOT_INUM);
|
||||
memmove(sb, data, sizeof(*sb));
|
||||
uint8_t* block = BlockRead(ROOT_INUM);
|
||||
memmove(sb, block, sizeof(*sb));
|
||||
}
|
||||
|
||||
/// @brief Get a existed Inode by inum
|
||||
struct Inode* InodeGet(uint32_t inum)
|
||||
{
|
||||
struct Inode* ip;
|
||||
uint8_t* data = BlockRead(BLOCK_INDEX(inum));
|
||||
ip = (struct Inode*)data + INODE_INDEX(inum);
|
||||
return ip;
|
||||
struct Inode* inode;
|
||||
uint8_t* block = BlockRead(BLOCK_INDEX(inum));
|
||||
inode = (struct Inode*)block + INODE_INDEX(inum);
|
||||
return inode;
|
||||
}
|
||||
|
||||
/// @brief Create a new Inode under the parent Inode
|
||||
struct Inode* InodeCreate(struct Inode* parent_inode, char* name, int type)
|
||||
{
|
||||
struct Inode* inode;
|
||||
if ((inode = DirInodeLookup(parent_inode, name)) != 0) {
|
||||
if (type == FS_FILE && inode->type == FS_FILE) {
|
||||
return inode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((inode = InodeAlloc(type)) == 0) {
|
||||
printf("InodeCreate: alloc Inode failed, no free inode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (type == FS_DIRECTORY) {
|
||||
if (DirInodeAddEntry(inode, ".", inode->inum) < 0 || DirInodeAddEntry(inode, "..", parent_inode->inum) < 0) {
|
||||
printf("InodeCreate: create dots");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (DirInodeAddEntry(parent_inode, name, inode->inum) < 0) {
|
||||
printf("InodeCreate: DirInodeAddEntry failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
||||
/// @brief Delete a file Inode or a dir Inode
|
||||
int InodeDelete(struct Inode* parent_inode, char* name)
|
||||
{
|
||||
uint32_t offset;
|
||||
struct Inode* inode;
|
||||
struct DirectEntry de;
|
||||
|
||||
if ((inode = DirInodeLookup(parent_inode, name)) == 0) {
|
||||
printf("Inode delete failed, file not exsit");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inode->type == FS_FILE) {
|
||||
inode->type = 0;
|
||||
} else if (inode->type == FS_DIRECTORY) {
|
||||
// recursive free alloced Inode
|
||||
if (InodeFreeRecursive(inode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
DirInodeDelEntry(parent_inode, name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Read data from the Inode to the dst buffer.
|
||||
int InodeRead(struct Inode* inode, char* dst, int offset, int len)
|
||||
{
|
||||
uint32_t location, writen_len;
|
||||
uint8_t* block;
|
||||
|
||||
if (len < 0 || offset > inode->size) {
|
||||
return -1;
|
||||
}
|
||||
if (offset + len > inode->size) {
|
||||
len = inode->size - offset;
|
||||
}
|
||||
|
||||
location = 0;
|
||||
while (location < len) {
|
||||
if ((block = BlockRead(InodeBlockMapping(inode, offset / BLOCK_SIZE))) == 0) {
|
||||
return 0;
|
||||
}
|
||||
writen_len = MIN_LENGTH(len - location, BLOCK_SIZE - offset % BLOCK_SIZE);
|
||||
memmove(dst, block + offset % BLOCK_SIZE, writen_len);
|
||||
location += writen_len;
|
||||
offset += writen_len;
|
||||
dst += writen_len;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/// @brief Write data from src buffer to the Inode, then increase the Inode size if neccessary.
|
||||
int InodeWrite(struct Inode* inode, char* src, int offset, int len)
|
||||
{
|
||||
uint32_t location, writen_len;
|
||||
uint8_t* block;
|
||||
|
||||
if (len < 0 || offset > inode->size) {
|
||||
return -1;
|
||||
}
|
||||
if (offset + len > MAX_FILE_SIZE * BLOCK_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
location = 0;
|
||||
while (location < len) {
|
||||
if ((block = BlockRead(InodeBlockMapping(inode, offset / BLOCK_SIZE))) == 0) {
|
||||
return 0;
|
||||
}
|
||||
writen_len = MIN_LENGTH(len - location, BLOCK_SIZE - offset % BLOCK_SIZE);
|
||||
memmove(block + offset % BLOCK_SIZE, src, writen_len);
|
||||
location += writen_len;
|
||||
offset += writen_len;
|
||||
src += writen_len;
|
||||
}
|
||||
|
||||
if (len > 0 && offset > inode->size) {
|
||||
inode->size = offset;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/// @brief Find target Inode from source Inode
|
||||
struct Inode* InodeSeek(struct Inode* source, char* path)
|
||||
{
|
||||
if (source->size == 0) {
|
||||
printf("Inode is empty\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char name[DIR_NAME_SIZE] = { 0 };
|
||||
struct Inode *cur_inode, *next_inode;
|
||||
cur_inode = source;
|
||||
while ((path = PathElementExtract(path, name)) != 0) {
|
||||
if (cur_inode->type != FS_DIRECTORY) {
|
||||
return NULL;
|
||||
}
|
||||
if ((next_inode = DirInodeLookup(cur_inode, name)) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
cur_inode = next_inode;
|
||||
}
|
||||
return cur_inode;
|
||||
}
|
||||
|
||||
/// @brief Find target parent Inode from source Inode
|
||||
struct Inode* InodeParentSeek(struct Inode* source, char* path, char* name)
|
||||
{
|
||||
if (source->size == 0) {
|
||||
printf("Inode is empty\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Inode *cur_inode, *next_inode;
|
||||
cur_inode = source;
|
||||
while ((path = PathElementExtract(path, name)) != 0) {
|
||||
if (cur_inode->type != FS_DIRECTORY) {
|
||||
return NULL;
|
||||
}
|
||||
if (*path == '\0') {
|
||||
return cur_inode;
|
||||
}
|
||||
if ((next_inode = DirInodeLookup(cur_inode, name)) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
cur_inode = next_inode;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// @brief Alloc a new Inode using type
|
||||
static struct Inode* InodeAlloc(short type)
|
||||
static struct Inode* InodeAlloc(int type)
|
||||
{
|
||||
int inum;
|
||||
struct Inode* ip;
|
||||
struct Inode* inode;
|
||||
struct SuperBlock sb;
|
||||
|
||||
ReadSuperBlock(&sb);
|
||||
for (inum = 1; inum < sb.ninodes; inum++) {
|
||||
uint8_t* data = BlockRead(BLOCK_INDEX(inum));
|
||||
ip = (struct Inode*)data + INODE_INDEX(inum);
|
||||
if (ip->type == 0) {
|
||||
memset(ip, 0, sizeof(*ip));
|
||||
ip->inum = inum;
|
||||
ip->type = type;
|
||||
ip->nlink = 1;
|
||||
ip->size = 0;
|
||||
return ip;
|
||||
uint8_t* block = BlockRead(BLOCK_INDEX(inum));
|
||||
inode = (struct Inode*)block + INODE_INDEX(inum);
|
||||
if (inode->type == 0) {
|
||||
memset(inode, 0, sizeof(*inode));
|
||||
inode->inum = inum;
|
||||
inode->type = type;
|
||||
inode->size = 0;
|
||||
return inode;
|
||||
}
|
||||
}
|
||||
|
||||
Error("InodeAlloc: no inodes");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// @brief Free the existed Inode
|
||||
static int InodeFree(struct Inode* ip)
|
||||
{
|
||||
uint8_t* data = BlockRead(BLOCK_INDEX(ip->inum));
|
||||
struct Inode* dip = (struct Inode*)data + INODE_INDEX(ip->inum);
|
||||
dip->type = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Delete the dir and all files or dirs under the dir.
|
||||
static int InodeFreeRecursive(struct Inode* dp)
|
||||
static int InodeFreeRecursive(struct Inode* parent_inode)
|
||||
{
|
||||
uint32_t off;
|
||||
struct Inode* ip;
|
||||
uint32_t offset;
|
||||
struct Inode* inode;
|
||||
struct DirectEntry de;
|
||||
|
||||
for (off = 0; off < dp->size; off += sizeof(de)) {
|
||||
if (InodeRead(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) {
|
||||
Error("inode_delete_dir failed: read directory entry failed");
|
||||
for (offset = 0; offset < parent_inode->size; offset += sizeof(de)) {
|
||||
if (InodeRead(parent_inode, (char*)&de, offset, sizeof(de)) != sizeof(de)) {
|
||||
printf("inode_delete_dir failed: read directory entry failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// unlink dir
|
||||
if (de.inum == 0 || strcmp(de.name, "..") == 0 || strcmp(de.name, ".") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ip = InodeGet(de.inum);
|
||||
if (ip->type == T_DIR) {
|
||||
if (InodeFreeRecursive(ip) < 0) {
|
||||
inode = InodeGet(de.inum);
|
||||
if (inode->type == FS_DIRECTORY) {
|
||||
if (InodeFreeRecursive(inode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else if (ip->type == T_FILE) {
|
||||
InodeFree(ip);
|
||||
} else if (inode->type == FS_FILE) {
|
||||
inode->type = 0;
|
||||
}
|
||||
|
||||
// delete the dir entry
|
||||
de.inum = 0;
|
||||
if (InodeWrite(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) {
|
||||
if (InodeWrite(parent_inode, (char*)&de, offset, sizeof(de)) != sizeof(de)) {
|
||||
printf("InodeDelete failed: clear directory entry failed");
|
||||
return -1;
|
||||
}
|
||||
@@ -164,74 +309,14 @@ static int InodeFreeRecursive(struct Inode* dp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Delete a file Inode or a dir Inode
|
||||
int InodeDelete(struct Inode* dp, char* name)
|
||||
{
|
||||
uint32_t off;
|
||||
struct Inode* ip;
|
||||
struct DirectEntry de;
|
||||
|
||||
if ((ip = DirInodeLookup(dp, name, &off)) == 0) {
|
||||
Error("Inode delete failed, file not exsit");
|
||||
return -1;
|
||||
}
|
||||
|
||||
InodeFree(ip);
|
||||
if (ip->type == T_DIR) {
|
||||
// recursive free alloced Inode
|
||||
if (InodeFreeRecursive(ip) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// delete the dir entry
|
||||
de.inum = 0;
|
||||
if (InodeWrite(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) {
|
||||
printf("InodeDelete failed: clear directory entry failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Create a new Inode under the parent Inode
|
||||
struct Inode* InodeCreate(struct Inode* dp, char* name, short type, short major, short minor)
|
||||
{
|
||||
uint32_t off;
|
||||
struct Inode* ip;
|
||||
|
||||
if ((ip = DirInodeLookup(dp, name, &off)) != 0) {
|
||||
if (type == T_FILE && ip->type == T_FILE) {
|
||||
return ip;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ip = InodeAlloc(type)) == 0) {
|
||||
Error("InodeCreate: create Inode failed\n");
|
||||
}
|
||||
|
||||
if (type == T_DIR) {
|
||||
dp->nlink++;
|
||||
if (DirInodeAddEntry(ip, ".", ip->inum) < 0 || DirInodeAddEntry(ip, "..", dp->inum) < 0) {
|
||||
Error("InodeCreate: create dots");
|
||||
}
|
||||
}
|
||||
|
||||
if (DirInodeAddEntry(dp, name, ip->inum) < 0) {
|
||||
Error("InodeCreate: DirInodeAddEntry failed");
|
||||
}
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
/// @brief Mapping the direct block addrs or indirect block addrs of the Inode using the block_num
|
||||
static uint32_t InodeBlockMapping(struct Inode* ip, uint32_t block_num)
|
||||
static uint32_t InodeBlockMapping(struct Inode* inode, uint32_t block_num)
|
||||
{
|
||||
uint32_t addr;
|
||||
// block is in range of direct mapping
|
||||
if (block_num < NR_DIRECT_BLOCKS) {
|
||||
if ((addr = ip->addrs[block_num]) == 0) {
|
||||
ip->addrs[block_num] = addr = BlockAlloc();
|
||||
if ((addr = inode->addrs[block_num]) == 0) {
|
||||
inode->addrs[block_num] = addr = BlockAlloc();
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -240,12 +325,12 @@ static uint32_t InodeBlockMapping(struct Inode* ip, uint32_t block_num)
|
||||
block_num -= NR_DIRECT_BLOCKS;
|
||||
int indirect_block_id = block_num / MAX_INDIRECT_BLOCKS;
|
||||
if (indirect_block_id < NR_INDIRECT_BLOCKS) {
|
||||
if ((addr = ip->addrs[NR_DIRECT_BLOCKS + indirect_block_id]) == 0) {
|
||||
ip->addrs[NR_DIRECT_BLOCKS + indirect_block_id] = addr = BlockAlloc();
|
||||
if ((addr = inode->addrs[NR_DIRECT_BLOCKS + indirect_block_id]) == 0) {
|
||||
inode->addrs[NR_DIRECT_BLOCKS + indirect_block_id] = addr = BlockAlloc();
|
||||
}
|
||||
block_num -= indirect_block_id * MAX_INDIRECT_BLOCKS;
|
||||
} else {
|
||||
Error("InodeBlockMapping: out of range");
|
||||
printf("InodeBlockMapping: out of range");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -259,18 +344,20 @@ static uint32_t InodeBlockMapping(struct Inode* ip, uint32_t block_num)
|
||||
}
|
||||
|
||||
/// @brief Look up the directory Inode for searching the target Inode
|
||||
static struct Inode* DirInodeLookup(struct Inode* dp, char* name, uint32_t* poff)
|
||||
static struct Inode* DirInodeLookup(struct Inode* parent_inode, char* name)
|
||||
{
|
||||
uint32_t off, inum;
|
||||
uint32_t offset, inum;
|
||||
struct DirectEntry de;
|
||||
|
||||
if (dp->type != T_DIR) {
|
||||
Error("DirInodeLookup not DIR");
|
||||
if (parent_inode->type != FS_DIRECTORY) {
|
||||
printf("DirInodeLookup not DIR");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (off = 0; off < dp->size; off += sizeof(de)) {
|
||||
if (InodeRead(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) {
|
||||
Error("DirInodeAddEntry read");
|
||||
for (offset = 0; offset < parent_inode->size; offset += sizeof(de)) {
|
||||
if (InodeRead(parent_inode, (char*)&de, offset, sizeof(de)) != sizeof(de)) {
|
||||
printf("DirInodeAddEntry read");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (de.inum == 0) {
|
||||
@@ -278,9 +365,6 @@ static struct Inode* DirInodeLookup(struct Inode* dp, char* name, uint32_t* poff
|
||||
}
|
||||
|
||||
if (strncmp((const char*)name, (const char*)de.name, DIR_NAME_SIZE) == 0) {
|
||||
if (poff) {
|
||||
*poff = off;
|
||||
}
|
||||
inum = de.inum;
|
||||
return InodeGet(inum);
|
||||
}
|
||||
@@ -290,21 +374,22 @@ static struct Inode* DirInodeLookup(struct Inode* dp, char* name, uint32_t* poff
|
||||
}
|
||||
|
||||
/// @brief Add a new directory entry for dir Inode
|
||||
static int DirInodeAddEntry(struct Inode* dp, char* name, uint32_t inum)
|
||||
static int DirInodeAddEntry(struct Inode* parent_inode, char* name, uint32_t inum)
|
||||
{
|
||||
int off;
|
||||
int offset;
|
||||
struct DirectEntry de;
|
||||
struct Inode* ip;
|
||||
struct Inode* inode;
|
||||
|
||||
// Check that direct entry is existed.
|
||||
if ((ip = DirInodeLookup(dp, name, 0)) != 0) {
|
||||
// Check the direct entry is not existed.
|
||||
if ((inode = DirInodeLookup(parent_inode, name)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Look for an empty dir entry.
|
||||
for (off = 0; off < dp->size; off += sizeof(de)) {
|
||||
if (InodeRead(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) {
|
||||
Error("DirInodeAddEntry: read failed");
|
||||
for (offset = 0; offset < parent_inode->size; offset += sizeof(de)) {
|
||||
if (InodeRead(parent_inode, (char*)&de, offset, sizeof(de)) != sizeof(de)) {
|
||||
printf("DirInodeAddEntry: read failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (de.inum == 0) {
|
||||
@@ -315,98 +400,45 @@ static int DirInodeAddEntry(struct Inode* dp, char* name, uint32_t inum)
|
||||
// build a new direct entry.
|
||||
strncpy(de.name, name, DIR_NAME_SIZE);
|
||||
de.inum = inum;
|
||||
if (InodeWrite(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) {
|
||||
Error("DirInodeAddEntry: write failed");
|
||||
if (InodeWrite(parent_inode, (char*)&de, offset, sizeof(de)) != sizeof(de)) {
|
||||
printf("DirInodeAddEntry: write failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct Inode* Seek(struct Inode* ip, char* path, int nameiparent, char* name)
|
||||
/// @brief Delete the directory entry for dir Inode
|
||||
static int DirInodeDelEntry(struct Inode* parent_inode, char* name)
|
||||
{
|
||||
if (ip->size == 0) {
|
||||
Error("Inode is not sync\n");
|
||||
}
|
||||
int offset;
|
||||
struct DirectEntry de;
|
||||
struct Inode* inode;
|
||||
|
||||
struct Inode* next;
|
||||
while ((path = PathElementExtract(path, name)) != 0) {
|
||||
if (ip->type != T_DIR) {
|
||||
return NULL;
|
||||
}
|
||||
if (nameiparent && *path == '\0') {
|
||||
return ip;
|
||||
}
|
||||
if ((next = DirInodeLookup(ip, name, 0)) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
ip = next;
|
||||
}
|
||||
|
||||
if (nameiparent) {
|
||||
return NULL;
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
/// @brief Find target Inode from source Inode
|
||||
struct Inode* InodeSeek(struct Inode* source, char* path)
|
||||
{
|
||||
char name[DIR_NAME_SIZE] = { 0 };
|
||||
return Seek(source, path, 0, name);
|
||||
}
|
||||
|
||||
/// @brief Find target parent Inode from source Inode
|
||||
struct Inode* InodeParentSeek(struct Inode* source, char* path, char* name)
|
||||
{
|
||||
return Seek(source, path, 1, name);
|
||||
}
|
||||
|
||||
/// @brief Read data from the Inode to the dst buffer.
|
||||
int InodeRead(struct Inode* ip, char* dst, int off, int n)
|
||||
{
|
||||
uint32_t tot, m;
|
||||
|
||||
if (off > ip->size || off + n < off) {
|
||||
// Check the direct entry is existed.
|
||||
if ((inode = DirInodeLookup(parent_inode, name)) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (off + n > ip->size) {
|
||||
n = ip->size - off;
|
||||
// Look for an empty dir entry.
|
||||
for (offset = 0; offset < parent_inode->size; offset += sizeof(de)) {
|
||||
if (InodeRead(parent_inode, (char*)&de, offset, sizeof(de)) != sizeof(de)) {
|
||||
printf("DirInodeAddEntry: read failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strncmp(de.name, name, DIR_NAME_SIZE) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (tot = 0; tot < n; tot += m, off += m, dst += m) {
|
||||
uint8_t* data = BlockRead(InodeBlockMapping(ip, off / BLOCK_SIZE));
|
||||
m = min(n - tot, BLOCK_SIZE - off % BLOCK_SIZE);
|
||||
memmove(dst, data + off % BLOCK_SIZE, m);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/// @brief Write data from src buffer to the Inode, then increase the Inode size if neccessary.
|
||||
int InodeWrite(struct Inode* ip, char* src, uint32_t off, uint32_t n)
|
||||
{
|
||||
uint32_t tot, m;
|
||||
|
||||
if (off > ip->size || off + n < off) {
|
||||
de.inum = 0;
|
||||
if (InodeWrite(parent_inode, (char*)&de, offset, sizeof(de)) != sizeof(de)) {
|
||||
printf("DirInodeAddEntry: write failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (off + n > MAX_FILE_SIZE * BLOCK_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (tot = 0; tot < n; tot += m, off += m, src += m) {
|
||||
uint8_t* data = BlockRead(InodeBlockMapping(ip, off / BLOCK_SIZE));
|
||||
m = min(n - tot, BLOCK_SIZE - off % BLOCK_SIZE);
|
||||
memmove(data + off % BLOCK_SIZE, src, m);
|
||||
}
|
||||
|
||||
if (n > 0 && off > ip->size) {
|
||||
ip->size = off;
|
||||
}
|
||||
|
||||
return n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Paths process
|
||||
|
||||
@@ -110,7 +110,7 @@ int IPC_DO_SERVE_FUNC(Ipc_cd)(char* path)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ip->type != T_DIR) {
|
||||
if (ip->type != FS_DIRECTORY) {
|
||||
printf("cd:not a dir\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -148,7 +148,7 @@ int IPC_DO_SERVE_FUNC(Ipc_mkdir)(char* path)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (InodeCreate(ip, name, T_DIR, 0, 0) == 0) {
|
||||
if (InodeCreate(ip, name, FS_DIRECTORY) == 0) {
|
||||
printf("create target Inode %s failed\n", path);
|
||||
return -1;
|
||||
}
|
||||
@@ -207,7 +207,7 @@ int IPC_DO_SERVE_FUNC(Ipc_cat)(char* path)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ip->type != T_FILE) {
|
||||
if (ip->type != FS_FILE) {
|
||||
printf("cat: %s Is not a file\n", path);
|
||||
return -1;
|
||||
}
|
||||
@@ -254,7 +254,6 @@ int IPC_DO_SERVE_FUNC(Ipc_open)(char* path)
|
||||
|
||||
/// @todo record absolute path
|
||||
strncpy(fdp->path, path, strlen(path) + 1);
|
||||
ip->nlink++;
|
||||
fdp->data = ip;
|
||||
|
||||
return fd;
|
||||
@@ -262,15 +261,6 @@ int IPC_DO_SERVE_FUNC(Ipc_open)(char* path)
|
||||
|
||||
int IPC_DO_SERVE_FUNC(Ipc_close)(int* fd)
|
||||
{
|
||||
struct FileDescriptor* fdp = GetFileDescriptor(*fd);
|
||||
if (!fdp) {
|
||||
printf("read: fd invalid\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct Inode* ip = fdp->data;
|
||||
ip->nlink--;
|
||||
|
||||
FreeFileDescriptor(*fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -285,7 +275,7 @@ int IPC_DO_SERVE_FUNC(Ipc_read)(int* fd, char* dst, int* offset, int* len)
|
||||
}
|
||||
|
||||
struct Inode* ip = fdp->data;
|
||||
if (ip->type != T_FILE) {
|
||||
if (ip->type != FS_FILE) {
|
||||
printf("read: %s Is not a file\n", fdp->path);
|
||||
return -1;
|
||||
}
|
||||
@@ -305,7 +295,7 @@ int IPC_DO_SERVE_FUNC(Ipc_write)(int* fd, char* src, int* offset, int* len)
|
||||
}
|
||||
|
||||
struct Inode* ip = fdp->data;
|
||||
if (ip->type != T_FILE) {
|
||||
if (ip->type != FS_FILE) {
|
||||
printf("read: %s Is not a file\n", fdp->path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
// Copyright (c) 2006-2018 Frans Kaashoek, Robert Morris, Russ Cox, Massachusetts Institute of Technology
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
/**
|
||||
* @file fs.h
|
||||
* @brief file system important struct definition
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2024-01-25
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: fs.h
|
||||
Description: file system important struct definition
|
||||
Others: take ARM_XV6 kernel/fs.h and kernel/file.h for references
|
||||
https://github.com/KingofHamyang/ARM_xv6
|
||||
History:
|
||||
1. Date: 2024-01-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. remove nlog member of superblock struct
|
||||
2. rebuild inode struct to fit XIZI_AIoT use sceneries
|
||||
3. change direct and indirect block number to fit XIZI_AIoT use sceneries
|
||||
*************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -33,19 +64,12 @@ struct MemFsRange {
|
||||
uint32_t memfs_nr_blocks;
|
||||
};
|
||||
|
||||
// current state of the Inode
|
||||
enum INODE_STATE {
|
||||
I_RESERVED = 0,
|
||||
I_BUSY,
|
||||
I_VALID
|
||||
};
|
||||
|
||||
// memfs file type
|
||||
enum FILE_TYPE {
|
||||
T_RESERVED = 0,
|
||||
T_DIR, // Directory
|
||||
T_FILE, // File
|
||||
T_DEV, // Device
|
||||
FS_RESERVED = 0,
|
||||
FS_DIRECTORY, // Directory
|
||||
FS_FILE, // File
|
||||
FS_DEVICE, // Device
|
||||
};
|
||||
|
||||
// File system super block
|
||||
@@ -55,20 +79,10 @@ struct SuperBlock {
|
||||
uint32_t ninodes; // Number of inodes.
|
||||
};
|
||||
|
||||
// state of the Inode
|
||||
struct State {
|
||||
short type; // Type of file
|
||||
int dev; // File system's disk device
|
||||
uint32_t ino; // Inode number
|
||||
short nlink; // Number of links to file
|
||||
uint32_t size; // Size of file in bytes
|
||||
};
|
||||
|
||||
// Inode structure
|
||||
struct Inode {
|
||||
uint32_t inum; // Inode number
|
||||
short type; // File type
|
||||
short nlink; // Number of links to Inode in file system
|
||||
uint32_t type; // File type
|
||||
uint32_t size; // Size of file (bytes)
|
||||
uint32_t addrs[NR_DIRECT_BLOCKS + NR_INDIRECT_BLOCKS]; // Data block addresses
|
||||
};
|
||||
@@ -85,7 +99,6 @@ struct DirectEntry {
|
||||
struct FileDescriptor {
|
||||
char path[MAX_PATH_LEN];
|
||||
void* data;
|
||||
struct State st;
|
||||
};
|
||||
|
||||
// range of memory fs
|
||||
@@ -96,10 +109,10 @@ void ReadSuperBlock(struct SuperBlock*);
|
||||
|
||||
// fs Inode ops
|
||||
struct Inode* InodeGet(uint32_t inum);
|
||||
struct Inode* InodeCreate(struct Inode*, char*, short, short, short);
|
||||
struct Inode* InodeCreate(struct Inode*, char*, int);
|
||||
int InodeDelete(struct Inode*, char*);
|
||||
int InodeRead(struct Inode*, char*, int, int);
|
||||
int InodeWrite(struct Inode*, char*, uint32_t, uint32_t);
|
||||
int InodeWrite(struct Inode*, char*, int, int);
|
||||
struct Inode* InodeSeek(struct Inode*, char*);
|
||||
struct Inode* InodeParentSeek(struct Inode*, char*, char*);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. Increse the number of blocks and inodes
|
||||
2. support more than one indirect blocks
|
||||
3. remove unused stat
|
||||
3. remove unused stat and nlink property of inode struct
|
||||
*************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
@@ -136,7 +136,7 @@ int main(int argc, char* argv[])
|
||||
wsect(1, buf);
|
||||
|
||||
// build root
|
||||
rootino = ialloc(T_DIR);
|
||||
rootino = ialloc(FS_DIRECTORY);
|
||||
assert(rootino == ROOT_INUM);
|
||||
|
||||
bzero(&de, sizeof(de));
|
||||
@@ -165,7 +165,7 @@ int main(int argc, char* argv[])
|
||||
if (argv[i][0] == '_')
|
||||
++argv[i];
|
||||
|
||||
inum = ialloc(T_FILE);
|
||||
inum = ialloc(FS_FILE);
|
||||
|
||||
bzero(&de, sizeof(de));
|
||||
de.inum = xshort(inum);
|
||||
@@ -251,7 +251,6 @@ uint ialloc(ushort type)
|
||||
|
||||
bzero(&din, sizeof(din));
|
||||
din.type = xshort(type);
|
||||
din.nlink = xshort(1);
|
||||
din.size = xint(0);
|
||||
din.inum = inum;
|
||||
winode(inum, &din);
|
||||
|
||||
@@ -37,14 +37,14 @@ History:
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. Increse the number of indirect blocks
|
||||
2. Rename some variables' name for readability
|
||||
2. Remove unused nlink of inode struct
|
||||
*************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define T_DIR 1 // Directory
|
||||
#define T_FILE 2 // File
|
||||
#define T_DEV 3 // Device
|
||||
#define FS_DIRECTORY 1 // Directory
|
||||
#define FS_FILE 2 // File
|
||||
#define FS_DEVICE 3 // Device
|
||||
|
||||
#define ROOT_INUM 1 // root inode number
|
||||
#define BLOCK_SIZE 512 // block size
|
||||
@@ -74,8 +74,7 @@ struct SuperBlock {
|
||||
// Inode structure
|
||||
struct Inode {
|
||||
uint inum; // inode number
|
||||
short type; // File type
|
||||
short nlink; // Number of links to inode in file system
|
||||
uint type; // File type
|
||||
uint size; // Size of file (bytes)
|
||||
uint addrs[NR_DIRECT_BLOCKS + NR_INDIRECT_BLOCKS]; // Data block addresses
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user