Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@

# debug information files
*.dwo
test_dir/*
data/*
build/*
32 changes: 29 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,33 @@ project(FastDevFS)
find_package(PkgConfig REQUIRED)
pkg_check_modules(FUSE3 REQUIRED fuse3)

add_executable(FastDevFS main.cpp)
target_include_directories(FastDevFS PRIVATE ${FUSE3_INCLUDE_DIRS})

add_executable(FastDevFS
main.cpp

src/src/fuse_functions/getattr.cpp
src/src/fuse_functions/readdir.cpp
src/src/fuse_functions/opendir.cpp
src/src/fuse_functions/mkdir.cpp
src/src/fuse_functions/rmdir.cpp
src/src/fuse_functions/access.cpp
src/src/fuse_functions/statfs.cpp
src/src/fuse_functions/file_funcs.cpp
src/src/fuse_functions/utimens.cpp

src/src/daemon/dir_manager.cpp
src/src/daemon/hash.cpp
src/src/daemon/file_io.cpp
src/src/config.cpp
)

target_include_directories(FastDevFS PRIVATE
${FUSE3_INCLUDE_DIRS}
${CMAKE_SOURCE_DIR}/src/include
)

target_link_libraries(FastDevFS PRIVATE ${FUSE3_LIBRARIES})
target_compile_options(FastDevFS PRIVATE ${FUSE3_CFLAGS_OTHER})
target_compile_options(FastDevFS PRIVATE ${FUSE3_CFLAGS_OTHER})

enable_testing()
add_subdirectory(test)
Binary file added dir_tree.dat
Binary file not shown.
2 changes: 2 additions & 0 deletions fdfs.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dedup=true
data_dir=./data
Binary file added hash_table.dat
Binary file not shown.
218 changes: 197 additions & 21 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,200 @@
#include<fuse3/fuse.h>
#include<iostream>
// #define FUSE_USE_VERSION 31

// #include<fuse3/fuse.h>
// #include<iostream>
// #include "src/include/fuse_functions/getattr.h"
// #include "src/include/fuse_functions/readdir.h"
// #include "src/include/fuse_functions/opendir.h"

// using namespace std;

// // int get_attr(const char* path, struct stat* stbuf, struct fuse_file_info* fi){
// // cout<<"getattr called for path: "<<path<<endl;
// // // Implementation of getattr would go here
// // return 0;
// // }
// // int readdir(const char* path, void* buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info* fi, enum fuse_readdir_flags flags){
// // cout<<"readdir called for path: "<<path<<endl;
// // // Implementation of readdir would go here
// // return 0;
// // }

// static struct fuse_operations fastdevfs_oper = {
// // .getattr = get_attr,
// // .readdir = readdir,
// .getattr = fastdevfs_getattr,
// .opendir = fastdevfs_opendir,
// .readdir = fastdevfs_readdir,
// };
// int main(int argc, char* argv[]){
// cout<<"Starting FastDevFs Daemon..."<<endl;
// // Initialization code for FastDevFs would go here

// return fuse_main(argc, argv, &fastdevfs_oper, NULL);
// }



#define FUSE_USE_VERSION 31

#include <fuse3/fuse.h>
#include <iostream>

#include "daemon/dir_manager.h"
#include "daemon/hash.h"
#include "daemon/file_io.h"
#include "fuse_functions/getattr.h"
#include "fuse_functions/readdir.h"
#include "fuse_functions/opendir.h"
#include "fuse_functions/mkdir.h"
#include "fuse_functions/rmdir.h"
#include "fuse_functions/access.h"
#include "fuse_functions/statfs.h"
#include "fuse_functions/file_funcs.h"
#include "fuse_functions/utimens.h"
#include "sys/mman.h"
#include "config.h"
#include <unistd.h>
using namespace std;
#define DIR_TREE_FILE "dir_tree.dat"
#define HASH_TABLE_FILE "hash_table.dat"

/*
* Global DirManager instance.
* Used by all FUSE callbacks.
*/
DirManager* g_dir_manager = nullptr;

static struct fuse_operations fdfs_ops;
extern FSConfig g_config;
// static struct fuse_operations fdfs_ops = {
// .getattr = fdfs_getattr,
// .readdir = fdfs_readdir,
// .opendir = fdfs_opendir,
// // .mkdir = fdfs_mkdir,
// // .rmdir = fdfs_rmdir,
// // .access = fdfs_access,
// // .statfs = fdfs_statfs,

// // // safety stubs
// // .open = fdfs_open,
// // .read = fdfs_read,
// // .write = fdfs_write,
// // .create = fdfs_create,
// // .unlink = fdfs_unlink,
// // .truncate = fdfs_truncate,

// // // metadata no-ops
// // .chmod = fdfs_chmod,
// // .chown = fdfs_chown,
// // .utimens = fdfs_utimens,
// };


