I've been making read() and write() functions. I also modified the file system driver functions.
This is new file system driver...
struct file_system_driver {
// check whether the device has file system
virtual bool check(blockdev::block_device *device) = 0;
// Get the physical location of root directory
virtual bool get_root_directory(physical_file_location &file_loc) = 0;
// Create new file
virtual bool create(const general_file_name file_name , word file_type) = 0;
// Get file handle by file name
virtual file_info *get_file_handle(const general_file_name file_name) = 0;
// remove the file by file name
virtual bool remove(const general_file_name file_name) = 0;
// Rename the file
virtual bool rename(const general_file_name file_name , const char *new_file_name) = 0;
// Move the file
virtual bool move(const general_file_name file_name , file_info *new_directory) = 0;
// Read a block of the file
virtual bool read_block(file_info *file , max_t file_block_addr , void *buffer) = 0;
// Write to a block of file
virtual bool write_block(file_info *file , max_t file_block_addr , const void *buffer) = 0;
// Allocate a new block to file
virtual max_t allocate_new_block(file_info *file) = 0;
// Get physical block address of the file
virtual max_t get_phys_block_address(file_info *file , max_t offset) = 0;
// Read the directory
virtual int read_directory(file_info *file , max_t cursor) = 0;
char fs_string[32];
};
I just rejected the idea of function pointer, as it is quite cumbersome to deal with. I also added some functions like read_block(), write_block() and removed some functions like read(), write() and lseek().
File open, read and write management is now dealt by Virtual File System functions, and low-level read/write/open is dealt by File System Driver. Especially, allocate_new_block creates new space for a file, read_block reads a block of a file, and so on.
I added a list that contains who opened the file. The list is in the file_info structure. The object in the list contains the task id, flag used to open the file and the current cursor.
typedef struct file_info_s {
char file_name[FILE_NAME_SIZE]; /* Doesn't contain the path, only contains the name of itself */
word file_type; /* FILE_TYPE_ */
max_t file_size;
/* For tree structure */
file_info_s *parent_dir;
// cached
ObjectLinkedList *file_lists; /* only for directory */
/* physical information */
bool is_mounted;
physical_file_location file_loc_info;
physical_file_location mount_loc_info;
ObjectLinkedList *who_open_list;
...
}
I also created a system that makes a cache for every block of file that is accessed or written. The block buffer is stored with its block number in the cache. I used the Hash Table to maintain the cache objects(object that contains buffer pointer and block location), because the cache objects need to be find by the block location.
// block_cache_t : Cache of one block, contains cached block data and some other informations.
typedef struct block_cache_s {
// flushed == true : the contents of the cache is the same as contents in the disk
bool flushed = true;
void *block;
max_t block_size;
}block_cache_t;
typedef struct file_info_s {
char file_name[FILE_NAME_SIZE]; /* Doesn't contain the path, only contains the name of itself */
word file_type; /* FILE_TYPE_ */
max_t file_size;
/* For tree structure */
file_info_s *parent_dir;
// cached
ObjectLinkedList *file_lists; /* only for directory */
/* physical information */
bool is_mounted;
physical_file_location file_loc_info;
physical_file_location mount_loc_info;
ObjectLinkedList *who_open_list;
// Hash table for file buffer
// Key value : Block location
HashTable *disk_buffer_hash_table;
}file_info;
(I will also make a function that flushes all the cached data into disk. )
The problem here is the unit of block. Should the unit of block be one unit from file system(like cluster) or one unit from block device? (a sector) The advantage of using sector as a unit of block is that we no longer need read_block and write_block function because we can directly use the functions that block device driver provides. The disadvantage, however, is that it might get pretty complicated dealing only with a unit of sector(idk. this is speculation.) On the other hand, the advantage of using file-system dependent unit of block is that it reduces some complications on the process. The disadvantage is that the code might get also complicated... idk
I will use (for now) sector as unit of caching. I think it will make my life bit easier. If not, I'm gonna just revert it and use the file system-dependent unit. idk.
By the way, the implementation of cache system will be soon committed to github. Stay tuned..