파일 시스템 내에서 동기화를 위해 lock을 사용하려 한다. 우선 filesys_init에서 lock을 초기화 해준다.
void
filesys_init (bool format) {
filesys_disk = disk_get (0, 1);
if (filesys_disk == NULL)
PANIC ("hd0:1 (hdb) not present, file system initialization failed");
inode_init ();
lock_init(&filesys_lock);
#ifdef EFILESYS
fat_init ();
if (format)
do_format ();
fat_open ();
init_fat_bitmap();
#else
/* Original FS */
free_map_init ();
if (format)
do_format ();
free_map_open ();
#endif
}
그리고 파일 시스템의 세부 동작들 마다 lock을 걸어준다.
bool
filesys_create (const char *name, off_t initial_size) {
bool success = false;
lock_acquire(&filesys_lock);
// Parse path and get directory
struct path* path = parse_filepath(name);
if(path->dircount==-1) { // create-empty, create-long
goto done_lock;
}
struct dir* dir = find_subdir(path->dirnames, path->dircount);
if(dir == NULL) {
goto done;
}
struct inode *inode = NULL;
if(dir_lookup(dir, path->filename, &inode)){ // create-exists (trying to create file that already exists)
goto done;
}
disk_sector_t inode_sector = 0;
// struct dir *dir = dir_open_root ();
#ifdef EFILESYS
cluster_t clst = fat_create_chain(0);
if(clst == 0){ // FAT is full (= disk is full)
goto done;
}
inode_sector = cluster_to_sector(clst);
success = (dir != NULL
&& inode_create (inode_sector, initial_size, false)
&& dir_add (dir, path->filename, inode_sector));
if (!success)
fat_remove_chain (inode_sector, 0);
// struct path path = parse_filepath(name);
// struct dir *dir = dir_open(find_subdir(path.dirnames, path.dircount));
// create?
#else
success = (dir != NULL
&& free_map_allocate (1, &inode_sector)
&& inode_create (inode_sector, initial_size, false)
&& dir_add (dir, name, inode_sector));
if (!success && inode_sector != 0)
free_map_release (inode_sector, 1);
#endif
done:
dir_close (dir);
free_path(path);
done_lock:
lock_release(&filesys_lock);
return success;
}
struct file *
filesys_open (const char *name) {
lock_acquire(&filesys_lock);
// Parse path and get directory
struct path* path = parse_filepath(name);
if(path->dircount==-1) { // open-empty
lock_release(&filesys_lock);
return NULL;
}
struct dir* dir = find_subdir(path->dirnames, path->dircount);
if(dir == NULL) {
dir_close (dir);
free_path(path);
lock_release(&filesys_lock);
return NULL;
}
if (path->filename == "root"){ // open "/"
lock_release(&filesys_lock);
return file_open(inode_open (cluster_to_sector(1)));
}
// struct dir *dir = dir_open_root ();
struct inode *inode = NULL;
if (dir != NULL)
dir_lookup (dir, path->filename, &inode);
struct file *file = file_open (inode);
dir_close (dir);
free_path(path);
lock_release(&filesys_lock);
return file;
}
bool
filesys_remove (const char *name) {
bool success = false;
lock_acquire(&filesys_lock);
// Parse path and get directory
struct path* path = parse_filepath(name);
if(path->dircount==-1) {
goto done_lock;
}
struct dir* dir = find_subdir(path->dirnames, path->dircount);
if(dir == NULL) {
goto done;
}
// Check if the target is open (dir-rm-cwd)
struct inode *inode = NULL;
dir_lookup(dir, path->filename, &inode);
// if(inode == NULL || (inode_isdir(inode) && inode->open_cnt > 2)){ // only dir can't be closed when open (dir-rm-cwd vs syn-remove)
if(inode == NULL){ // only dir can't be closed when open (dir-rm-cwd vs syn-remove)
goto done;
}
//printf("isDir? %d / openCnt %d\\n", inode->data.isdir, inode->open_cnt);
struct dir *cwd = current_directory();
if(cwd->inode == inode)
set_current_directory(NULL);
// struct dir *dir = dir_open_root ();
success = dir != NULL && dir_remove (dir, path->filename);
done:
dir_close (dir);
free_path(path);
done_lock:
lock_release(&filesys_lock);
return success;
}