Shark File System Lab

Author: ZT

In the given test cases, each thread operates on a file using a single int fd. This fd can be used to obtain an sfs_mem_filedesc_t object through openFileDescTable[fd]. Similarly, a v-node can be obtained through fileEntry, and a block can be accessed via superBlock.file[i].

First, we need to implement a few functions that are not yet implemented: sfs_getpos, sfs_seek, and sfs_rename. These three functions are relatively easy to implement. Next, let's explain the mutex locking and unlocking mechanism for multi-threaded reading and writing in the file system.

Then, complete the global lock global_lock to ensure that an event is atomic during multi-threaded read and write operations. It is not required to isolate files, nor to separate read and write operations, or to prevent interference between multiple read operations. Only thread-safe functionality is required, which only needs a global lock.

static pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;

Afterwards, add the global lock at the beginning and release it at the end for the following functions: sfs_open, sfs_close, sfs_read, sfs_write, sfs_getpos, sfs_seek, sfs_remove, sfs_rename, and sfs_list.

Once thread safety is ensured, you can introduce file descriptor (fd) locks. The fd locks can guarantee the atomicity of each file operation but cannot ensure simultaneous writes by multiple threads. Therefore, node locks should also be added. Details are as follows:

// To destory lock, we need to acquire lock...
pthread_mutex_lock(&tFile->fd_lock);
pthread_mutex_unlock(&tFile->fd_lock);
pthread_mutex_destroy(&tFile->fd_lock);
fileEntry->refCount--;
if (fileEntry->refCount > 0){
    pthread_mutex_unlock(&global_lock);
    return;
}else if(fileEntry->refCount == 0){
    pthread_mutex_lock(&fileEntry->node_lock);
    pthread_mutex_unlock(&fileEntry->node_lock);
    pthread_mutex_destroy(&fileEntry->node_lock);
}
pthread_mutex_unlock(&tFile->fileEntry->node_lock);
pthread_mutex_unlock(&tFile->fd_lock);