Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fast_fuse:添加删除功能 #871

Merged
merged 10 commits into from
Jul 30, 2024
Next Next commit
fuse文件系统示例
qcloud committed Jun 6, 2024
commit 0e2caea773e6b1574ee351a9bf561db85ffae96b
32 changes: 32 additions & 0 deletions eBPF_Supermarket/Filesystem_Subsystem/fast_fuse/difuse/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# DIFUSE

## 代码结构

```
.
├── README.md
├── src
│ ├── difuse.c 源码
│ ├── Makefile
│ └── mountpoints 挂载目录
└── test
└── test.sh 测试脚本
```



## Build

在`src`目录下执行`make`

```bash
cd src
make
```

在`test`目录下执行`test`脚本

```bash
cd test
./test.sh
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Makefile for FUSE difuse example

# Compiler
CC = gcc

# Compiler flags
CFLAGS = -Wall `pkg-config fuse3 --cflags`

# Linker flags
LDFLAGS = `pkg-config fuse3 --libs`

# Source files
SRCS = difuse.c

# Output executable
TARGET = difuse

# Build target
all: $(TARGET)

# Rule to build the target
$(TARGET): $(SRCS)
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LDFLAGS)

# Clean rule
clean:
rm -f $(TARGET)

.PHONY: all clean
231 changes: 231 additions & 0 deletions eBPF_Supermarket/Filesystem_Subsystem/fast_fuse/difuse/src/difuse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
#define FUSE_USE_VERSION 31

#include <fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <assert.h>
#include <errno.h>

/*相关数据结构*/

#define FILE_TYPE 1
#define DIRECTORY_TYPE 2


struct dfs_data
{
int chunk_size;
size_t size;
struct dfs_data *next;
};

struct dfs_inode
{
uint32_t ino; //inode编号
int size; //文件大小
int dir_cnt; // 如果是目录类型文件,下面有几个目录项
struct dfs_data *data_pointer; //指向数据块的指针
};

struct dfs_dentry
{
char fname[255];
int ftype;
struct dfs_dentry *parent;
struct dfs_dentry *brother;
struct dfs_dentry *child;
struct dfs_inode *inode; //指向对应的inode
};

struct dfs_dentry *root; //根节点

/*过程函数*/
static struct dfs_inode *new_inode(uint32_t ino, int size, int dir_cnt)
{
struct dfs_inode *inode = (struct dfs_inode *)malloc(sizeof(struct dfs_inode));
inode->ino = ino;
inode->size = size;
inode->dir_cnt = dir_cnt;
inode->data_pointer = NULL;
return inode;
}

static struct dfs_dentry *new_dentry(char *fname, int ftype, struct dfs_dentry *parent, struct dfs_inode *inode)
{
struct dfs_dentry *dentry = (struct dfs_dentry *)malloc(sizeof(struct dfs_dentry));
strcpy(dentry->fname, fname);
dentry->inode = inode;
dentry->brother = NULL;
dentry->parent = parent;
dentry->child = NULL;
dentry->ftype = ftype;
return dentry;
}

void add_child_dentry(struct dfs_dentry *parent, struct dfs_dentry *child)
{
child->brother = parent->child;
parent->child = child;
}

struct dfs_dentry *look_up(struct dfs_dentry *dentrys, const char *path)
{
struct dfs_dentry *dentry = dentrys;
char *path_copy = strdup(path);
char *token = strtok(path_copy, "/");
while (token != NULL && dentry != NULL)
{
struct dfs_dentry *child = dentry->child;
while (child != NULL && strcmp(child->fname, token) != 0)
{
child = child->brother;
}
dentry = child;
token = strtok(NULL, "/");
}

free(path_copy);
return dentry;
}


/*功能函数*/

static int di_getattr(const char *path, struct stat *di_stat,
struct fuse_file_info *fi)
{
(void)fi;
int ret = 0;
memset(di_stat, 0, sizeof(struct stat));

struct dfs_dentry *dentry = look_up(root, path);
if (dentry == NULL)
return -ENOENT;

if (dentry->ftype == DIRECTORY_TYPE)
{
di_stat->st_mode = S_IFDIR | 0755;
di_stat->st_nlink = 2;
}
else if (dentry->ftype == FILE_TYPE)
{
di_stat->st_mode = S_IFREG | 0644;
di_stat->st_nlink = 1;
di_stat->st_size = dentry->inode->size;
}

return ret;
}

/*遍历目录项*/
static int di_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
(void)fi;
(void)offset;
struct dfs_dentry *dentry = look_up(root, path);

if (dentry == NULL)
return -ENOENT;

if (dentry->ftype != DIRECTORY_TYPE)
return -ENOTDIR;

filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0, 0);

struct dfs_dentry *child = dentry->child;
while (child != NULL)
{
filler(buf, child->fname, NULL, 0, 0);
child = child->brother;
}

return 0;
}

static int di_open(const char *path, struct fuse_file_info *fi)
{
struct dfs_dentry *dentry = look_up(root, path);

if (dentry == NULL)
return -ENOENT;

if (dentry->ftype != FILE_TYPE)
return -EISDIR;

return 0;
}

/*
确保我们尝试从文件中读取的起始位置(偏移量)在文件范围内。
如果偏移量超出了文件内容的长度,说明请求读取的位置在文件的末尾或之后,这种情况下不能读取任何数据。
*/
static int di_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
struct dfs_dentry *dentry = look_up(root, path);

if (dentry == NULL)
return -ENOENT;

if (dentry->ftype != FILE_TYPE)
return -EISDIR;

if (offset < dentry->inode->size)
{
if (offset + size > dentry->inode->size)
size = dentry->inode->size - offset;
memcpy(buf, "dummy_content", size); // Replace with actual file data handling
}
else
size = 0;

return size;
}


static struct fuse_operations difs_ops = {
.readdir = di_readdir,
.getattr = di_getattr,
.open = di_open,
.read = di_read,
//.mkdir = di_mkdir,
};

int main(int argc, char *argv[])
{
struct dfs_inode *root_inode = new_inode(1, 0, 2);
root = new_dentry("/", DIRECTORY_TYPE, NULL, root_inode);

// 创建dir1目录
struct dfs_inode *dir1_inode = new_inode(2, 0, 2);
struct dfs_dentry *dir1 = new_dentry("dir1", DIRECTORY_TYPE, root, dir1_inode);
add_child_dentry(root, dir1);

// 创建dir2目录
struct dfs_inode *dir2_inode = new_inode(3, 0, 1);
struct dfs_dentry *dir2 = new_dentry("dir2", DIRECTORY_TYPE, root, dir2_inode);
add_child_dentry(root, dir2);

// 创建file1文件
struct dfs_inode *file1_inode = new_inode(4, 100, 0);
struct dfs_dentry *file1 = new_dentry("file1", FILE_TYPE, dir1, file1_inode);
add_child_dentry(dir1, file1);

// 创建file2文件
struct dfs_inode *file2_inode = new_inode(5, 200, 0);
struct dfs_dentry *file2 = new_dentry("file2", FILE_TYPE, dir1, file2_inode);
add_child_dentry(dir1, file2);

// 创建file3文件
struct dfs_inode *file3_inode = new_inode(6, 150, 0);
struct dfs_dentry *file3 = new_dentry("file3", FILE_TYPE, dir2, file3_inode);
add_child_dentry(dir2, file3);

return fuse_main(argc, argv, &difs_ops, NULL);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/bin/bash

# 挂载点目录
MOUNT_POINT="../src/mountpoints"
SRC_DIR="../src"

# FUSE 可执行文件
FUSE_EXEC="../src/difuse"

echo "Compiling FUSE filesystem..."
make -C "$SRC_DIR" clean
make -C "$SRC_DIR" all

# 检查编译是否成功
if [ ! -f "$FUSE_EXEC" ]; then
echo "Compilation failed. Exiting."
exit 1
fi

# 创建挂载点目录(如果不存在)
if [ ! -d "$MOUNT_POINT" ]; then
mkdir -p "$MOUNT_POINT"
fi

# 挂载 FUSE 文件系统(前台运行并显示调试信息)
echo "Mounting FUSE filesystem..."
$FUSE_EXEC -f -d "$MOUNT_POINT" &
FUSE_PID=$!
sleep 1 # 等待文件系统完全挂载

# 测试读取根目录
echo "Testing readdir on root..."
ls "$MOUNT_POINT"

# 测试读取子目录 dir1
echo "Testing readdir on dir1..."
ls "$MOUNT_POINT/dir1"

# 测试读取子目录 dir2
echo "Testing readdir on dir2..."
ls "$MOUNT_POINT/dir2"

# 测试读取文件 file1
echo "Testing read file1..."
cat "$MOUNT_POINT/dir1/file1"

# 测试读取文件 file2
echo "Testing read file2..."
cat "$MOUNT_POINT/dir1/file2"

# 测试读取文件 file3
echo "Testing read file3..."
cat "$MOUNT_POINT/dir2/file3"

# 测试打开文件
echo "Testing open file..."
if [ -e "$MOUNT_POINT/dir1/file1" ]; then
echo "File 'file1' exists in dir1"
else
echo "File 'file1' does not exist in dir1"
fi

if [ -e "$MOUNT_POINT/dir1/file2" ]; then
echo "File 'file2' exists in dir1"
else
echo "File 'file2' does not exist in dir1"
fi

if [ -e "$MOUNT_POINT/dir2/file3" ]; then
echo "File 'file3' exists in dir2"
else
echo "File 'file3' does not exist in dir2"
fi

# 显示调试日志
echo "FUSE debug log:"
kill -USR1 $FUSE_PID
sleep 1 # 等待日志输出

# 卸载 FUSE 文件系统
echo "Unmounting FUSE filesystem..."
sudo fusermount -u "$MOUNT_POINT"

# 等待 FUSE 进程终止
wait $FUSE_PID

echo "All tests completed."