对mkdir以及do_open进行加锁 (#55)

* 对mkdir加锁

* 给mkdir和do_open的dentry加锁

* 对加锁进行了修改

* modified

* bugfix: 修复一些死锁及空指针的错误

Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
DaJiYuQia 2022-10-13 14:34:39 +08:00 committed by GitHub
parent efa38a7d5d
commit 5f4c802880
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 50 deletions

View File

@ -1,16 +1,16 @@
#include "VFS.h" #include "VFS.h"
#include "mount.h"
#include "internal.h" #include "internal.h"
#include <common/kprint.h> #include "mount.h"
#include <debug/bug.h>
#include <common/dirent.h> #include <common/dirent.h>
#include <common/string.h>
#include <common/errno.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/mm.h>
#include <mm/slab.h> #include <mm/slab.h>
#include <process/ptrace.h>
#include <process/process.h> #include <process/process.h>
#include <filesystem/rootfs/rootfs.h> #include <process/ptrace.h>
// 为filesystem_type_t结构体实例化一个链表头 // 为filesystem_type_t结构体实例化一个链表头
static struct vfs_filesystem_type_t vfs_fs = {"filesystem", 0}; 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) for (p = &vfs_fs; p; p = p->next)
{ {
if (!strcmp(p->name, fs->name)) // 已经注册相同名称的文件系统 if (!strcmp(p->name, fs->name)) // 已经注册相同名称的文件系统
return VFS_E_FS_EXISTED; return -EEXIST;
} }
fs->next = vfs_fs.next; fs->next = vfs_fs.next;
vfs_fs.next = fs; vfs_fs.next = fs;
return VFS_SUCCESS; return 0;
} }
uint64_t vfs_unregister_filesystem(struct vfs_filesystem_type_t *fs) 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; p->next = p->next->next;
fs->next = NULL; fs->next = NULL;
return VFS_SUCCESS; return 0;
} }
else else
p = p->next; 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) int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland)
{ {
uint32_t pathlen; uint32_t pathlen;
int retval = 0;
if (from_userland) if (from_userland)
pathlen = strnlen_user(path, PAGE_4K_SIZE - 1); pathlen = strnlen_user(path, PAGE_4K_SIZE - 1);
else else
@ -296,30 +297,57 @@ int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland)
kwarn("Dir '%s' aleardy exists.", path); kwarn("Dir '%s' aleardy exists.", path);
return -EEXIST; return -EEXIST;
} }
spin_lock(&parent_dir->lockref.lock);
struct vfs_dir_entry_t *subdir_dentry = vfs_alloc_dentry(pathlen - last_slash); struct vfs_dir_entry_t *subdir_dentry = vfs_alloc_dentry(pathlen - last_slash);
if (path[pathlen - 1] == '/') if (path[pathlen - 1] == '/')
subdir_dentry->name_length = pathlen - last_slash - 2; subdir_dentry->name_length = pathlen - last_slash - 2;
else else
subdir_dentry->name_length = pathlen - last_slash - 1; 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) 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[cnt] = path[i];
} }
++subdir_dentry->name_length;
// kdebug("last_slash=%d", last_slash); // kdebug("last_slash=%d", last_slash);
// kdebug("name=%s", path + last_slash + 1); // kdebug("name=%s", path + last_slash + 1);
subdir_dentry->parent = parent_dir; subdir_dentry->parent = parent_dir;
// kdebug("to mkdir, parent name=%s", parent_dir->name); // 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); spin_lock(&parent_dir->dir_inode->lockref.lock);
list_append(&parent_dir->subdirs_list, &subdir_dentry->child_node_list); retval = parent_dir->dir_inode->inode_ops->mkdir(parent_dir->dir_inode, subdir_dentry, 0);
// kdebug("retval = %d", retval); spin_unlock(&parent_dir->dir_inode->lockref.lock);
return 0;
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 * @brief
* *
@ -351,13 +379,9 @@ uint64_t do_open(const char *filename, int flags)
long path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1; long path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1;
if (path_len <= 0) // 地址空间错误 if (path_len <= 0) // 地址空间错误
{
return -EFAULT; return -EFAULT;
}
else if (path_len >= PAGE_4K_SIZE) // 名称过长 else if (path_len >= PAGE_4K_SIZE) // 名称过长
{
return -ENAMETOOLONG; return -ENAMETOOLONG;
}
// 为待拷贝文件路径字符串分配内存空间 // 为待拷贝文件路径字符串分配内存空间
char *path = (char *)kzalloc(path_len, 0); char *path = (char *)kzalloc(path_len, 0);
@ -394,17 +418,17 @@ uint64_t do_open(const char *filename, int flags)
{ {
path[tmp_index] = '\0'; path[tmp_index] = '\0';
dentry = vfs_path_walk(path, 0); parent_dentry = vfs_path_walk(path, 0);
if (dentry == NULL) if (parent_dentry == NULL)
{ {
kfree(path); kfree(path);
return -ENOENT; return -ENOENT;
} }
parent_dentry = dentry;
} }
else else
{
parent_dentry = vfs_root_sb->root; parent_dentry = vfs_root_sb->root;
}
// 创建新的文件 // 创建新的文件
dentry = vfs_alloc_dentry(path_len - tmp_index); 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); strncpy(dentry->name, path + tmp_index + 1, dentry->name_length);
// kdebug("to create new file:%s namelen=%d", dentry->name, dentry->name_length) // kdebug("to create new file:%s namelen=%d", dentry->name, dentry->name_length)
dentry->parent = parent_dentry; 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); 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) if (retval != 0)
{ {
kfree(dentry->name); if (vfs_dentry_put(dentry) != 0) // 释放dentry
kfree(dentry); BUG_ON(1);
BUG_ON(1);
kfree(path); kfree(path);
spin_unlock(&parent_dentry->lockref.lock);
return retval; 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); 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."); // kdebug("created.");
} }
kfree(path); kfree(path);
if (dentry == NULL) if (dentry == NULL)
{
return -ENOENT; return -ENOENT;
}
spin_lock(&dentry->lockref.lock);
// 要求打开文件夹而目标不是文件夹 // 要求打开文件夹而目标不是文件夹
if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_IF_DIR)) if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_IF_DIR))
{
spin_unlock(&dentry->lockref.lock);
return -ENOTDIR; return -ENOTDIR;
}
// 创建文件描述符 // 创建文件描述符
struct vfs_file_t *file_ptr = (struct vfs_file_t *)kzalloc(sizeof(struct vfs_file_t), 0); 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) if (file_ptr->file_ops && file_ptr->file_ops->open)
errcode = file_ptr->file_ops->open(dentry->dir_inode, file_ptr); errcode = file_ptr->file_ops->open(dentry->dir_inode, file_ptr);
if (errcode != VFS_SUCCESS) if (errcode != 0)
{ {
kfree(file_ptr); kfree(file_ptr);
spin_unlock(&dentry->lockref.lock);
return -EFAULT; return -EFAULT;
} }
@ -481,10 +531,12 @@ uint64_t do_open(const char *filename, int flags)
if (fd_num == -1) if (fd_num == -1)
{ {
kfree(file_ptr); kfree(file_ptr);
return -EMFILE; spin_unlock(&dentry->lockref.lock);
return -ENFILE;
} }
// 保存文件描述符 // 保存文件描述符
f[fd_num] = file_ptr; f[fd_num] = file_ptr;
spin_unlock(&dentry->lockref.lock);
return fd_num; return fd_num;
} }