int main(int argc, char* argv[]) {
cout << "Starting FastDevFS Daemon..." << endl;

// Initialize DirManager with mmap
int fd = open(DIR_TREE_FILE, O_RDWR | O_CREAT, 0644);
if (fd < 0) {
perror("open");
exit(1);
}

size_t dir_manager_size = sizeof(DirManager);

/* ensure file size */
if (ftruncate(fd, dir_manager_size) < 0) {
perror("ftruncate");
exit(1);
}

/* mmap - maps DirManager to shared memory */
g_dir_manager = (DirManager*) mmap(
NULL,
dir_manager_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0
);

if (g_dir_manager == MAP_FAILED) {
perror("mmap");
exit(1);
}

// Initialize directory ADT only if not already initialized
if (!is_dir_manager_initialized(g_dir_manager)) {
dir_manager_init(g_dir_manager);
}

// Initialize data directory for file storage
if (init_data_dir() < 0) {
cerr << "Failed to initialize data directory" << endl;
exit(1);
}

// Initialize HashTable with separate mmap
int hash_fd = open(HASH_TABLE_FILE, O_RDWR | O_CREAT, 0644);
if (hash_fd < 0) {
perror("open hash_table");
exit(1);
}

size_t hash_table_size = sizeof(HashTable);

/* ensure file size */
if (ftruncate(hash_fd, hash_table_size) < 0) {
perror("ftruncate hash_table");
exit(1);
}

/* mmap - maps HashTable to shared memory */
g_hash_table = (HashTable*) mmap(
NULL,
hash_table_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
hash_fd,
0
);

if (g_hash_table == MAP_FAILED) {
perror("mmap hash_table");
exit(1);
}

// Initialize hash table only if not already initialized
if (g_hash_table->magic != HASH_TABLE_MAGIC) {
hash_init(g_hash_table);
}

// basic fuse_functions
fdfs_ops.getattr = fdfs_getattr;
fdfs_ops.opendir = fdfs_opendir;
fdfs_ops.readdir = fdfs_readdir;
fdfs_ops.mkdir = fdfs_mkdir;
fdfs_ops.rmdir = fdfs_rmdir;
fdfs_ops.access = fdfs_access;
fdfs_ops.statfs = fdfs_statfs;

// file ops
fdfs_ops.open = fdfs_open;
fdfs_ops.read = fdfs_read;
fdfs_ops.write = fdfs_write;
fdfs_ops.create = fdfs_create;
fdfs_ops.unlink = fdfs_unlink;
fdfs_ops.truncate = fdfs_truncate;
fdfs_ops.utimens = fdfs_utimens;

int get_attr(const char* path, struct stat* stbuf, struct fuse_file_info* fi){
cout<<"getattr called for path: "<<path<<endl;
// Implementation of getattr would go here
return 0;
}
int readdir(const char* path, void* buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info* fi, enum fuse_readdir_flags flags){
cout<<"readdir called for path: "<<path<<endl;
// Implementation of readdir would go here
return 0;
}
static struct fuse_operations fastdevfs_oper = {
.getattr = get_attr,
.readdir = readdir,
};
int main(int argc, char* argv[]){
cout<<"Starting FastDevFs Daemon..."<<endl;
// Initialization code for FastDevFs would go here

return fuse_main(argc, argv, &fastdevfs_oper, NULL);
// load config
load_config("/home/diya_limbani/FastDevFs/fdfs.conf");
if(g_config.dedup_enabled) {
// to do
}else{
cout<<"WARN: We are not using dedup-thread. This can lead to higher memory usage.";
}
// Start FUSE
return fuse_main(argc, argv, &fdfs_ops, nullptr);
}
11 changes: 11 additions & 0 deletions src/include/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once
#include <string>

struct FSConfig {
bool dedup_enabled = false;
std::string data_dir = "data";
};

extern FSConfig g_config;

bool load_config(const std::string path);
47 changes: 47 additions & 0 deletions src/include/daemon/dir_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include <stdbool.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "daemon/hash.h"

#define MAX_NODES 10000
#define NAME_SIZE 256
#define DIR_MANAGER_MAGIC 0xDEADBEEF

typedef struct DirNode {
char name[NAME_SIZE];
int parent;
int first_child;
int next_sibling;

mode_t mode; // file type + permissions
uid_t uid;
gid_t gid;
off_t size;
time_t atime;
time_t mtime;
time_t ctime;
nlink_t nlink;

bool in_use;
int next_free;
} DirNode;

typedef struct DirManager {
unsigned int magic; // Magic number to detect initialization
DirNode nodes[MAX_NODES];
int root;
int free_list;
pthread_rwlock_t rwlock;
} DirManager;

// API
void dir_manager_init(DirManager* dm);
int insert_node(DirManager* dm, const char* path);
int lookup_node(DirManager* dm, const char* path);
int lookup_node_nolock(DirManager* dm, const char* path);
bool remove_node(DirManager* dm, const char* path);
bool is_dir_manager_initialized(DirManager* dm);
59 changes: 59 additions & 0 deletions src/include/daemon/file_io.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#pragma once

#include <sys/types.h>

// Data directory for storing file contents (will be set to absolute path)
extern char g_data_dir_path[512];

// Helper functions for file I/O operations
// These functions handle reading/writing file data to the host filesystem
// using inode numbers as filenames

/**
* Get the path to the data file for a given inode
* @param inode The inode number
* @param path_buf Buffer to store the constructed path
* @param buf_size Size of the buffer
*/
void get_data_file_path(int inode, char* path_buf, size_t buf_size);

/**
* Read data from the host filesystem for a given inode
* @param inode The inode number
* @param buf Buffer to read data into
* @param size Number of bytes to read
* @param offset Offset to start reading from
* @return Number of bytes read, or -1 on error
*/
ssize_t read_inode_data(int inode, char* buf, size_t size, off_t offset);

/**
* Write data to the host filesystem for a given inode
* @param inode The inode number
* @param buf Buffer containing data to write
* @param size Number of bytes to write
* @param offset Offset to start writing at
* @return Number of bytes written, or -1 on error
*/
ssize_t write_inode_data(int inode, const char* buf, size_t size, off_t offset);

/**
* Truncate the data file for a given inode
* @param inode The inode number
* @param new_size New size for the file
* @return 0 on success, -1 on error
*/
int truncate_inode_data(int inode, off_t new_size);

/**
* Delete the data file for a given inode
* @param inode The inode number
* @return 0 on success, -1 on error
*/
int delete_inode_data(int inode);

/**
* Initialize the data directory
* @return 0 on success, -1 on error
*/
int init_data_dir();
Loading