对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 "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;
}

View File

@ -11,9 +11,9 @@
#pragma once
#include <common/glib.h>
#include <common/fcntl.h>
#include <common/blk_types.h>
#include <common/fcntl.h>
#include <common/glib.h>
#include <common/lockref.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_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
/**
@ -33,7 +29,7 @@ extern struct vfs_superblock_t *vfs_root_sb;
*
*/
#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_DEAD (1UL << 3) /* removed, but still open directory */
@ -116,7 +112,8 @@ struct vfs_filesystem_type_t
{
char *name;
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;
};
@ -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 (*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 (*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);
/**
* @brief dentryinode
* @brief dentryinode dentry加锁
*
* @param dentry dentry
*
*
* @return
* 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>
/**
* @brief dentryinode
* @brief dentryinode. dentry加锁
*
* @param dentry dentry
*
@ -21,7 +21,6 @@ int vfs_dentry_put(struct vfs_dir_entry_t *dentry)
{
BUG_ON(1);
retval = -EBUSY;
spin_unlock(&dentry->lockref.lock);
goto out;
}

View File

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