mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 11:16:47 +00:00
对mkdir以及do_open进行加锁 (#55)
* 对mkdir加锁 * 给mkdir和do_open的dentry加锁 * 对加锁进行了修改 * modified * bugfix: 修复一些死锁及空指针的错误 Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
parent
efa38a7d5d
commit
5f4c802880
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 释放dentry,并视情况自动释放inode
|
* @brief 释放dentry,并视情况自动释放inode。 在调用该函数前,需要将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);
|
@ -3,7 +3,7 @@
|
|||||||
#include <debug/bug.h>
|
#include <debug/bug.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 释放dentry,并视情况自动释放inode
|
* @brief 释放dentry,并视情况自动释放inode. 在调用该函数前,需要将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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user