1 #include "VFS.h"
2 #include "internal.h"
3 #include "mount.h"
4 #include <common/dirent.h>
5 #include <common/err.h>
6 #include <common/errno.h>
7 #include <common/kprint.h>
8 #include <common/string.h>
9 #include <debug/bug.h>
10 #include <filesystem/rootfs/rootfs.h>
11 #include <mm/mm.h>
12 #include <mm/slab.h>
13 #include <process/process.h>
14 #include <process/ptrace.h>
15 
16 // 为filesystem_type_t结构体实例化一个链表头
17 static struct vfs_filesystem_type_t vfs_fs = {"filesystem", 0};
18 struct vfs_superblock_t *vfs_root_sb = NULL;
19 
20 struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size);
21 
22 /**
23  * @brief 挂载文件系统
24  *
25  * @param path 要挂载到的路径
26  * @param name 文件系统名
27  * @param blk 块设备结构体
28  * @return struct vfs_superblock_t* 挂载后,文件系统的超级块
29  */
vfs_mount_fs(const char * path,char * name,struct block_device * blk)30 struct vfs_superblock_t *vfs_mount_fs(const char *path, char *name, struct block_device *blk)
31 {
32 
33     // 判断挂载点是否存在
34     struct vfs_dir_entry_t *target_dentry = NULL;
35 
36     target_dentry = vfs_path_walk(path, 0);
37     if (target_dentry == NULL)
38         return NULL;
39 
40     struct vfs_filesystem_type_t *p = NULL;
41     for (p = &vfs_fs; p; p = p->next)
42     {
43         if (!strcmp(p->name, name)) // 存在符合的文件系统
44         {
45             struct vfs_superblock_t *sb = p->read_superblock(blk);
46             if (strcmp(path, "/") == 0) // 如果挂载到的是'/'挂载点,则让其成为最顶层的文件系统
47             {
48                 vfs_root_sb = sb;
49             }
50             else
51             {
52                 kdebug("to mount %s", name);
53                 // 调用mount机制,挂载文件系统
54                 struct vfs_dir_entry_t *new_dentry = sb->root;
55                 // 注意,umount的时候需要释放这些内存
56                 new_dentry->name = kzalloc(target_dentry->name_length + 1, 0);
57                 new_dentry->name_length = target_dentry->name_length;
58 
59                 do_mount(target_dentry, new_dentry);
60             }
61             return sb;
62         }
63     }
64 
65     kdebug("unsupported fs: %s", name);
66     return NULL;
67 }
68 
69 /**
70  * @brief 在VFS中注册文件系统
71  *
72  * @param fs 文件系统类型结构体
73  * @return uint64_t
74  */
vfs_register_filesystem(struct vfs_filesystem_type_t * fs)75 uint64_t vfs_register_filesystem(struct vfs_filesystem_type_t *fs)
76 {
77     struct vfs_filesystem_type_t *p = NULL;
78     for (p = &vfs_fs; p; p = p->next)
79     {
80         if (!strcmp(p->name, fs->name)) // 已经注册相同名称的文件系统
81             return -EEXIST;
82     }
83 
84     fs->next = vfs_fs.next;
85     vfs_fs.next = fs;
86     return 0;
87 }
88 
vfs_unregister_filesystem(struct vfs_filesystem_type_t * fs)89 uint64_t vfs_unregister_filesystem(struct vfs_filesystem_type_t *fs)
90 {
91     struct vfs_filesystem_type_t *p = &vfs_fs;
92     while (p->next)
93     {
94         if (p->next == fs)
95         {
96             p->next = p->next->next;
97             fs->next = NULL;
98             return 0;
99         }
100         else
101             p = p->next;
102     }
103     return -EINVAL;
104 }
105 
106 /**
107  * @brief 在dentry的sub_dir_list中搜索指定名称的dentry
108  *
109  * @param dentry 目录项结构体dentry
110  * @param name 待搜索的dentry名称
111  * @return struct vfs_dir_entry_t* 目标dentry (无结果则返回NULL)
112  */
vfs_search_dentry_list(struct vfs_dir_entry_t * dentry,const char * name)113 static struct vfs_dir_entry_t *vfs_search_dentry_list(struct vfs_dir_entry_t *dentry, const char *name)
114 {
115     if (list_empty(&dentry->subdirs_list))
116         return NULL;
117 
118     struct List *ptr = &dentry->subdirs_list;
119     struct vfs_dir_entry_t *d_ptr = NULL;
120     do
121     {
122         ptr = list_next(ptr);
123         d_ptr = container_of(ptr, struct vfs_dir_entry_t, child_node_list);
124         if (strcmp(name, d_ptr->name) == 0)
125             return d_ptr;
126     } while (list_next(ptr) != (&dentry->subdirs_list));
127 
128     return NULL;
129 }
130 
131 /**
132  * @brief 按照路径查找文件
133  *
134  * @param path 路径
135  * @param flags 1:返回父目录项, 0:返回结果目录项
136  * @return struct vfs_dir_entry_t* 目录项
137  */
vfs_path_walk(const char * path,uint64_t flags)138 struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags)
139 {
140 
141     struct vfs_dir_entry_t *parent = vfs_root_sb->root;
142     // 去除路径前的斜杠
143     while (*path == '/')
144         ++path;
145 
146     if ((!*path) || (*path == '\0'))
147         return parent;
148 
149     struct vfs_dir_entry_t *dentry = NULL;
150     // kdebug("path before walk:%s", path);
151     while (true)
152     {
153         // 提取出下一级待搜索的目录名或文件名,并保存在dEntry_name中
154         const char *tmp_path = path;
155         while ((*path && *path != '\0') && (*path != '/'))
156             ++path;
157         int tmp_path_len = path - tmp_path;
158         // 搜索是否有dentry缓存
159         {
160             char *tmpname = kzalloc(tmp_path_len + 1, 0);
161             strncpy(tmpname, tmp_path, tmp_path_len);
162             tmpname[tmp_path_len] = '\0';
163             // kdebug("tmpname=%s", tmpname);
164             dentry = vfs_search_dentry_list(parent, tmpname);
165 
166             kfree(tmpname);
167         }
168 
169         // 如果没有找到dentry缓存,则申请新的dentry
170         if (dentry == NULL)
171         {
172             dentry = vfs_alloc_dentry(tmp_path_len + 1);
173 
174             memcpy(dentry->name, (void *)tmp_path, tmp_path_len);
175             dentry->name[tmp_path_len] = '\0';
176             // kdebug("tmp_path_len=%d, dentry->name=%s", tmp_path_len, dentry->name);
177             dentry->name_length = tmp_path_len;
178 
179             if (parent->dir_inode->inode_ops->lookup(parent->dir_inode, dentry) == NULL)
180             {
181                 // 搜索失败
182                 // kwarn("cannot find the file/dir : %s", dentry->name);
183                 kfree(dentry->name);
184                 kfree(dentry);
185                 return NULL;
186             }
187             // 找到子目录项
188             dentry->parent = parent;
189 
190             list_add(&parent->subdirs_list, &dentry->child_node_list);
191         }
192 
193         while (*path == '/')
194             ++path;
195 
196         if ((!*path) || (*path == '\0')) //  已经到达末尾
197         {
198             if (flags & 1) // 返回父目录
199             {
200                 return parent;
201             }
202 
203             return dentry;
204         }
205 
206         parent = dentry;
207     }
208 }
209 
210 /**
211  * @brief 填充dentry
212  *
213  * @return dirent的总大小
214  */
vfs_fill_dirent(void * buf,ino_t d_ino,char * name,int namelen,unsigned char type,off_t offset)215 int vfs_fill_dirent(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset)
216 {
217     struct dirent *dent = (struct dirent *)buf;
218 
219     // 如果尝试访问内核空间,则返回错误
220     if (!(verify_area((uint64_t)buf, sizeof(struct dirent) + namelen)))
221         return -EFAULT;
222 
223     // ====== 填充dirent结构体 =====
224     memset(buf, 0, sizeof(struct dirent) + namelen);
225 
226     memcpy(dent->d_name, name, namelen);
227     dent->d_name[namelen] = '\0';
228     // 暂时不显示目录下的记录数
229     dent->d_reclen = 0;
230     dent->d_ino = d_ino;
231     dent->d_off = offset;
232     dent->d_type = type;
233 
234     // 返回dirent的总大小
235     return sizeof(struct dirent) + namelen;
236 }
237 
238 /**
239  * @brief 创建文件夹
240  *
241  * @param path 文件夹路径
242  * @param mode 创建模式
243  * @param from_userland 该创建请求是否来自用户态
244  * @return int64_t 错误码
245  */
vfs_mkdir(const char * path,mode_t mode,bool from_userland)246 int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland)
247 {
248     uint32_t pathlen;
249     int retval = 0;
250     if (from_userland)
251         pathlen = strnlen_user(path, PAGE_4K_SIZE - 1);
252     else
253         pathlen = strnlen(path, PAGE_4K_SIZE - 1);
254 
255     if (pathlen == 0)
256         return -ENOENT;
257 
258     int last_slash = -1;
259 
260     // 查找最后一个'/',忽略路径末尾的'/'
261     for (int i = pathlen - 2; i >= 0; --i)
262     {
263         if (path[i] == '/')
264         {
265             last_slash = i;
266             break;
267         }
268     }
269 
270     // 路径格式不合法(必须使用绝对路径)
271     if (last_slash < 0)
272         return -ENOTDIR;
273 
274     char *buf = (char *)kzalloc(last_slash + 2, 0);
275 
276     // 拷贝字符串(不包含要被创建的部分)
277     if (from_userland)
278         strncpy_from_user(buf, path, last_slash);
279     else
280         strncpy(buf, path, last_slash);
281     buf[last_slash + 1] = '\0';
282 
283     // 查找父目录
284     struct vfs_dir_entry_t *parent_dir = vfs_path_walk(buf, 0);
285 
286     if (parent_dir == NULL)
287     {
288         kwarn("parent dir is NULL.");
289         kfree(buf);
290         return -ENOENT;
291     }
292     kfree(buf);
293 
294     // 检查父目录中是否已经有相同的目录项
295     if (vfs_path_walk((const char *)path, 0) != NULL)
296     {
297         // 目录中已有对应的文件夹
298         kwarn("Dir '%s' aleardy exists.", path);
299         return -EEXIST;
300     }
301     spin_lock(&parent_dir->lockref.lock);
302     struct vfs_dir_entry_t *subdir_dentry = vfs_alloc_dentry(pathlen - last_slash);
303 
304     if (path[pathlen - 1] == '/')
305         subdir_dentry->name_length = pathlen - last_slash - 2;
306     else
307         subdir_dentry->name_length = pathlen - last_slash - 1;
308 
309     for (int i = last_slash + 1, cnt = 0; i < pathlen && cnt < subdir_dentry->name_length; ++i, ++cnt)
310         subdir_dentry->name[cnt] = path[i];
311     // 设置subdir的dentry的父路径
312     subdir_dentry->parent = parent_dir;
313 
314     // kdebug("to mkdir, parent name=%s", parent_dir->name);
315     spin_lock(&parent_dir->dir_inode->lockref.lock);
316     retval = parent_dir->dir_inode->inode_ops->mkdir(parent_dir->dir_inode, subdir_dentry, 0);
317     spin_unlock(&parent_dir->dir_inode->lockref.lock);
318 
319     if (retval != 0)
320     {
321         if (vfs_dentry_put(parent_dir) != 0) // 释放dentry
322             spin_unlock(&parent_dir->lockref.lock);
323         return retval;
324     }
325 
326     // 获取append前一个dentry并加锁
327     struct List *target_list = &parent_dir->subdirs_list;
328     // kdebug("target_list=%#018lx target_list->prev=%#018lx",target_list,target_list->prev);
329     if (list_empty(target_list) == false)
330     {
331         struct vfs_dir_entry_t *prev_dentry = list_entry(target_list->prev, struct vfs_dir_entry_t, child_node_list);
332         // kdebug("prev_dentry%#018lx",prev_dentry);
333         spin_lock(&prev_dentry->lockref.lock);
334         list_append(&parent_dir->subdirs_list, &subdir_dentry->child_node_list);
335         // kdebug("retval = %d", retval);
336         spin_unlock(&prev_dentry->lockref.lock);
337     }
338     else
339     {
340         list_append(&parent_dir->subdirs_list, &subdir_dentry->child_node_list);
341         goto out;
342     }
343 
344 out:;
345     spin_unlock(&parent_dir->lockref.lock);
346     return retval;
347 }
348 
349 /**
350  * @brief 创建文件夹
351  *
352  * @param path(r8) 路径
353  * @param mode(r9) 模式
354  * @return uint64_t
355  */
sys_mkdir(struct pt_regs * regs)356 uint64_t sys_mkdir(struct pt_regs *regs)
357 {
358     const char *path = (const char *)regs->r8;
359     // kdebug("path = %s", path);
360     mode_t mode = (mode_t)regs->r9;
361 
362     if (user_mode(regs))
363         return vfs_mkdir(path, mode, true);
364     else
365         return vfs_mkdir(path, mode, false);
366 }
367 
368 /**
369  * @brief 打开文件
370  *
371  * @param filename 文件路径
372  * @param flags 标志位
373  * @param from_user 是否由用户态调用,1为是,0为否
374  * @return uint64_t 错误码
375  */
do_open(const char * filename,int flags,bool from_user)376 uint64_t do_open(const char *filename, int flags, bool from_user)
377 {
378     long path_len = 0;
379     if (from_user)
380         path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1;
381     else
382         path_len = strnlen(filename, PAGE_4K_SIZE) + 1;
383 
384     if (path_len <= 0) // 地址空间错误
385         return -EFAULT;
386     else if (path_len >= PAGE_4K_SIZE) // 名称过长
387         return -ENAMETOOLONG;
388 
389     // 为待拷贝文件路径字符串分配内存空间
390     char *path = (char *)kzalloc(path_len, 0);
391     if (path == NULL)
392         return -ENOMEM;
393 
394     if (from_user)
395         strncpy_from_user(path, filename, path_len);
396     else
397         strncpy(path, filename, path_len);
398 
399     // 去除末尾的 '/'
400     if (path_len >= 2 && path[path_len - 2] == '/')
401     {
402         path[path_len - 2] = '\0';
403         --path_len;
404     }
405 
406     // 寻找文件
407     struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0);
408     if (dentry == NULL && flags & O_CREAT)
409     {
410         // 先找到倒数第二级目录
411         int tmp_index = -1;
412         for (int i = path_len - 1; i >= 0; --i)
413         {
414             if (path[i] == '/')
415             {
416                 tmp_index = i;
417                 break;
418             }
419         }
420 
421         struct vfs_dir_entry_t *parent_dentry = NULL;
422         // kdebug("tmp_index=%d", tmp_index);
423         if (tmp_index > 0)
424         {
425 
426             path[tmp_index] = '\0';
427             parent_dentry = vfs_path_walk(path, 0);
428             if (parent_dentry == NULL)
429             {
430                 kfree(path);
431                 return -ENOENT;
432             }
433         }
434         else
435         {
436             parent_dentry = vfs_root_sb->root;
437         }
438         // 创建新的文件
439         dentry = vfs_alloc_dentry(path_len - tmp_index);
440 
441         dentry->name_length = path_len - tmp_index - 2;
442 
443         // kdebug("to create new file:%s   namelen=%d", dentry->name, dentry->name_length);
444         strncpy(dentry->name, path + tmp_index + 1, dentry->name_length);
445         dentry->parent = parent_dentry;
446 
447         // 对父目录项加锁
448         spin_lock(&parent_dentry->lockref.lock);
449         spin_lock(&parent_dentry->dir_inode->lockref.lock);
450         // 创建子目录项
451         uint64_t retval = parent_dentry->dir_inode->inode_ops->create(parent_dentry->dir_inode, dentry, 0);
452         spin_unlock(&parent_dentry->dir_inode->lockref.lock); // 解锁inode
453 
454         if (retval != 0)
455         {
456             if (vfs_dentry_put(dentry) != 0) // 释放dentry
457                 BUG_ON(1);
458             BUG_ON(1);
459             kfree(path);
460             spin_unlock(&parent_dentry->lockref.lock);
461             return retval;
462         }
463 
464         // ==== 将子目录项添加到链表 ====
465         struct vfs_dir_entry_t *next_dentry = NULL;
466         // 若list非空,则对前一个dentry加锁
467         if (!list_empty(&parent_dentry->subdirs_list))
468         {
469             next_dentry = list_entry(list_next(&parent_dentry->subdirs_list), struct vfs_dir_entry_t, child_node_list);
470             spin_lock(&next_dentry->lockref.lock);
471         }
472         list_add(&parent_dentry->subdirs_list, &dentry->child_node_list);
473         if (next_dentry != NULL)
474             spin_unlock(&next_dentry->lockref.lock);
475 
476         // 新建文件结束,对父目录项解锁
477         spin_unlock(&parent_dentry->lockref.lock);
478         // kdebug("created.");
479     }
480 
481     kfree(path);
482     if (dentry == NULL)
483     {
484         return -ENOENT;
485     }
486     spin_lock(&dentry->lockref.lock);
487     // 要求打开文件夹而目标不是文件夹
488     if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_IF_DIR))
489     {
490         spin_unlock(&dentry->lockref.lock);
491         return -ENOTDIR;
492     }
493     // 创建文件描述符
494     struct vfs_file_t *file_ptr = (struct vfs_file_t *)kzalloc(sizeof(struct vfs_file_t), 0);
495 
496     int errcode = -1;
497 
498     file_ptr->dEntry = dentry;
499     file_ptr->mode = flags;
500 
501     file_ptr->file_ops = dentry->dir_inode->file_ops;
502 
503     // 如果文件系统实现了打开文件的函数
504     if (file_ptr->file_ops && file_ptr->file_ops->open)
505         errcode = file_ptr->file_ops->open(dentry->dir_inode, file_ptr);
506 
507     if (errcode != 0)
508     {
509         kfree(file_ptr);
510         spin_unlock(&dentry->lockref.lock);
511         return -EFAULT;
512     }
513 
514     if (file_ptr->mode & O_TRUNC) // 清空文件
515         file_ptr->dEntry->dir_inode->file_size = 0;
516 
517     if (file_ptr->mode & O_APPEND)
518         file_ptr->position = file_ptr->dEntry->dir_inode->file_size;
519     else
520         file_ptr->position = 0;
521 
522     int fd_num = process_fd_alloc(file_ptr);
523 
524     // 指针数组没有空位了
525     if (fd_num == -1)
526     {
527         kfree(file_ptr);
528         spin_unlock(&dentry->lockref.lock);
529         return -ENFILE;
530     }
531     spin_unlock(&dentry->lockref.lock);
532     return fd_num;
533 }
534 
sys_open(struct pt_regs * regs)535 uint64_t sys_open(struct pt_regs *regs)
536 {
537     char *filename = (char *)(regs->r8);
538     int flags = (int)(regs->r9);
539     return do_open(filename, flags, true);
540 }
541 
542 /**
543  * @brief 关闭文件
544  *
545  * @param fd_num 文件描述符
546  * @return uint64_t 错误码
547  */
vfs_close(int fd_num)548 uint64_t vfs_close(int fd_num)
549 {
550     // 校验文件描述符范围
551     if (fd_num < 0 || fd_num > PROC_MAX_FD_NUM)
552         return -EBADF;
553     // 文件描述符不存在
554     if (current_pcb->fds[fd_num] == NULL)
555         return -EBADF;
556     struct vfs_file_t *file_ptr = current_pcb->fds[fd_num];
557     uint64_t ret;
558     // If there is a valid close function
559     if (file_ptr->file_ops && file_ptr->file_ops->close)
560         ret = file_ptr->file_ops->close(file_ptr->dEntry->dir_inode, file_ptr);
561 
562     kfree(file_ptr);
563     current_pcb->fds[fd_num] = NULL;
564     return 0;
565 }
566 /**
567  * @brief 动态分配dentry以及路径字符串名称
568  *
569  * @param name_size 名称字符串大小(字节)(注意考虑字符串最后需要有一个‘\0’作为结尾)
570  * @return struct vfs_dir_entry_t* 创建好的dentry
571  */
vfs_alloc_dentry(const int name_size)572 struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size)
573 {
574     if (unlikely(name_size > VFS_MAX_PATHLEN))
575         return NULL;
576     struct vfs_dir_entry_t *dentry = (struct vfs_dir_entry_t *)kzalloc(sizeof(struct vfs_dir_entry_t), 0);
577     if (unlikely(dentry == NULL))
578         return NULL;
579     if (name_size != 0)
580         dentry->name = (char *)kzalloc(name_size, 0);
581 
582     // 初始化lockref
583     spin_init(&dentry->lockref.lock);
584     dentry->lockref.count = 1;
585     // 初始化链表
586     list_init(&dentry->child_node_list);
587     list_init(&dentry->subdirs_list);
588     return dentry;
589 }
590 
591 /**
592  * @brief 判断是否可以删除指定的dentry
593  *
594  * 1、我们不能删除一个只读的dentry
595  * 2、我们应当对这个dentry的inode拥有写、执行权限(暂时还没有实现权限)
596  * 3、如果dentry指向的是文件夹,而isdir为false,则不能删除
597  * 3、如果dentry指向的是文件,而isdir为true,则不能删除
598  * @param dentry 将要被删除的dentry
599  * @param isdir 是否要删除文件夹
600  * @return int 错误码
601  */
vfs_may_delete(struct vfs_dir_entry_t * dentry,bool isdir)602 int vfs_may_delete(struct vfs_dir_entry_t *dentry, bool isdir)
603 {
604     // 当dentry没有inode的时候,认为是bug
605     BUG_ON(dentry->dir_inode == NULL);
606 
607     // todo: 进行权限检查
608 
609     if (isdir) // 要删除文件夹
610     {
611         if (!D_ISDIR(dentry))
612             return -ENOTDIR;
613         else if (IS_ROOT(dentry))
614             return -EBUSY;
615     }
616     else if (D_ISDIR(dentry)) // 要删除文件但是当前是文件夹
617         return -EISDIR;
618 
619     return 0;
620 }
621 
622 /**
623  * @brief 删除文件夹
624  *
625  * @param path 文件夹路径
626  * @param from_userland 请求是否来自用户态
627  * @return int64_t 错误码
628  */
vfs_rmdir(const char * path,bool from_userland)629 int64_t vfs_rmdir(const char *path, bool from_userland)
630 {
631     uint32_t pathlen;
632     int retval = 0;
633     if (from_userland)
634         pathlen = strnlen_user(path, PAGE_4K_SIZE - 1);
635     else
636         pathlen = strnlen(path, PAGE_4K_SIZE - 1);
637 
638     if (pathlen == 0)
639         return -ENOENT;
640 
641     int last_slash = -1;
642 
643     // 去除末尾的'/'
644     for (int i = pathlen - 1; i >= 0; --i)
645     {
646         if (path[i] != '/')
647         {
648             last_slash = i + 1;
649             break;
650         }
651     }
652 
653     // 路径格式不合法
654     if (last_slash < 0)
655         return -ENOTDIR;
656     else if (path[0] != '/')
657         return -EINVAL;
658 
659     char *buf = (char *)kzalloc(last_slash + 2, 0);
660 
661     // 拷贝字符串(不包含要被创建的部分)
662     if (from_userland)
663         strncpy_from_user(buf, path, last_slash);
664     else
665         strncpy(buf, path, last_slash);
666     buf[last_slash + 1] = '\0';
667 
668     struct vfs_dir_entry_t *dentry = vfs_path_walk(buf, 0);
669 
670     kfree(buf);
671 
672     if (dentry == NULL)
673     {
674         retval = -ENOENT;
675         goto out0;
676     }
677 
678     // todo: 检查文件夹是否为空
679 
680     spin_lock(&dentry->lockref.lock);
681     retval = vfs_may_delete(dentry, true);
682     if (retval != 0)
683         goto out1;
684     // todo: 对dentry和inode加锁
685     retval = -EBUSY;
686     if (is_local_mountpoint(dentry))
687         goto out1;
688     // todo:
689     retval = dentry->dir_inode->inode_ops->rmdir(dentry->dir_inode, dentry);
690     if (retval != 0)
691     {
692         BUG_ON(1);
693         goto out1;
694     }
695 
696     dentry->dir_inode->attribute |= VFS_IF_DEAD; // 将当前inode标记为dead
697     dont_mount(dentry);                          // 将当前dentry标记为不可被挂载
698     detach_mounts(dentry);                       // 清理同样挂载在该路径的所有挂载点的挂载树
699 
700     // 释放dentry
701     retval = vfs_dentry_put(dentry);
702 
703     if (retval != 0)
704         goto out1;
705     goto out0;
706 out2:;
707     spin_unlock(&dentry->dir_inode->lockref.lock);
708 out1:;
709     spin_unlock(&dentry->lockref.lock);
710 out0:;
711     return retval;
712 }
713 
714 /**
715  * @brief unlink a filesystem object
716  *
717  * 调用者必须持有parent_inode->lockref.lock
718  *
719  * @param mnt_userns 暂时未使用 用户命名空间. 请置为NULL
720  * @param parent_inode 父目录项的inode
721  * @param dentry 要被删除的目录项
722  * @param delegated_inode 暂未使用,请置为NULL
723  * @return int
724  */
vfs_unlink(struct user_namespace * mnt_userns,struct vfs_index_node_t * parent_inode,struct vfs_dir_entry_t * dentry,struct vfs_index_node_t ** delegated_inode)725 int vfs_unlink(struct user_namespace *mnt_userns, struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dentry,
726                struct vfs_index_node_t **delegated_inode)
727 {
728     // 暂时不支持用户命名空间,因此发出警告
729     if (unlikely(mnt_userns != NULL))
730     {
731         WARN_ON(1);
732         return -EINVAL;
733     }
734 
735     int retval = 0;
736     struct vfs_index_node_t *target = dentry->dir_inode;
737 
738     retval = vfs_may_delete(dentry, false);
739     if (unlikely(retval != 0))
740         return retval;
741 
742     // 没有unlink方法,则不允许删除
743     if (!parent_inode->inode_ops->unlink)
744         return -EPERM;
745 
746     // 对inode加锁
747     spin_lock(&target->lockref.lock);
748 
749     if (is_local_mountpoint(dentry))
750         retval = -EBUSY;
751     else
752     {
753         retval = parent_inode->inode_ops->unlink(parent_inode, dentry);
754         if (retval == 0)
755         {
756             dont_mount(dentry);
757             detach_mounts(dentry);
758         }
759     }
760 
761     spin_unlock(&target->lockref.lock);
762 
763 out:;
764     return retval;
765 }
766 /**
767  * @brief 取消dentry和inode之间的链接
768  *
769  * @param dfd 进程相对路径基准目录的文件描述符(fcntl.h)
770  * @param pathname 路径
771  * @param from_userland 请求是否来自用户态
772  * @return int 错误码
773  */
do_unlink_at(int dfd,const char * pathname,bool from_userland)774 int do_unlink_at(int dfd, const char *pathname, bool from_userland)
775 {
776     // 暂时不支持相对路径,只支持绝对路径
777     if (dfd & AT_FDCWD)
778     {
779         kwarn("Not support: AT_FDCWD");
780         return -EINVAL;
781     }
782 
783     uint32_t pathlen;
784     int retval = 0;
785     if (from_userland)
786         pathlen = strnlen_user(pathname, PAGE_4K_SIZE - 1);
787     else
788         pathlen = strnlen(pathname, PAGE_4K_SIZE - 1);
789 
790     if (pathlen == 0)
791         return -ENOENT;
792 
793     int last_slash = -1;
794 
795     // 去除末尾的'/'
796     for (int i = pathlen - 1; i >= 0; --i)
797     {
798         if (pathname[i] != '/')
799         {
800             last_slash = i + 1;
801             break;
802         }
803     }
804 
805     // 路径格式不合法
806     if (last_slash < 0)
807         return -ENOTDIR;
808     else if (pathname[0] != '/')
809         return -EINVAL;
810 
811     char *buf = (char *)kzalloc(last_slash + 1, 0);
812 
813     // 拷贝字符串
814     if (from_userland)
815         strncpy_from_user(buf, pathname, last_slash);
816     else
817         strncpy(buf, pathname, last_slash);
818     buf[last_slash] = '\0';
819 
820     struct vfs_dir_entry_t *dentry = vfs_path_walk(buf, 0);
821     kfree(buf);
822 
823     if (dentry == NULL || dentry->parent == NULL)
824     {
825         retval = -ENOENT;
826         goto out;
827     }
828 
829     struct vfs_index_node_t *p_inode = dentry->parent->dir_inode;
830     // 对父inode加锁
831     spin_lock(&p_inode->lockref.lock);
832     spin_lock(&dentry->lockref.lock);
833     retval = vfs_unlink(NULL, dentry->parent->dir_inode, dentry, NULL);
834     if (unlikely(retval != 0))
835     {
836         // kdebug("retval=%d", retval);
837         spin_unlock(&dentry->lockref.lock);
838         spin_unlock(&p_inode->lockref.lock);
839         goto out;
840     }
841     // kdebug("vfs_dentry_put=%d", retval);
842     spin_unlock(&dentry->lockref.lock);
843     spin_unlock(&p_inode->lockref.lock);
844 
845     if (IS_ERR_VALUE(retval))
846         kwarn("In do_unlink_at: dentry put failed; retval=%d", retval);
847     else
848         retval = 0;
849 out:;
850     return retval;
851 }
852 
853 /**
854  * @brief 删除文件夹、取消文件的链接、删除文件的系统调用
855  *
856  * @param regs->r8 dfd 进程相对路径基准目录的文件描述符(见fcntl.h)
857  * @param regs->r9 路径名称字符串
858  * @param regs->r10 flag 预留的标志位,暂时未使用,请置为0。
859  * @return uint64_t 错误码
860  */
sys_unlink_at(struct pt_regs * regs)861 uint64_t sys_unlink_at(struct pt_regs *regs)
862 {
863     int dfd = regs->r8;
864     const char *pathname = (const char *)regs->r9;
865     int flag = regs->r10;
866     bool from_user = SYSCALL_FROM_USER(regs) ? true : false;
867     if ((flag & (~AT_REMOVEDIR)) != 0)
868         return -EINVAL;
869     if (flag & AT_REMOVEDIR)
870         return vfs_rmdir(pathname, from_user);
871     // kdebug("to do_unlink_at, path=%s", pathname);
872     return do_unlink_at(dfd, pathname, from_user);
873 }
874 
875 /**
876  * @brief 分配inode并将引用计数初始化为1
877  *
878  * @return struct vfs_index_node_t * 分配得到的inode
879  */
vfs_alloc_inode()880 struct vfs_index_node_t *vfs_alloc_inode()
881 {
882     struct vfs_index_node_t *inode = kzalloc(sizeof(struct vfs_index_node_t), 0);
883     spin_init(&inode->lockref.lock);
884     inode->lockref.count = 1; // 初始化引用计数为1
885     return inode;
886 }
887 
888 /**
889  * @brief 初始化vfs
890  *
891  * @return int 错误码
892  */
vfs_init()893 int vfs_init()
894 {
895     mount_init();
896     rootfs_init();
897     return 0;
898 }