View File

@ -11,9 +11,9 @@
#pragma once #pragma once
#include <common/glib.h>
#include <common/fcntl.h>
#include <common/blk_types.h> #include <common/blk_types.h>
#include <common/fcntl.h>
#include <common/glib.h>
#include <common/lockref.h> #include <common/lockref.h>
#include <mm/slab.h> #include <mm/slab.h>
@ -22,10 +22,6 @@ extern struct vfs_superblock_t *vfs_root_sb;
#define VFS_DPT_MBR 0 // MBR分区表 #define VFS_DPT_MBR 0 // MBR分区表
#define VFS_DPT_GPT 1 // GPT分区表 #define VFS_DPT_GPT 1 // GPT分区表
#define VFS_SUCCESS 0
#define VFS_E_FS_EXISTED 1 // 错误:文件系统已存在
#define VFS_E_FS_NOT_EXIST 2 // 错误:文件系统不存在
#define VFS_MAX_PATHLEN 1024 #define VFS_MAX_PATHLEN 1024
/** /**
@ -33,7 +29,7 @@ extern struct vfs_superblock_t *vfs_root_sb;
* *
*/ */
#define VFS_IF_FILE (1UL << 0) #define VFS_IF_FILE (1UL << 0)
#define VFS_IF_DIR (1UL << 1) // 文件夹 #define VFS_IF_DIR (1UL << 1) // 文件夹
#define VFS_IF_DEVICE (1UL << 2) #define VFS_IF_DEVICE (1UL << 2)
#define VFS_IF_DEAD (1UL << 3) /* removed, but still open directory */ #define VFS_IF_DEAD (1UL << 3) /* removed, but still open directory */
@ -116,7 +112,8 @@ struct vfs_filesystem_type_t
{ {
char *name; char *name;
int fs_flags; int fs_flags;
struct vfs_superblock_t *(*read_superblock)(struct block_device *blk); // 解析文件系统引导扇区的函数,为文件系统创建超级块结构。 struct vfs_superblock_t *(*read_superblock)(
struct block_device *blk); // 解析文件系统引导扇区的函数,为文件系统创建超级块结构。
struct vfs_filesystem_type_t *next; struct vfs_filesystem_type_t *next;
}; };
@ -155,7 +152,8 @@ struct vfs_inode_operations_t
*/ */
long (*mkdir)(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry, int mode); long (*mkdir)(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry, int mode);
long (*rmdir)(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry); long (*rmdir)(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry);
long (*rename)(struct vfs_index_node_t *old_inode, struct vfs_dir_entry_t *old_dEntry, struct vfs_index_node_t *new_inode, struct vfs_dir_entry_t *new_dEntry); long (*rename)(struct vfs_index_node_t *old_inode, struct vfs_dir_entry_t *old_dEntry,
struct vfs_index_node_t *new_inode, struct vfs_dir_entry_t *new_dEntry);
long (*getAttr)(struct vfs_dir_entry_t *dEntry, uint64_t *attr); long (*getAttr)(struct vfs_dir_entry_t *dEntry, uint64_t *attr);
long (*setAttr)(struct vfs_dir_entry_t *dEntry, uint64_t *attr); long (*setAttr)(struct vfs_dir_entry_t *dEntry, uint64_t *attr);
}; };
@ -271,11 +269,11 @@ int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland);
int64_t vfs_rmdir(const char *path, bool from_userland); int64_t vfs_rmdir(const char *path, bool from_userland);
/** /**
* @brief dentryinode * @brief dentryinode dentry加锁
* *
* @param dentry dentry * @param dentry dentry
* *
* @return * @return
* dentry指向文件时dentry后dentry指向的inode的引用计数 * dentry指向文件时dentry后dentry指向的inode的引用计数
*/ */
int vfs_dentry_put(struct vfs_dir_entry_t * dentry); int vfs_dentry_put(struct vfs_dir_entry_t *dentry);

View File

@ -3,7 +3,7 @@
#include <debug/bug.h> #include <debug/bug.h>
/** /**
* @brief dentryinode * @brief dentryinode. dentry加锁
* *
* @param dentry dentry * @param dentry dentry
* *
@ -21,7 +21,6 @@ int vfs_dentry_put(struct vfs_dir_entry_t *dentry)
{ {
BUG_ON(1); BUG_ON(1);
retval = -EBUSY; retval = -EBUSY;
spin_unlock(&dentry->lockref.lock);
goto out; goto out;
} }

View File

@ -502,13 +502,13 @@ struct vfs_dir_entry_operations_t fat32_dEntry_ops =
// todo: open // todo: open
long fat32_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) long fat32_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr)
{ {
return VFS_SUCCESS; return 0;
} }
// todo: close // todo: close
long fat32_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) long fat32_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr)
{ {
return VFS_SUCCESS; return 0;
} }
/** /**