|
@@ -1,16 +1,16 @@
|
|
|
#include "VFS.h"
|
|
|
-#include "mount.h"
|
|
|
#include "internal.h"
|
|
|
-#include <common/kprint.h>
|
|
|
-#include <debug/bug.h>
|
|
|
+#include "mount.h"
|
|
|
#include <common/dirent.h>
|
|
|
-#include <common/string.h>
|
|
|
#include <common/errno.h>
|
|
|
+#include <common/kprint.h>
|
|
|
+#include <common/string.h>
|
|
|
+#include <debug/bug.h>
|
|
|
+#include <filesystem/rootfs/rootfs.h>
|
|
|
#include <mm/mm.h>
|
|
|
#include <mm/slab.h>
|
|
|
-#include <process/ptrace.h>
|
|
|
#include <process/process.h>
|
|
|
-#include <filesystem/rootfs/rootfs.h>
|
|
|
+#include <process/ptrace.h>
|
|
|
|
|
|
// 为filesystem_type_t结构体实例化一个链表头
|
|
|
static struct vfs_filesystem_type_t vfs_fs = {"filesystem", 0};
|
|
@@ -77,12 +77,12 @@ uint64_t vfs_register_filesystem(struct vfs_filesystem_type_t *fs)
|
|
|
for (p = &vfs_fs; p; p = p->next)
|
|
|
{
|
|
|
if (!strcmp(p->name, fs->name)) // 已经注册相同名称的文件系统
|
|
|
- return VFS_E_FS_EXISTED;
|
|
|
+ return -EEXIST;
|
|
|
}
|
|
|
|
|
|
fs->next = vfs_fs.next;
|
|
|
vfs_fs.next = fs;
|
|
|
- return VFS_SUCCESS;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
uint64_t vfs_unregister_filesystem(struct vfs_filesystem_type_t *fs)
|
|
@@ -94,12 +94,12 @@ uint64_t vfs_unregister_filesystem(struct vfs_filesystem_type_t *fs)
|
|
|
{
|
|
|
p->next = p->next->next;
|
|
|
fs->next = NULL;
|
|
|
- return VFS_SUCCESS;
|
|
|
+ return 0;
|
|
|
}
|
|
|
else
|
|
|
p = p->next;
|
|
|
}
|
|
|
- return VFS_E_FS_NOT_EXIST;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -245,6 +245,7 @@ int vfs_fill_dirent(void *buf, ino_t d_ino, char *name, int namelen, unsigned ch
|
|
|
int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland)
|
|
|
{
|
|
|
uint32_t pathlen;
|
|
|
+ int retval = 0;
|
|
|
if (from_userland)
|
|
|
pathlen = strnlen_user(path, PAGE_4K_SIZE - 1);
|
|
|
else
|
|
@@ -296,30 +297,57 @@ int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland)
|
|
|
kwarn("Dir '%s' aleardy exists.", path);
|
|
|
return -EEXIST;
|
|
|
}
|
|
|
-
|
|
|
+ spin_lock(&parent_dir->lockref.lock);
|
|
|
struct vfs_dir_entry_t *subdir_dentry = vfs_alloc_dentry(pathlen - last_slash);
|
|
|
|
|
|
if (path[pathlen - 1] == '/')
|
|
|
subdir_dentry->name_length = pathlen - last_slash - 2;
|
|
|
else
|
|
|
subdir_dentry->name_length = pathlen - last_slash - 1;
|
|
|
- memset((void *)subdir_dentry->name, 0, subdir_dentry->name_length + 1);
|
|
|
|
|
|
for (int i = last_slash + 1, cnt = 0; i < pathlen && cnt < subdir_dentry->name_length; ++i, ++cnt)
|
|
|
{
|
|
|
subdir_dentry->name[cnt] = path[i];
|
|
|
}
|
|
|
- ++subdir_dentry->name_length;
|
|
|
-
|
|
|
// kdebug("last_slash=%d", last_slash);
|
|
|
// kdebug("name=%s", path + last_slash + 1);
|
|
|
subdir_dentry->parent = parent_dir;
|
|
|
+
|
|
|
// kdebug("to mkdir, parent name=%s", parent_dir->name);
|
|
|
- int retval = parent_dir->dir_inode->inode_ops->mkdir(parent_dir->dir_inode, subdir_dentry, 0);
|
|
|
- list_append(&parent_dir->subdirs_list, &subdir_dentry->child_node_list);
|
|
|
- // kdebug("retval = %d", retval);
|
|
|
- return 0;
|
|
|
+ spin_lock(&parent_dir->dir_inode->lockref.lock);
|
|
|
+ retval = parent_dir->dir_inode->inode_ops->mkdir(parent_dir->dir_inode, subdir_dentry, 0);
|
|
|
+ spin_unlock(&parent_dir->dir_inode->lockref.lock);
|
|
|
+
|
|
|
+ if (retval != 0)
|
|
|
+ {
|
|
|
+ if (vfs_dentry_put(parent_dir) != 0) // 释放dentry
|
|
|
+ spin_unlock(&parent_dir->lockref.lock);
|
|
|
+ return retval;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取append前一个dentry并加锁
|
|
|
+ struct List *target_list = &parent_dir->subdirs_list;
|
|
|
+ // kdebug("target_list=%#018lx target_list->prev=%#018lx",target_list,target_list->prev);
|
|
|
+ if (list_empty(target_list) == false)
|
|
|
+ {
|
|
|
+ struct vfs_dir_entry_t *prev_dentry = list_entry(target_list->prev, struct vfs_dir_entry_t, child_node_list);
|
|
|
+ // kdebug("prev_dentry%#018lx",prev_dentry);
|
|
|
+ spin_lock(&prev_dentry->lockref.lock);
|
|
|
+ list_append(&parent_dir->subdirs_list, &subdir_dentry->child_node_list);
|
|
|
+ // kdebug("retval = %d", retval);
|
|
|
+ spin_unlock(&prev_dentry->lockref.lock);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ list_append(&parent_dir->subdirs_list, &subdir_dentry->child_node_list);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+out:;
|
|
|
+ spin_unlock(&parent_dir->lockref.lock);
|
|
|
+ return retval;
|
|
|
}
|
|
|
+
|
|
|
/**
|
|
|
* @brief 创建文件夹
|
|
|
*
|
|
@@ -351,13 +379,9 @@ uint64_t do_open(const char *filename, int flags)
|
|
|
long path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1;
|
|
|
|
|
|
if (path_len <= 0) // 地址空间错误
|
|
|
- {
|
|
|
return -EFAULT;
|
|
|
- }
|
|
|
else if (path_len >= PAGE_4K_SIZE) // 名称过长
|
|
|
- {
|
|
|
return -ENAMETOOLONG;
|
|
|
- }
|
|
|
|
|
|
// 为待拷贝文件路径字符串分配内存空间
|
|
|
char *path = (char *)kzalloc(path_len, 0);
|
|
@@ -394,17 +418,17 @@ uint64_t do_open(const char *filename, int flags)
|
|
|
{
|
|
|
|
|
|
path[tmp_index] = '\0';
|
|
|
- dentry = vfs_path_walk(path, 0);
|
|
|
- if (dentry == NULL)
|
|
|
+ parent_dentry = vfs_path_walk(path, 0);
|
|
|
+ if (parent_dentry == NULL)
|
|
|
{
|
|
|
kfree(path);
|
|
|
return -ENOENT;
|
|
|
}
|
|
|
- parent_dentry = dentry;
|
|
|
}
|
|
|
else
|
|
|
+ {
|
|
|
parent_dentry = vfs_root_sb->root;
|
|
|
-
|
|
|
+ }
|
|
|
// 创建新的文件
|
|
|
dentry = vfs_alloc_dentry(path_len - tmp_index);
|
|
|
|
|
@@ -412,28 +436,53 @@ uint64_t do_open(const char *filename, int flags)
|
|
|
strncpy(dentry->name, path + tmp_index + 1, dentry->name_length);
|
|
|
// kdebug("to create new file:%s namelen=%d", dentry->name, dentry->name_length)
|
|
|
dentry->parent = parent_dentry;
|
|
|
+
|
|
|
+ // 对父目录项加锁
|
|
|
+ spin_lock(&parent_dentry->lockref.lock);
|
|
|
+ spin_lock(&parent_dentry->dir_inode->lockref.lock);
|
|
|
+ // 创建子目录项
|
|
|
uint64_t retval = parent_dentry->dir_inode->inode_ops->create(parent_dentry->dir_inode, dentry, 0);
|
|
|
+ spin_unlock(&parent_dentry->dir_inode->lockref.lock); // 解锁inode
|
|
|
+
|
|
|
if (retval != 0)
|
|
|
{
|
|
|
- kfree(dentry->name);
|
|
|
- kfree(dentry);
|
|
|
+ if (vfs_dentry_put(dentry) != 0) // 释放dentry
|
|
|
+ BUG_ON(1);
|
|
|
+ BUG_ON(1);
|
|
|
kfree(path);
|
|
|
+ spin_unlock(&parent_dentry->lockref.lock);
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
- list_init(&dentry->child_node_list);
|
|
|
- list_init(&dentry->subdirs_list);
|
|
|
+ // ==== 将子目录项添加到链表 ====
|
|
|
+ struct vfs_dir_entry_t *next_dentry = NULL;
|
|
|
+ // 若list非空,则对前一个dentry加锁
|
|
|
+ if (!list_empty(&parent_dentry->subdirs_list))
|
|
|
+ {
|
|
|
+ next_dentry = list_entry(list_next(&parent_dentry->subdirs_list), struct vfs_dir_entry_t, child_node_list);
|
|
|
+ spin_lock(&next_dentry->lockref.lock);
|
|
|
+ }
|
|
|
list_add(&parent_dentry->subdirs_list, &dentry->child_node_list);
|
|
|
+ if (next_dentry != NULL)
|
|
|
+ spin_unlock(&next_dentry->lockref.lock);
|
|
|
+
|
|
|
+ // 新建文件结束,对父目录项解锁
|
|
|
+ spin_unlock(&parent_dentry->lockref.lock);
|
|
|
// kdebug("created.");
|
|
|
}
|
|
|
+
|
|
|
kfree(path);
|
|
|
if (dentry == NULL)
|
|
|
+ {
|
|
|
return -ENOENT;
|
|
|
-
|
|
|
+ }
|
|
|
+ spin_lock(&dentry->lockref.lock);
|
|
|
// 要求打开文件夹而目标不是文件夹
|
|
|
if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_IF_DIR))
|
|
|
+ {
|
|
|
+ spin_unlock(&dentry->lockref.lock);
|
|
|
return -ENOTDIR;
|
|
|
-
|
|
|
+ }
|
|
|
// 创建文件描述符
|
|
|
struct vfs_file_t *file_ptr = (struct vfs_file_t *)kzalloc(sizeof(struct vfs_file_t), 0);
|
|
|
|
|
@@ -448,9 +497,10 @@ uint64_t do_open(const char *filename, int flags)
|
|
|
if (file_ptr->file_ops && file_ptr->file_ops->open)
|
|
|
errcode = file_ptr->file_ops->open(dentry->dir_inode, file_ptr);
|
|
|
|
|
|
- if (errcode != VFS_SUCCESS)
|
|
|
+ if (errcode != 0)
|
|
|
{
|
|
|
kfree(file_ptr);
|
|
|
+ spin_unlock(&dentry->lockref.lock);
|
|
|
return -EFAULT;
|
|
|
}
|
|
|
|
|
@@ -481,10 +531,12 @@ uint64_t do_open(const char *filename, int flags)
|
|
|
if (fd_num == -1)
|
|
|
{
|
|
|
kfree(file_ptr);
|
|
|
- return -EMFILE;
|
|
|
+ spin_unlock(&dentry->lockref.lock);
|
|
|
+ return -ENFILE;
|
|
|
}
|
|
|
// 保存文件描述符
|
|
|
f[fd_num] = file_ptr;
|
|
|
+ spin_unlock(&dentry->lockref.lock);
|
|
|
return fd_num;
|
|
|
}
|
|
|
|