Files
rust-based-os-comp2022/chapter6/2fs-implementation-2.html
2022-06-30 04:46:48 +00:00

959 lines
141 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html class="no-js" lang="zh_CN">
<head><meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<meta name="color-scheme" content="light dark"><link rel="index" title="索引" href="../genindex.html" /><link rel="search" title="搜索" href="../search.html" /><link rel="next" title="在内核中使用 easy-fs" href="3using-easy-fs-in-kernel.html" /><link rel="prev" title="简易文件系统 easy-fs (上)" href="2fs-implementation-1.html" />
<meta name="generator" content="sphinx-4.1.2, furo 2021.08.31"/>
<title>简易文件系统 easy-fs (下) - Open-Source-OS-Training-Camp-2022 文档</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/styles/furo.css?digest=c7c65a82b42f6b978e58466c1e9ef2509836d916" />
<link rel="stylesheet" type="text/css" href="../_static/tabs.css" />
<link rel="stylesheet" type="text/css" href="../_static/styles/furo-extensions.css?digest=16fb25fabf47304eee183a5e9af80b1ba98259b1" />
<link rel="stylesheet" type="text/css" href="../_static/my_style.css" />
<style>
body {
--color-code-background: #f8f8f8;
--color-code-foreground: black;
}
body[data-theme="dark"] {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
@media (prefers-color-scheme: dark) {
body:not([data-theme="light"]) {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
}
</style></head>
<body>
<script>
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
</script>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-toc" viewBox="0 0 24 24">
<title>Contents</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" />
<line x1="4" y1="6" x2="20" y2="6" />
<line x1="10" y1="12" x2="20" y2="12" />
<line x1="6" y1="18" x2="20" y2="18" />
</svg>
</symbol>
<symbol id="svg-menu" viewBox="0 0 24 24">
<title>Menu</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</symbol>
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
<title>Expand</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24">
<title>Light mode</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24">
<title>Dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
</svg>
</symbol>
<symbol id="svg-sun-half" viewBox="0 0 24 24">
<title>Auto light/dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r="9" />
<path d="M13 12h5" />
<path d="M13 15h4" />
<path d="M13 18h1" />
<path d="M13 9h4" />
<path d="M13 6h1" />
</svg>
</symbol>
</svg>
<input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
<input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
<label class="overlay sidebar-overlay" for="__navigation">
<div class="visually-hidden">Hide navigation sidebar</div>
</label>
<label class="overlay toc-overlay" for="__toc">
<div class="visually-hidden">Hide table of contents sidebar</div>
</label>
<div class="page">
<header class="mobile-header">
<div class="header-left">
<label class="nav-overlay-icon" for="__navigation">
<div class="visually-hidden">Toggle site navigation sidebar</div>
<i class="icon"><svg><use href="#svg-menu"></use></svg></i>
</label>
</div>
<div class="header-center">
<a href="../index.html"><div class="brand">Open-Source-OS-Training-Camp-2022 文档</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-header-icon" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
</header>
<aside class="sidebar-drawer">
<div class="sidebar-container">
<div class="sidebar-sticky"><a class="sidebar-brand" href="../index.html">
<span class="sidebar-brand-text">Open-Source-OS-Training-Camp-2022 文档</span>
</a><form class="sidebar-search-container" method="get" action="../search.html" role="search">
<input class="sidebar-search" placeholder=搜索 name="q" aria-label="搜索">
<input type="hidden" name="check_keywords" value="yes">
<input type="hidden" name="area" value="default">
</form>
<div id="searchbox"></div><div class="sidebar-scroll"><div class="sidebar-tree">
<p class="caption" role="heading"><span class="caption-text">正文</span></p>
<ul class="current">
<li class="toctree-l1 has-children"><a class="reference internal" href="../0setup-devel-env.html">第零章:实验环境配置</a><input class="toctree-checkbox" id="toctree-checkbox-1" name="toctree-checkbox-1" role="switch" type="checkbox"/><label for="toctree-checkbox-1"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter1/index.html">第一章:应用程序与基本执行环境</a><input class="toctree-checkbox" id="toctree-checkbox-2" name="toctree-checkbox-2" role="switch" type="checkbox"/><label for="toctree-checkbox-2"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter1/0intro.html">引言</a></li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/1app-ee-platform.html">应用程序执行环境与平台支持</a><input class="toctree-checkbox" id="toctree-checkbox-3" name="toctree-checkbox-3" role="switch" type="checkbox"/><label for="toctree-checkbox-3"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/2remove-std.html">移除标准库依赖</a><input class="toctree-checkbox" id="toctree-checkbox-4" name="toctree-checkbox-4" role="switch" type="checkbox"/><label for="toctree-checkbox-4"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/3mini-rt-usrland.html">构建用户态执行环境</a><input class="toctree-checkbox" id="toctree-checkbox-5" name="toctree-checkbox-5" role="switch" type="checkbox"/><label for="toctree-checkbox-5"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/4mini-rt-baremetal.html">构建裸机执行环境</a><input class="toctree-checkbox" id="toctree-checkbox-6" name="toctree-checkbox-6" role="switch" type="checkbox"/><label for="toctree-checkbox-6"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter2/index.html">第二章:批处理系统</a><input class="toctree-checkbox" id="toctree-checkbox-7" name="toctree-checkbox-7" role="switch" type="checkbox"/><label for="toctree-checkbox-7"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter2/0intro.html">引言</a></li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter2/2application.html">实现应用程序</a><input class="toctree-checkbox" id="toctree-checkbox-8" name="toctree-checkbox-8" role="switch" type="checkbox"/><label for="toctree-checkbox-8"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter2/3batch-system.html">实现批处理操作系统</a><input class="toctree-checkbox" id="toctree-checkbox-9" name="toctree-checkbox-9" role="switch" type="checkbox"/><label for="toctree-checkbox-9"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter2/4trap-handling.html">实现特权级的切换</a><input class="toctree-checkbox" id="toctree-checkbox-10" name="toctree-checkbox-10" role="switch" type="checkbox"/><label for="toctree-checkbox-10"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter3/index.html">第三章:多道程序与分时多任务</a><input class="toctree-checkbox" id="toctree-checkbox-11" name="toctree-checkbox-11" role="switch" type="checkbox"/><label for="toctree-checkbox-11"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/1multi-loader.html">多道程序放置与加载</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/2task-switching.html">任务切换</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/3multiprogramming.html">管理多道程序</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/4time-sharing-system.html">分时多任务系统</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/5exercise.html">chapter3练习</a></li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter4/index.html">第四章:地址空间</a><input class="toctree-checkbox" id="toctree-checkbox-12" name="toctree-checkbox-12" role="switch" type="checkbox"/><label for="toctree-checkbox-12"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/3sv39-implementation-1.html">实现 SV39 多级页表机制(上)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/4sv39-implementation-2.html">实现 SV39 多级页表机制(下)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/5kernel-app-spaces.html">内核与应用的地址空间</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/6multitasking-based-on-as.html">基于地址空间的分时多任务</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/7exercise.html">chapter4练习</a></li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter5/index.html">第五章:进程及进程管理</a><input class="toctree-checkbox" id="toctree-checkbox-13" name="toctree-checkbox-13" role="switch" type="checkbox"/><label for="toctree-checkbox-13"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter5/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter5/1process.html">与进程有关的重要系统调用</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter5/2core-data-structures.html">进程管理的核心数据结构</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter5/3implement-process-mechanism.html">进程管理机制的设计实现</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter5/4exercise.html">chapter5练习</a></li>
</ul>
</li>
<li class="toctree-l1 current has-children"><a class="reference internal" href="index.html">第六章文件系统与I/O重定向</a><input checked="" class="toctree-checkbox" id="toctree-checkbox-14" name="toctree-checkbox-14" role="switch" type="checkbox"/><label for="toctree-checkbox-14"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="1file-descriptor.html">文件与文件描述符</a></li>
<li class="toctree-l2"><a class="reference internal" href="1fs-interface.html">文件系统接口</a></li>
<li class="toctree-l2"><a class="reference internal" href="2fs-implementation-1.html">简易文件系统 easy-fs (上)</a></li>
<li class="toctree-l2 current current-page"><a class="current reference internal" href="#">简易文件系统 easy-fs (下)</a></li>
<li class="toctree-l2"><a class="reference internal" href="3using-easy-fs-in-kernel.html">在内核中使用 easy-fs</a></li>
<li class="toctree-l2"><a class="reference internal" href="4exercise.html">chapter6练习</a></li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter7/index.html">第七章:进程间通信</a><input class="toctree-checkbox" id="toctree-checkbox-15" name="toctree-checkbox-15" role="switch" type="checkbox"/><label for="toctree-checkbox-15"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter7/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter7/1pipe.html">管道</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter7/2cmdargs-and-redirection.html">命令行参数与标准 I/O 重定向</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter7/3exercise.html">chapter7练习</a></li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter8/index.html">第八章:并发</a><input class="toctree-checkbox" id="toctree-checkbox-16" name="toctree-checkbox-16" role="switch" type="checkbox"/><label for="toctree-checkbox-16"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/1thread-kernel.html">内核态的线程管理</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/2lock.html">锁机制</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/3semaphore.html">信号量机制</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/4condition-variable.html">条件变量机制</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/5exercise.html">chapter8 练习</a></li>
</ul>
</li>
</ul>
<p class="caption" role="heading"><span class="caption-text">附录</span></p>
<ul>
<li class="toctree-l1 has-children"><a class="reference internal" href="../appendix-a/index.html">附录 ARust 系统编程资料</a><input class="toctree-checkbox" id="toctree-checkbox-17" name="toctree-checkbox-17" role="switch" type="checkbox"/><label for="toctree-checkbox-17"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../appendix-b/index.html">附录 B常见工具的使用方法</a><input class="toctree-checkbox" id="toctree-checkbox-18" name="toctree-checkbox-18" role="switch" type="checkbox"/><label for="toctree-checkbox-18"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../appendix-c/index.html">附录 C深入机器模式RustSBI</a><input class="toctree-checkbox" id="toctree-checkbox-19" name="toctree-checkbox-19" role="switch" type="checkbox"/><label for="toctree-checkbox-19"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../appendix-d/index.html">附录 DRISC-V相关信息</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">开发注记</span></p>
<ul>
<li class="toctree-l1 has-children"><a class="reference internal" href="../setup-sphinx.html">修改和构建本项目</a><input class="toctree-checkbox" id="toctree-checkbox-20" name="toctree-checkbox-20" role="switch" type="checkbox"/><label for="toctree-checkbox-20"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../rest-example.html">reStructuredText 基本语法</a><input class="toctree-checkbox" id="toctree-checkbox-21" name="toctree-checkbox-21" role="switch" type="checkbox"/><label for="toctree-checkbox-21"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
</aside>
<div class="main">
<div class="content">
<article role="main">
<div class="content-icon-container">
<div class="theme-toggle-container theme-toggle-content">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-content-icon" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
<div class="section" id="easy-fs">
<h1>简易文件系统 easy-fs (下)<a class="headerlink" href="#easy-fs" title="永久链接至标题"></a></h1>
<div class="section" id="id1">
<h2>磁盘块管理器<a class="headerlink" href="#id1" title="永久链接至标题"></a></h2>
<p>本层的代码在 <code class="docutils literal notranslate"><span class="pre">efs.rs</span></code> 中。</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/efs.rs</span>
<span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">EasyFileSystem</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="n">block_device</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span class="n">BlockDevice</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="n">inode_bitmap</span>: <span class="nc">Bitmap</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="n">data_bitmap</span>: <span class="nc">Bitmap</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">inode_area_start_block</span>: <span class="kt">u32</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">data_area_start_block</span>: <span class="kt">u32</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">EasyFileSystem</span></code> 包含索引节点和数据块的两个位图 <code class="docutils literal notranslate"><span class="pre">inode_bitmap</span></code><code class="docutils literal notranslate"><span class="pre">data_bitmap</span></code> ,还记录下索引节点区域和数据块区域起始块编号方便确定每个索引节点和数据块在磁盘上的具体位置。我们还要在其中保留块设备的一个指针 <code class="docutils literal notranslate"><span class="pre">block_device</span></code> ,在进行后续操作的时候,该指针会被拷贝并传递给下层的数据结构,让它们也能够直接访问块设备。</p>
<p>通过 <code class="docutils literal notranslate"><span class="pre">create</span></code> 方法可以在块设备上创建并初始化一个 easy-fs 文件系统:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// easy-fs/src/efs.rs</span>
<span class="linenos"> 2</span>
<span class="linenos"> 3</span><span class="k">impl</span><span class="w"> </span><span class="n">EasyFileSystem</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 4</span><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">create</span><span class="p">(</span><span class="w"></span>
<span class="linenos"> 5</span><span class="w"> </span><span class="n">block_device</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span class="n">BlockDevice</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="linenos"> 6</span><span class="w"> </span><span class="n">total_blocks</span>: <span class="kt">u32</span><span class="p">,</span><span class="w"></span>
<span class="linenos"> 7</span><span class="w"> </span><span class="n">inode_bitmap_blocks</span>: <span class="kt">u32</span><span class="p">,</span><span class="w"></span>
<span class="linenos"> 8</span><span class="w"> </span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Arc</span><span class="o">&lt;</span><span class="n">Mutex</span><span class="o">&lt;</span><span class="bp">Self</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 9</span><span class="w"> </span><span class="c1">// calculate block size of areas &amp; create bitmaps</span>
<span class="linenos">10</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">inode_bitmap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Bitmap</span>::<span class="n">new</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">inode_bitmap_blocks</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">);</span><span class="w"></span>
<span class="linenos">11</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">inode_num</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">inode_bitmap</span><span class="p">.</span><span class="n">maximum</span><span class="p">();</span><span class="w"></span>
<span class="linenos">12</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">inode_area_blocks</span><span class="w"> </span><span class="o">=</span><span class="w"></span>
<span class="linenos">13</span><span class="w"> </span><span class="p">((</span><span class="n">inode_num</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">core</span>::<span class="n">mem</span>::<span class="n">size_of</span>::<span class="o">&lt;</span><span class="n">DiskInode</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">BLOCK_SZ</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">BLOCK_SZ</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u32</span><span class="p">;</span><span class="w"></span>
<span class="linenos">14</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">inode_total_blocks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">inode_bitmap_blocks</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">inode_area_blocks</span><span class="p">;</span><span class="w"></span>
<span class="linenos">15</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">data_total_blocks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">total_blocks</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">inode_total_blocks</span><span class="p">;</span><span class="w"></span>
<span class="linenos">16</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">data_bitmap_blocks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">data_total_blocks</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">4096</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">4097</span><span class="p">;</span><span class="w"></span>
<span class="linenos">17</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">data_area_blocks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">data_total_blocks</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">data_bitmap_blocks</span><span class="p">;</span><span class="w"></span>
<span class="linenos">18</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">data_bitmap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Bitmap</span>::<span class="n">new</span><span class="p">(</span><span class="w"></span>
<span class="linenos">19</span><span class="w"> </span><span class="p">(</span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">inode_bitmap_blocks</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">inode_area_blocks</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="linenos">20</span><span class="w"> </span><span class="n">data_bitmap_blocks</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="linenos">21</span><span class="w"> </span><span class="p">);</span><span class="w"></span>
<span class="linenos">22</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">efs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">23</span><span class="w"> </span><span class="n">block_device</span>: <span class="nc">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&amp;</span><span class="n">block_device</span><span class="p">),</span><span class="w"></span>
<span class="linenos">24</span><span class="w"> </span><span class="n">inode_bitmap</span><span class="p">,</span><span class="w"></span>
<span class="linenos">25</span><span class="w"> </span><span class="n">data_bitmap</span><span class="p">,</span><span class="w"></span>
<span class="linenos">26</span><span class="w"> </span><span class="n">inode_area_start_block</span>: <span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">inode_bitmap_blocks</span><span class="p">,</span><span class="w"></span>
<span class="linenos">27</span><span class="w"> </span><span class="n">data_area_start_block</span>: <span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">inode_total_blocks</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">data_bitmap_blocks</span><span class="p">,</span><span class="w"></span>
<span class="linenos">28</span><span class="w"> </span><span class="p">};</span><span class="w"></span>
<span class="linenos">29</span><span class="w"> </span><span class="c1">// clear all blocks</span>
<span class="linenos">30</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="n">total_blocks</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">31</span><span class="w"> </span><span class="n">get_block_cache</span><span class="p">(</span><span class="w"></span>
<span class="linenos">32</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="linenos">33</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&amp;</span><span class="n">block_device</span><span class="p">)</span><span class="w"></span>
<span class="linenos">34</span><span class="w"> </span><span class="p">)</span><span class="w"></span>
<span class="linenos">35</span><span class="w"> </span><span class="p">.</span><span class="n">lock</span><span class="p">()</span><span class="w"></span>
<span class="linenos">36</span><span class="w"> </span><span class="p">.</span><span class="n">modify</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="n">data_block</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">DataBlock</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">37</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">byte</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">data_block</span><span class="p">.</span><span class="n">iter_mut</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">*</span><span class="n">byte</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">38</span><span class="w"> </span><span class="p">});</span><span class="w"></span>
<span class="linenos">39</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">40</span><span class="w"> </span><span class="c1">// initialize SuperBlock</span>
<span class="linenos">41</span><span class="w"> </span><span class="n">get_block_cache</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&amp;</span><span class="n">block_device</span><span class="p">))</span><span class="w"></span>
<span class="linenos">42</span><span class="w"> </span><span class="p">.</span><span class="n">lock</span><span class="p">()</span><span class="w"></span>
<span class="linenos">43</span><span class="w"> </span><span class="p">.</span><span class="n">modify</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="n">super_block</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">SuperBlock</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">44</span><span class="w"> </span><span class="n">super_block</span><span class="p">.</span><span class="n">initialize</span><span class="p">(</span><span class="w"></span>
<span class="linenos">45</span><span class="w"> </span><span class="n">total_blocks</span><span class="p">,</span><span class="w"></span>
<span class="linenos">46</span><span class="w"> </span><span class="n">inode_bitmap_blocks</span><span class="p">,</span><span class="w"></span>
<span class="linenos">47</span><span class="w"> </span><span class="n">inode_area_blocks</span><span class="p">,</span><span class="w"></span>
<span class="linenos">48</span><span class="w"> </span><span class="n">data_bitmap_blocks</span><span class="p">,</span><span class="w"></span>
<span class="linenos">49</span><span class="w"> </span><span class="n">data_area_blocks</span><span class="p">,</span><span class="w"></span>
<span class="linenos">50</span><span class="w"> </span><span class="p">);</span><span class="w"></span>
<span class="linenos">51</span><span class="w"> </span><span class="p">});</span><span class="w"></span>
<span class="linenos">52</span><span class="w"> </span><span class="c1">// write back immediately</span>
<span class="linenos">53</span><span class="w"> </span><span class="c1">// create a inode for root node "/"</span>
<span class="linenos">54</span><span class="w"> </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">efs</span><span class="p">.</span><span class="n">alloc_inode</span><span class="p">(),</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="linenos">55</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">root_inode_block_id</span><span class="p">,</span><span class="w"> </span><span class="n">root_inode_offset</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">efs</span><span class="p">.</span><span class="n">get_disk_inode_pos</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="linenos">56</span><span class="w"> </span><span class="n">get_block_cache</span><span class="p">(</span><span class="w"></span>
<span class="linenos">57</span><span class="w"> </span><span class="n">root_inode_block_id</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="linenos">58</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&amp;</span><span class="n">block_device</span><span class="p">)</span><span class="w"></span>
<span class="linenos">59</span><span class="w"> </span><span class="p">)</span><span class="w"></span>
<span class="linenos">60</span><span class="w"> </span><span class="p">.</span><span class="n">lock</span><span class="p">()</span><span class="w"></span>
<span class="linenos">61</span><span class="w"> </span><span class="p">.</span><span class="n">modify</span><span class="p">(</span><span class="n">root_inode_offset</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="n">disk_inode</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">DiskInode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">62</span><span class="w"> </span><span class="n">disk_inode</span><span class="p">.</span><span class="n">initialize</span><span class="p">(</span><span class="n">DiskInodeType</span>::<span class="n">Directory</span><span class="p">);</span><span class="w"></span>
<span class="linenos">63</span><span class="w"> </span><span class="p">});</span><span class="w"></span>
<span class="linenos">64</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="n">Mutex</span>::<span class="n">new</span><span class="p">(</span><span class="n">efs</span><span class="p">))</span><span class="w"></span>
<span class="linenos">65</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">66</span><span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<ul class="simple">
<li><p>第 10~21 行根据传入的参数计算每个区域各应该包含多少块。根据 inode 位图的大小计算 inode 区域至少需要多少个块才能够使得 inode 位图中的每个bit都能够有一个实际的 inode 可以对应,这样就确定了 inode 位图区域和 inode 区域的大小。剩下的块都分配给数据块位图区域和数据块区域。我们希望数据块位图中的每个bit仍然能够对应到一个数据块但是数据块位图又不能过小不然会造成某些数据块永远不会被使用。因此数据块位图区域最合理的大小是剩余的块数除以 4097 再上取整,因为位图中的每个块能够对应 4096 个数据块。其余的块就都作为数据块使用。</p></li>
<li><p>第 22 行创建我们的 <code class="docutils literal notranslate"><span class="pre">EasyFileSystem</span></code> 实例 <code class="docutils literal notranslate"><span class="pre">efs</span></code></p></li>
<li><p>第 30 行首先将块设备的前 <code class="docutils literal notranslate"><span class="pre">total_blocks</span></code> 个块清零,因为我们的 easy-fs 要用到它们,这也是为初始化做准备。</p></li>
<li><p>第 41 行将位于块设备编号为 0 块上的超级块进行初始化,只需传入之前计算得到的每个区域的块数就行了。</p></li>
<li><p>第 54~63 行我们要做的事情是创建根目录 <code class="docutils literal notranslate"><span class="pre">/</span></code> 。首先需要调用 <code class="docutils literal notranslate"><span class="pre">alloc_inode</span></code> 在 inode 位图中分配一个 inode ,由于这是第一次分配,它的编号固定是 0 。接下来需要将分配到的 inode 初始化为 easy-fs 中的唯一一个目录,我们需要调用 <code class="docutils literal notranslate"><span class="pre">get_disk_inode_pos</span></code> 来根据 inode 编号获取该 inode 所在的块的编号以及块内偏移,之后就可以将它们传给 <code class="docutils literal notranslate"><span class="pre">get_block_cache</span></code><code class="docutils literal notranslate"><span class="pre">modify</span></code> 了。</p></li>
</ul>
<p>通过 <code class="docutils literal notranslate"><span class="pre">open</span></code> 方法可以从一个已写入了 easy-fs 镜像的块设备上打开我们的 easy-fs </p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/efs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">EasyFileSystem</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">open</span><span class="p">(</span><span class="n">block_device</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span class="n">BlockDevice</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Arc</span><span class="o">&lt;</span><span class="n">Mutex</span><span class="o">&lt;</span><span class="bp">Self</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="c1">// read SuperBlock</span>
<span class="w"> </span><span class="n">get_block_cache</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&amp;</span><span class="n">block_device</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="p">.</span><span class="n">lock</span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="n">super_block</span>: <span class="kp">&amp;</span><span class="nc">SuperBlock</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="fm">assert!</span><span class="p">(</span><span class="n">super_block</span><span class="p">.</span><span class="n">is_valid</span><span class="p">(),</span><span class="w"> </span><span class="s">"Error loading EFS!"</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">inode_total_blocks</span><span class="w"> </span><span class="o">=</span><span class="w"></span>
<span class="w"> </span><span class="n">super_block</span><span class="p">.</span><span class="n">inode_bitmap_blocks</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">super_block</span><span class="p">.</span><span class="n">inode_area_blocks</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">efs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">block_device</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">inode_bitmap</span>: <span class="nc">Bitmap</span>::<span class="n">new</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">super_block</span><span class="p">.</span><span class="n">inode_bitmap_blocks</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="w"></span>
<span class="w"> </span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">data_bitmap</span>: <span class="nc">Bitmap</span>::<span class="n">new</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="p">(</span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">inode_total_blocks</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">super_block</span><span class="p">.</span><span class="n">data_bitmap_blocks</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">inode_area_start_block</span>: <span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">super_block</span><span class="p">.</span><span class="n">inode_bitmap_blocks</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">data_area_start_block</span>: <span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">inode_total_blocks</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">super_block</span><span class="p">.</span><span class="n">data_bitmap_blocks</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">};</span><span class="w"></span>
<span class="w"> </span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="n">Mutex</span>::<span class="n">new</span><span class="p">(</span><span class="n">efs</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>它只需将块设备编号为 0 的块作为超级块读取进来,就可以从中知道 easy-fs 的磁盘布局,由此可以构造 <code class="docutils literal notranslate"><span class="pre">efs</span></code> 实例。</p>
<p><code class="docutils literal notranslate"><span class="pre">EasyFileSystem</span></code> 知道整个磁盘布局,即可以从 inode位图 或数据块位图上分配的 bit 编号来算出各个存储inode和数据块的磁盘块在磁盘上的实际位置。</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/efs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">EasyFileSystem</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">get_disk_inode_pos</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">inode_id</span>: <span class="kt">u32</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="p">(</span><span class="kt">u32</span><span class="p">,</span><span class="w"> </span><span class="kt">usize</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">inode_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">core</span>::<span class="n">mem</span>::<span class="n">size_of</span>::<span class="o">&lt;</span><span class="n">DiskInode</span><span class="o">&gt;</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">inodes_per_block</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">BLOCK_SZ</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">inode_size</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u32</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">block_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">inode_area_start_block</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">inode_id</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">inodes_per_block</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="p">(</span><span class="n">block_id</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="n">inode_id</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">inodes_per_block</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">inode_size</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">get_data_block_id</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">data_block_id</span>: <span class="kt">u32</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">u32</span> <span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">data_area_start_block</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">data_block_id</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>inode 和数据块的分配/回收也由它负责:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/efs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">EasyFileSystem</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">alloc_inode</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">u32</span> <span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">inode_bitmap</span><span class="p">.</span><span class="n">alloc</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">).</span><span class="n">unwrap</span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u32</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="sd">/// Return a block ID not ID in the data area.</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">alloc_data</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">u32</span> <span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">data_bitmap</span><span class="p">.</span><span class="n">alloc</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">).</span><span class="n">unwrap</span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u32</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">data_area_start_block</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">dealloc_data</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">block_id</span>: <span class="kt">u32</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">get_block_cache</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">block_id</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">.</span><span class="n">lock</span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="p">.</span><span class="n">modify</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="n">data_block</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">DataBlock</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">data_block</span><span class="p">.</span><span class="n">iter_mut</span><span class="p">().</span><span class="n">for_each</span><span class="p">(</span><span class="o">|</span><span class="n">p</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">*</span><span class="n">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w"> </span><span class="p">});</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">data_bitmap</span><span class="p">.</span><span class="n">dealloc</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">(</span><span class="n">block_id</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">data_area_start_block</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="w"></span>
<span class="w"> </span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>注意:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">alloc_data</span></code><code class="docutils literal notranslate"><span class="pre">dealloc_data</span></code> 分配/回收数据块传入/返回的参数都表示数据块在块设备上的编号而不是在数据块位图中分配的bit编号</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">dealloc_inode</span></code> 未实现,不支持文件删除。</p></li>
</ul>
</div>
<div class="section" id="id2">
<h2>索引节点<a class="headerlink" href="#id2" title="永久链接至标题"></a></h2>
<p>服务于文件相关系统调用的索引节点层的代码在 <code class="docutils literal notranslate"><span class="pre">vfs.rs</span></code> 中。</p>
<p><code class="docutils literal notranslate"><span class="pre">EasyFileSystem</span></code> 实现了我们设计的磁盘布局并能够将所有块有效的管理起来。但是对于文件系统的使用者而言,他们往往不关心磁盘布局是如何实现的,而是更希望能够直接看到目录树结构中逻辑上的文件和目录。为此我们设计索引节点 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 暴露给文件系统的使用者,让他们能够直接对文件和目录进行操作。 <code class="docutils literal notranslate"><span class="pre">Inode</span></code><code class="docutils literal notranslate"><span class="pre">DiskInode</span></code> 的区别从它们的名字中就可以看出: <code class="docutils literal notranslate"><span class="pre">DiskInode</span></code> 放在磁盘块中比较固定的位置,而 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 是放在内存中的记录文件索引节点信息的数据结构。</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/vfs.rs</span>
<span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">Inode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">block_id</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">block_offset</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">fs</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="n">Mutex</span><span class="o">&lt;</span><span class="n">EasyFileSystem</span><span class="o">&gt;&gt;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">block_device</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span class="n">BlockDevice</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">block_id</span></code><code class="docutils literal notranslate"><span class="pre">block_offset</span></code> 记录该 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 对应的 <code class="docutils literal notranslate"><span class="pre">DiskInode</span></code> 保存在磁盘上的具体位置方便我们后续对它进行访问。 <code class="docutils literal notranslate"><span class="pre">fs</span></code> 是指向 <code class="docutils literal notranslate"><span class="pre">EasyFileSystem</span></code> 的一个指针,因为对 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 的种种操作实际上都是要通过底层的文件系统来完成。</p>
<p>仿照 <code class="docutils literal notranslate"><span class="pre">BlockCache::read/modify</span></code> ,我们可以设计两个方法来简化对于 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 对应的磁盘上的 <code class="docutils literal notranslate"><span class="pre">DiskInode</span></code> 的访问流程,而不是每次都需要 <code class="docutils literal notranslate"><span class="pre">get_block_cache.lock.read/modify</span></code> </p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/vfs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">Inode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">read_disk_inode</span><span class="o">&lt;</span><span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">f</span>: <span class="nc">impl</span><span class="w"> </span><span class="nb">FnOnce</span><span class="p">(</span><span class="o">&amp;</span><span class="n">DiskInode</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">V</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">V</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">get_block_cache</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">block_id</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">).</span><span class="n">lock</span><span class="p">().</span><span class="n">read</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">block_offset</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">modify_disk_inode</span><span class="o">&lt;</span><span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">f</span>: <span class="nc">impl</span><span class="w"> </span><span class="nb">FnOnce</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">DiskInode</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">V</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">V</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">get_block_cache</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">block_id</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">).</span><span class="n">lock</span><span class="p">().</span><span class="n">modify</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">block_offset</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>下面我们分别介绍文件系统的使用者对于文件系统的一些常用操作:</p>
<div class="section" id="inode">
<h3>获取根目录的 inode<a class="headerlink" href="#inode" title="永久链接至标题"></a></h3>
<p>文件系统的使用者在通过 <code class="docutils literal notranslate"><span class="pre">EasyFileSystem::open</span></code> 从装载了 easy-fs 镜像的块设备上打开 easy-fs 之后,要做的第一件事情就是获取根目录的 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 。因为我们目前仅支持绝对路径,对于任何文件/目录的索引都必须从根目录开始向下逐级进行。等到索引完成之后,我们才能对文件/目录进行操作。事实上 <code class="docutils literal notranslate"><span class="pre">EasyFileSystem</span></code> 提供了另一个名为 <code class="docutils literal notranslate"><span class="pre">root_inode</span></code> 的方法来获取根目录的 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> :</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/efs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">EasyFileSystem</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">root_inode</span><span class="p">(</span><span class="n">efs</span>: <span class="kp">&amp;</span><span class="nc">Arc</span><span class="o">&lt;</span><span class="n">Mutex</span><span class="o">&lt;</span><span class="bp">Self</span><span class="o">&gt;&gt;</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Inode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">block_device</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&amp;</span><span class="n">efs</span><span class="p">.</span><span class="n">lock</span><span class="p">().</span><span class="n">block_device</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="c1">// acquire efs lock temporarily</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">block_id</span><span class="p">,</span><span class="w"> </span><span class="n">block_offset</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">efs</span><span class="p">.</span><span class="n">lock</span><span class="p">().</span><span class="n">get_disk_inode_pos</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="c1">// release efs lock</span>
<span class="w"> </span><span class="n">Inode</span>::<span class="n">new</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">block_id</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">block_offset</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="n">efs</span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">block_device</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="c1">// easy-fs/src/vfs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">Inode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="sd">/// We should not acquire efs lock here.</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">new</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">block_id</span>: <span class="kt">u32</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">block_offset</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">fs</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="n">Mutex</span><span class="o">&lt;</span><span class="n">EasyFileSystem</span><span class="o">&gt;&gt;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">block_device</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span class="n">BlockDevice</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">block_id</span>: <span class="nc">block_id</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">block_offset</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">fs</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">block_device</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">root_inode</span></code> 中,主要是在 <code class="docutils literal notranslate"><span class="pre">Inode::new</span></code> 的时候将传入的 <code class="docutils literal notranslate"><span class="pre">inode_id</span></code> 设置为 0 ,因为根目录对应于文件系统中第一个分配的 inode ,因此它的 <code class="docutils literal notranslate"><span class="pre">inode_id</span></code> 总会是 0 。同时在设计上,我们不会在 <code class="docutils literal notranslate"><span class="pre">Inode::new</span></code> 中尝试获取整个 <code class="docutils literal notranslate"><span class="pre">EasyFileSystem</span></code> 的锁来查询 inode 在块设备中的位置,而是在调用它之前预先查询并作为参数传过去。</p>
</div>
<div class="section" id="id3">
<h3>文件索引<a class="headerlink" href="#id3" title="永久链接至标题"></a></h3>
<p>为了尽可能简化我们的实现,所有的文件都在根目录下面。于是,我们不必实现目录索引。文件索引的查找比较简单,仅需在根目录的目录项中根据文件名找到文件的 inode 编号即可。由于没有子目录的存在,这个过程只会进行一次。</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/vfs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">Inode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">find</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">name</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Option</span><span class="o">&lt;</span><span class="n">Arc</span><span class="o">&lt;</span><span class="n">Inode</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">fs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">fs</span><span class="p">.</span><span class="n">lock</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">read_disk_inode</span><span class="p">(</span><span class="o">|</span><span class="n">disk_inode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">find_inode_id</span><span class="p">(</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">disk_inode</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="o">|</span><span class="n">inode_id</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">block_id</span><span class="p">,</span><span class="w"> </span><span class="n">block_offset</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fs</span><span class="p">.</span><span class="n">get_disk_inode_pos</span><span class="p">(</span><span class="n">inode_id</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="bp">Self</span>::<span class="n">new</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">block_id</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">block_offset</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">fs</span><span class="p">.</span><span class="n">clone</span><span class="p">(),</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">.</span><span class="n">clone</span><span class="p">(),</span><span class="w"></span>
<span class="w"> </span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">find_inode_id</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">name</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">disk_inode</span>: <span class="kp">&amp;</span><span class="nc">DiskInode</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Option</span><span class="o">&lt;</span><span class="kt">u32</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="c1">// assert it is a directory</span>
<span class="w"> </span><span class="fm">assert!</span><span class="p">(</span><span class="n">disk_inode</span><span class="p">.</span><span class="n">is_dir</span><span class="p">());</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">file_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">disk_inode</span><span class="p">.</span><span class="n">size</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">DIRENT_SZ</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">dirent</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">DirEntry</span>::<span class="n">empty</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="n">file_count</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">disk_inode</span><span class="p">.</span><span class="n">read_at</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">DIRENT_SZ</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">dirent</span><span class="p">.</span><span class="n">as_bytes_mut</span><span class="p">(),</span><span class="w"></span>
<span class="w"> </span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">DIRENT_SZ</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">dirent</span><span class="p">.</span><span class="n">name</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">dirent</span><span class="p">.</span><span class="n">inode_number</span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u32</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="nb">None</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">find</span></code> 方法只会被根目录 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 调用,文件系统中其他文件的 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 不会调用这个方法。它首先调用 <code class="docutils literal notranslate"><span class="pre">find_inode_id</span></code> 方法尝试从根目录的 <code class="docutils literal notranslate"><span class="pre">DiskInode</span></code> 上找到要索引的文件名对应的 inode 编号。这就需要将根目录内容中的所有目录项都读到内存进行逐个比对。如果能够找到的话, <code class="docutils literal notranslate"><span class="pre">find</span></code> 方法会根据查到 inode 编号对应生成一个 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 用于后续对文件的访问。</p>
<p>这里需要注意的是,包括 <code class="docutils literal notranslate"><span class="pre">find</span></code> 在内所有暴露给文件系统的使用者的文件系统操作(还包括接下来将要介绍的几种),全程均需持有 <code class="docutils literal notranslate"><span class="pre">EasyFileSystem</span></code> 的互斥锁(相对的,文件系统内部的操作如之前的 <code class="docutils literal notranslate"><span class="pre">Inode::new</span></code> 或是上面的 <code class="docutils literal notranslate"><span class="pre">find_inode_id</span></code> 都是假定在已持有 efs 锁的情况下才被调用的,因此它们不应尝试获取锁)。这能够保证在多核情况下,同时最多只能有一个核在进行文件系统相关操作。这样也许会带来一些不必要的性能损失,但我们目前暂时先这样做。如果我们在这里加锁的话,其实就能够保证块缓存的互斥访问了。</p>
</div>
<div class="section" id="id4">
<h3>文件列举<a class="headerlink" href="#id4" title="永久链接至标题"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">ls</span></code> 方法可以收集根目录下的所有文件的文件名并以向量的形式返回,这个方法只有根目录的 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 才会调用:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/vfs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">Inode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">ls</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Vec</span><span class="o">&lt;</span><span class="nb">String</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">_fs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">fs</span><span class="p">.</span><span class="n">lock</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">read_disk_inode</span><span class="p">(</span><span class="o">|</span><span class="n">disk_inode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">file_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">disk_inode</span><span class="p">.</span><span class="n">size</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">DIRENT_SZ</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">v</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="nb">String</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="n">file_count</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">dirent</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">DirEntry</span>::<span class="n">empty</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">disk_inode</span><span class="p">.</span><span class="n">read_at</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">DIRENT_SZ</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">dirent</span><span class="p">.</span><span class="n">as_bytes_mut</span><span class="p">(),</span><span class="w"></span>
<span class="w"> </span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">),</span><span class="w"></span>
<span class="w"> </span><span class="n">DIRENT_SZ</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="nb">String</span>::<span class="n">from</span><span class="p">(</span><span class="n">dirent</span><span class="p">.</span><span class="n">name</span><span class="p">()));</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="n">v</span><span class="w"></span>
<span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
</div>
<div class="section" id="id5">
<h3>文件创建<a class="headerlink" href="#id5" title="永久链接至标题"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">create</span></code> 方法可以在根目录下创建一个文件,该方法只有根目录的 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 会调用:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// easy-fs/src/vfs.rs</span>
<span class="linenos"> 2</span>
<span class="linenos"> 3</span><span class="k">impl</span><span class="w"> </span><span class="n">Inode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 4</span><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">create</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">name</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Option</span><span class="o">&lt;</span><span class="n">Arc</span><span class="o">&lt;</span><span class="n">Inode</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 5</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">fs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">fs</span><span class="p">.</span><span class="n">lock</span><span class="p">();</span><span class="w"></span>
<span class="linenos"> 6</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">modify_disk_inode</span><span class="p">(</span><span class="o">|</span><span class="n">root_inode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 7</span><span class="w"> </span><span class="c1">// assert it is a directory</span>
<span class="linenos"> 8</span><span class="w"> </span><span class="fm">assert!</span><span class="p">(</span><span class="n">root_inode</span><span class="p">.</span><span class="n">is_dir</span><span class="p">());</span><span class="w"></span>
<span class="linenos"> 9</span><span class="w"> </span><span class="c1">// has the file been created?</span>
<span class="linenos">10</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">find_inode_id</span><span class="p">(</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">root_inode</span><span class="p">)</span><span class="w"></span>
<span class="linenos">11</span><span class="w"> </span><span class="p">}).</span><span class="n">is_some</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">12</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">None</span><span class="p">;</span><span class="w"></span>
<span class="linenos">13</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">14</span><span class="w"> </span><span class="c1">// create a new file</span>
<span class="linenos">15</span><span class="w"> </span><span class="c1">// alloc a inode with an indirect block</span>
<span class="linenos">16</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">new_inode_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fs</span><span class="p">.</span><span class="n">alloc_inode</span><span class="p">();</span><span class="w"></span>
<span class="linenos">17</span><span class="w"> </span><span class="c1">// initialize inode</span>
<span class="linenos">18</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">new_inode_block_id</span><span class="p">,</span><span class="w"> </span><span class="n">new_inode_block_offset</span><span class="p">)</span><span class="w"></span>
<span class="linenos">19</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fs</span><span class="p">.</span><span class="n">get_disk_inode_pos</span><span class="p">(</span><span class="n">new_inode_id</span><span class="p">);</span><span class="w"></span>
<span class="linenos">20</span><span class="w"> </span><span class="n">get_block_cache</span><span class="p">(</span><span class="w"></span>
<span class="linenos">21</span><span class="w"> </span><span class="n">new_inode_block_id</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="linenos">22</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">)</span><span class="w"></span>
<span class="linenos">23</span><span class="w"> </span><span class="p">).</span><span class="n">lock</span><span class="p">().</span><span class="n">modify</span><span class="p">(</span><span class="n">new_inode_block_offset</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="n">new_inode</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">DiskInode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">24</span><span class="w"> </span><span class="n">new_inode</span><span class="p">.</span><span class="n">initialize</span><span class="p">(</span><span class="n">DiskInodeType</span>::<span class="n">File</span><span class="p">);</span><span class="w"></span>
<span class="linenos">25</span><span class="w"> </span><span class="p">});</span><span class="w"></span>
<span class="linenos">26</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">modify_disk_inode</span><span class="p">(</span><span class="o">|</span><span class="n">root_inode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">27</span><span class="w"> </span><span class="c1">// append file in the dirent</span>
<span class="linenos">28</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">file_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">root_inode</span><span class="p">.</span><span class="n">size</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">DIRENT_SZ</span><span class="p">;</span><span class="w"></span>
<span class="linenos">29</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">new_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">file_count</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">DIRENT_SZ</span><span class="p">;</span><span class="w"></span>
<span class="linenos">30</span><span class="w"> </span><span class="c1">// increase size</span>
<span class="linenos">31</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">increase_size</span><span class="p">(</span><span class="n">new_size</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u32</span><span class="p">,</span><span class="w"> </span><span class="n">root_inode</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">fs</span><span class="p">);</span><span class="w"></span>
<span class="linenos">32</span><span class="w"> </span><span class="c1">// write dirent</span>
<span class="linenos">33</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">dirent</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">DirEntry</span>::<span class="n">new</span><span class="p">(</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">new_inode_id</span><span class="p">);</span><span class="w"></span>
<span class="linenos">34</span><span class="w"> </span><span class="n">root_inode</span><span class="p">.</span><span class="n">write_at</span><span class="p">(</span><span class="w"></span>
<span class="linenos">35</span><span class="w"> </span><span class="n">file_count</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">DIRENT_SZ</span><span class="p">,</span><span class="w"></span>
<span class="linenos">36</span><span class="w"> </span><span class="n">dirent</span><span class="p">.</span><span class="n">as_bytes</span><span class="p">(),</span><span class="w"></span>
<span class="linenos">37</span><span class="w"> </span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">,</span><span class="w"></span>
<span class="linenos">38</span><span class="w"> </span><span class="p">);</span><span class="w"></span>
<span class="linenos">39</span><span class="w"> </span><span class="p">});</span><span class="w"></span>
<span class="linenos">40</span>
<span class="linenos">41</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">block_id</span><span class="p">,</span><span class="w"> </span><span class="n">block_offset</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fs</span><span class="p">.</span><span class="n">get_disk_inode_pos</span><span class="p">(</span><span class="n">new_inode_id</span><span class="p">);</span><span class="w"></span>
<span class="linenos">42</span><span class="w"> </span><span class="c1">// return inode</span>
<span class="linenos">43</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="bp">Self</span>::<span class="n">new</span><span class="p">(</span><span class="w"></span>
<span class="linenos">44</span><span class="w"> </span><span class="n">block_id</span><span class="p">,</span><span class="w"></span>
<span class="linenos">45</span><span class="w"> </span><span class="n">block_offset</span><span class="p">,</span><span class="w"></span>
<span class="linenos">46</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">fs</span><span class="p">.</span><span class="n">clone</span><span class="p">(),</span><span class="w"></span>
<span class="linenos">47</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">.</span><span class="n">clone</span><span class="p">(),</span><span class="w"></span>
<span class="linenos">48</span><span class="w"> </span><span class="p">)))</span><span class="w"></span>
<span class="linenos">49</span><span class="w"> </span><span class="c1">// release efs lock automatically by compiler</span>
<span class="linenos">50</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">51</span><span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<ul class="simple">
<li><p>第 6~13 行,检查文件是否已经在根目录下,如果找到的话返回 <code class="docutils literal notranslate"><span class="pre">None</span></code> </p></li>
<li><p>第 14~25 行,为待创建文件分配一个新的 inode 并进行初始化;</p></li>
<li><p>第 26~39 行,将待创建文件的目录项插入到根目录的内容中使得之后可以索引过来。</p></li>
</ul>
</div>
<div class="section" id="id6">
<h3>文件清空<a class="headerlink" href="#id6" title="永久链接至标题"></a></h3>
<p>在以某些标志位打开文件(例如带有 <em>CREATE</em> 标志打开一个已经存在的文件)的时候,需要首先将文件清空。在索引到文件的 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 之后可以调用 <code class="docutils literal notranslate"><span class="pre">clear</span></code> 方法:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/vfs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">Inode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">clear</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">fs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">fs</span><span class="p">.</span><span class="n">lock</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">modify_disk_inode</span><span class="p">(</span><span class="o">|</span><span class="n">disk_inode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">disk_inode</span><span class="p">.</span><span class="n">size</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">data_blocks_dealloc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">disk_inode</span><span class="p">.</span><span class="n">clear_size</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="fm">assert!</span><span class="p">(</span><span class="n">data_blocks_dealloc</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">DiskInode</span>::<span class="n">total_blocks</span><span class="p">(</span><span class="n">size</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">data_block</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">data_blocks_dealloc</span><span class="p">.</span><span class="n">into_iter</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">fs</span><span class="p">.</span><span class="n">dealloc_data</span><span class="p">(</span><span class="n">data_block</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">});</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>这会将之前该文件占据的索引块和数据块在 <code class="docutils literal notranslate"><span class="pre">EasyFileSystem</span></code> 中回收。</p>
</div>
<div class="section" id="id7">
<h3>文件读写<a class="headerlink" href="#id7" title="永久链接至标题"></a></h3>
<p>从根目录索引到一个文件之后可以对它进行读写,注意,和 <code class="docutils literal notranslate"><span class="pre">DiskInode</span></code> 一样,这里的读写作用在字节序列的一段区间上:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/vfs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">Inode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">read_at</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">offset</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span><span class="w"> </span>-&gt; <span class="kt">usize</span> <span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">_fs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">fs</span><span class="p">.</span><span class="n">lock</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">read_disk_inode</span><span class="p">(</span><span class="o">|</span><span class="n">disk_inode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">disk_inode</span><span class="p">.</span><span class="n">read_at</span><span class="p">(</span><span class="n">offset</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">write_at</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">offset</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span>: <span class="kp">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span><span class="w"> </span>-&gt; <span class="kt">usize</span> <span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">fs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">fs</span><span class="p">.</span><span class="n">lock</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">modify_disk_inode</span><span class="p">(</span><span class="o">|</span><span class="n">disk_inode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">increase_size</span><span class="p">((</span><span class="n">offset</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">buf</span><span class="p">.</span><span class="n">len</span><span class="p">())</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u32</span><span class="p">,</span><span class="w"> </span><span class="n">disk_inode</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">fs</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="n">disk_inode</span><span class="p">.</span><span class="n">write_at</span><span class="p">(</span><span class="n">offset</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>具体实现比较简单,需要注意在 <code class="docutils literal notranslate"><span class="pre">DiskInode::write_at</span></code> 之前先调用 <code class="docutils literal notranslate"><span class="pre">increase_size</span></code> 对自身进行扩容:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// easy-fs/src/vfs.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">Inode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">increase_size</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">new_size</span>: <span class="kt">u32</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">disk_inode</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">DiskInode</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">fs</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">MutexGuard</span><span class="o">&lt;</span><span class="n">EasyFileSystem</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">new_size</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">disk_inode</span><span class="p">.</span><span class="n">size</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">return</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">blocks_needed</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">disk_inode</span><span class="p">.</span><span class="n">blocks_num_needed</span><span class="p">(</span><span class="n">new_size</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">v</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="kt">u32</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="n">blocks_needed</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">fs</span><span class="p">.</span><span class="n">alloc_data</span><span class="p">());</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="n">disk_inode</span><span class="p">.</span><span class="n">increase_size</span><span class="p">(</span><span class="n">new_size</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">block_device</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>这里会从 <code class="docutils literal notranslate"><span class="pre">EasyFileSystem</span></code> 中分配一些用于扩容的数据块并传给 <code class="docutils literal notranslate"><span class="pre">DiskInode::increase_size</span></code></p>
</div>
</div>
<div class="section" id="id8">
<h2>将应用打包为 easy-fs 镜像<a class="headerlink" href="#id8" title="永久链接至标题"></a></h2>
<p>在第六章中我们需要将所有的应用都链接到内核中,随后在应用管理器中通过应用名进行索引来找到应用的 ELF 数据。这样做有一个缺点,就是会造成内核体积过度膨胀。同时这也会浪费内存资源,因为未被执行的应用也占据了内存空间。在实现了我们自己的文件系统之后,终于可以将这些应用打包到 easy-fs 镜像中放到磁盘中当我们要执行应用的时候只需从文件系统中取出ELF 执行文件格式的应用 并加载到内存中执行即可,这样就避免了上面的那些问题。</p>
<p><code class="docutils literal notranslate"><span class="pre">easy-fs-fuse</span></code> 的主体 <code class="docutils literal notranslate"><span class="pre">easy-fs-pack</span></code> 函数就实现了这个功能:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// easy-fs-fuse/src/main.rs</span>
<span class="linenos"> 2</span>
<span class="linenos"> 3</span><span class="k">use</span><span class="w"> </span><span class="n">clap</span>::<span class="p">{</span><span class="n">Arg</span><span class="p">,</span><span class="w"> </span><span class="n">App</span><span class="p">};</span><span class="w"></span>
<span class="linenos"> 4</span>
<span class="linenos"> 5</span><span class="k">fn</span> <span class="nf">easy_fs_pack</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">std</span>::<span class="n">io</span>::<span class="nb">Result</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 6</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">matches</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">App</span>::<span class="n">new</span><span class="p">(</span><span class="s">"EasyFileSystem packer"</span><span class="p">)</span><span class="w"></span>
<span class="linenos"> 7</span><span class="w"> </span><span class="p">.</span><span class="n">arg</span><span class="p">(</span><span class="n">Arg</span>::<span class="n">with_name</span><span class="p">(</span><span class="s">"source"</span><span class="p">)</span><span class="w"></span>
<span class="linenos"> 8</span><span class="w"> </span><span class="p">.</span><span class="n">short</span><span class="p">(</span><span class="s">"s"</span><span class="p">)</span><span class="w"></span>
<span class="linenos"> 9</span><span class="w"> </span><span class="p">.</span><span class="n">long</span><span class="p">(</span><span class="s">"source"</span><span class="p">)</span><span class="w"></span>
<span class="linenos">10</span><span class="w"> </span><span class="p">.</span><span class="n">takes_value</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span><span class="w"></span>
<span class="linenos">11</span><span class="w"> </span><span class="p">.</span><span class="n">help</span><span class="p">(</span><span class="s">"Executable source dir(with backslash)"</span><span class="p">)</span><span class="w"></span>
<span class="linenos">12</span><span class="w"> </span><span class="p">)</span><span class="w"></span>
<span class="linenos">13</span><span class="w"> </span><span class="p">.</span><span class="n">arg</span><span class="p">(</span><span class="n">Arg</span>::<span class="n">with_name</span><span class="p">(</span><span class="s">"target"</span><span class="p">)</span><span class="w"></span>
<span class="linenos">14</span><span class="w"> </span><span class="p">.</span><span class="n">short</span><span class="p">(</span><span class="s">"t"</span><span class="p">)</span><span class="w"></span>
<span class="linenos">15</span><span class="w"> </span><span class="p">.</span><span class="n">long</span><span class="p">(</span><span class="s">"target"</span><span class="p">)</span><span class="w"></span>
<span class="linenos">16</span><span class="w"> </span><span class="p">.</span><span class="n">takes_value</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span><span class="w"></span>
<span class="linenos">17</span><span class="w"> </span><span class="p">.</span><span class="n">help</span><span class="p">(</span><span class="s">"Executable target dir(with backslash)"</span><span class="p">)</span><span class="w"></span>
<span class="linenos">18</span><span class="w"> </span><span class="p">)</span><span class="w"></span>
<span class="linenos">19</span><span class="w"> </span><span class="p">.</span><span class="n">get_matches</span><span class="p">();</span><span class="w"></span>
<span class="linenos">20</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">src_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">matches</span><span class="p">.</span><span class="n">value_of</span><span class="p">(</span><span class="s">"source"</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="linenos">21</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">target_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">matches</span><span class="p">.</span><span class="n">value_of</span><span class="p">(</span><span class="s">"target"</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="linenos">22</span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"src_path = {}</span><span class="se">\n</span><span class="s">target_path = {}"</span><span class="p">,</span><span class="w"> </span><span class="n">src_path</span><span class="p">,</span><span class="w"> </span><span class="n">target_path</span><span class="p">);</span><span class="w"></span>
<span class="linenos">23</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">block_file</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="n">BlockFile</span><span class="p">(</span><span class="n">Mutex</span>::<span class="n">new</span><span class="p">({</span><span class="w"></span>
<span class="linenos">24</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">OpenOptions</span>::<span class="n">new</span><span class="p">()</span><span class="w"></span>
<span class="linenos">25</span><span class="w"> </span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span><span class="w"></span>
<span class="linenos">26</span><span class="w"> </span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span><span class="w"></span>
<span class="linenos">27</span><span class="w"> </span><span class="p">.</span><span class="n">create</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span><span class="w"></span>
<span class="linenos">28</span><span class="w"> </span><span class="p">.</span><span class="n">open</span><span class="p">(</span><span class="fm">format!</span><span class="p">(</span><span class="s">"{}{}"</span><span class="p">,</span><span class="w"> </span><span class="n">target_path</span><span class="p">,</span><span class="w"> </span><span class="s">"fs.img"</span><span class="p">))</span><span class="o">?</span><span class="p">;</span><span class="w"></span>
<span class="linenos">29</span><span class="w"> </span><span class="n">f</span><span class="p">.</span><span class="n">set_len</span><span class="p">(</span><span class="mi">8192</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">512</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="linenos">30</span><span class="w"> </span><span class="n">f</span><span class="w"></span>
<span class="linenos">31</span><span class="w"> </span><span class="p">})));</span><span class="w"></span>
<span class="linenos">32</span><span class="w"> </span><span class="c1">// 4MiB, at most 4095 files</span>
<span class="linenos">33</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">efs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">EasyFileSystem</span>::<span class="n">create</span><span class="p">(</span><span class="w"></span>
<span class="linenos">34</span><span class="w"> </span><span class="n">block_file</span><span class="p">.</span><span class="n">clone</span><span class="p">(),</span><span class="w"></span>
<span class="linenos">35</span><span class="w"> </span><span class="mi">8192</span><span class="p">,</span><span class="w"></span>
<span class="linenos">36</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"></span>
<span class="linenos">37</span><span class="w"> </span><span class="p">);</span><span class="w"></span>
<span class="linenos">38</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">root_inode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="n">EasyFileSystem</span>::<span class="n">root_inode</span><span class="p">(</span><span class="o">&amp;</span><span class="n">efs</span><span class="p">));</span><span class="w"></span>
<span class="linenos">39</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">apps</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">_</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">read_dir</span><span class="p">(</span><span class="n">src_path</span><span class="p">)</span><span class="w"></span>
<span class="linenos">40</span><span class="w"> </span><span class="p">.</span><span class="n">unwrap</span><span class="p">()</span><span class="w"></span>
<span class="linenos">41</span><span class="w"> </span><span class="p">.</span><span class="n">into_iter</span><span class="p">()</span><span class="w"></span>
<span class="linenos">42</span><span class="w"> </span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="o">|</span><span class="n">dir_entry</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">43</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">name_with_ext</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dir_entry</span><span class="p">.</span><span class="n">unwrap</span><span class="p">().</span><span class="n">file_name</span><span class="p">().</span><span class="n">into_string</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="linenos">44</span><span class="w"> </span><span class="n">name_with_ext</span><span class="p">.</span><span class="n">drain</span><span class="p">(</span><span class="n">name_with_ext</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="sc">'.'</span><span class="p">).</span><span class="n">unwrap</span><span class="p">()</span><span class="o">..</span><span class="n">name_with_ext</span><span class="p">.</span><span class="n">len</span><span class="p">());</span><span class="w"></span>
<span class="linenos">45</span><span class="w"> </span><span class="n">name_with_ext</span><span class="w"></span>
<span class="linenos">46</span><span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="linenos">47</span><span class="w"> </span><span class="p">.</span><span class="n">collect</span><span class="p">();</span><span class="w"></span>
<span class="linenos">48</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">app</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">apps</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">49</span><span class="w"> </span><span class="c1">// load app data from host file system</span>
<span class="linenos">50</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">host_file</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">File</span>::<span class="n">open</span><span class="p">(</span><span class="fm">format!</span><span class="p">(</span><span class="s">"{}{}"</span><span class="p">,</span><span class="w"> </span><span class="n">target_path</span><span class="p">,</span><span class="w"> </span><span class="n">app</span><span class="p">)).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="linenos">51</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">all_data</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="linenos">52</span><span class="w"> </span><span class="n">host_file</span><span class="p">.</span><span class="n">read_to_end</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">all_data</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="linenos">53</span><span class="w"> </span><span class="c1">// create a file in easy-fs</span>
<span class="linenos">54</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">inode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">root_inode</span><span class="p">.</span><span class="n">create</span><span class="p">(</span><span class="n">app</span><span class="p">.</span><span class="n">as_str</span><span class="p">()).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="linenos">55</span><span class="w"> </span><span class="c1">// write data to easy-fs</span>
<span class="linenos">56</span><span class="w"> </span><span class="n">inode</span><span class="p">.</span><span class="n">write_at</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">all_data</span><span class="p">.</span><span class="n">as_slice</span><span class="p">());</span><span class="w"></span>
<span class="linenos">57</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">58</span><span class="w"> </span><span class="c1">// list apps</span>
<span class="linenos">59</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">app</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">root_inode</span><span class="p">.</span><span class="n">ls</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">60</span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">app</span><span class="p">);</span><span class="w"></span>
<span class="linenos">61</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">62</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(())</span><span class="w"></span>
<span class="linenos">63</span><span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<ul class="simple">
<li><p>为了实现 <code class="docutils literal notranslate"><span class="pre">easy-fs-fuse</span></code><code class="docutils literal notranslate"><span class="pre">os/user</span></code> 的解耦,第 6~21 行使用 <code class="docutils literal notranslate"><span class="pre">clap</span></code> crate 进行命令行参数解析,需要通过 <code class="docutils literal notranslate"><span class="pre">-s</span></code><code class="docutils literal notranslate"><span class="pre">-t</span></code> 分别指定应用的源代码目录和保存应用 ELF 的目录而不是在 <code class="docutils literal notranslate"><span class="pre">easy-fs-fuse</span></code> 中硬编码。如果解析成功的话它们会分别被保存在变量 <code class="docutils literal notranslate"><span class="pre">src_path</span></code><code class="docutils literal notranslate"><span class="pre">target_path</span></code> 中。</p></li>
<li><p>第 23~38 行依次完成:创建 4MiB 的 easy-fs 镜像文件、进行 easy-fs 初始化、获取根目录 inode 。</p></li>
<li><p>第 39 行获取源码目录中的每个应用的源代码文件并去掉后缀名,收集到向量 <code class="docutils literal notranslate"><span class="pre">apps</span></code> 中。</p></li>
<li><p>第 48 行开始,枚举 <code class="docutils literal notranslate"><span class="pre">apps</span></code> 中的每个应用,从放置应用执行程序的目录中找到对应应用的 ELF 文件(这是一个 HostOS 上的文件)并将数据读入内存。接着需要在我们的 easy-fs 中创建一个同名文件并将 ELF 数据写入到这个文件中。这个过程相当于将 HostOS 上的文件系统中的一个文件复制到我们的 easy-fs 中。</p></li>
</ul>
<p>尽管没有进行任何同步写回磁盘的操作,我们也不用担心块缓存中的修改没有写回磁盘。因为在 <code class="docutils literal notranslate"><span class="pre">easy-fs-fuse</span></code> 这个应用正常退出的过程中,块缓存因生命周期结束会被回收,届时如果 <code class="docutils literal notranslate"><span class="pre">modified</span></code> 标志为 true 就会将修改写回磁盘。</p>
</div>
</div>
</article>
<footer>
<div class="related-pages">
<a class="next-page" href="3using-easy-fs-in-kernel.html">
<div class="page-info">
<div class="context">
<span>Next</span>
</div>
<div class="title">在内核中使用 easy-fs</div>
</div>
<svg><use href="#svg-arrow-right"></use></svg>
</a>
<a class="prev-page" href="2fs-implementation-1.html">
<svg><use href="#svg-arrow-right"></use></svg>
<div class="page-info">
<div class="context">
<span>Previous</span>
</div>
<div class="title">简易文件系统 easy-fs (上)</div>
</div>
</a>
</div>
<div class="related-information">
Copyright &#169; OS2022Summer
|
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a>
and
<a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
<a href="https://github.com/pradyunsg/furo">Furo theme</a>.
|
<a class="muted-link" href="../_sources/chapter6/2fs-implementation-2.rst.txt"
rel="nofollow">
显示源代码
</a>
</div>
</footer>
</div>
<aside class="toc-drawer">
<div class="toc-sticky toc-scroll">
<div class="toc-title-container">
<span class="toc-title">
目录
</span>
</div>
<div class="toc-tree-container">
<div class="toc-tree">
<ul>
<li><a class="reference internal" href="#">简易文件系统 easy-fs (下)</a><ul>
<li><a class="reference internal" href="#id1">磁盘块管理器</a></li>
<li><a class="reference internal" href="#id2">索引节点</a><ul>
<li><a class="reference internal" href="#inode">获取根目录的 inode</a></li>
<li><a class="reference internal" href="#id3">文件索引</a></li>
<li><a class="reference internal" href="#id4">文件列举</a></li>
<li><a class="reference internal" href="#id5">文件创建</a></li>
<li><a class="reference internal" href="#id6">文件清空</a></li>
<li><a class="reference internal" href="#id7">文件读写</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id8">将应用打包为 easy-fs 镜像</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</aside>
</div>
</div><script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/scripts/main.js"></script>
<script kind="utterances">
var commentsRunWhenDOMLoaded = cb => {
if (document.readyState != 'loading') {
cb()
} else if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', cb)
} else {
document.attachEvent('onreadystatechange', function() {
if (document.readyState == 'complete') cb()
})
}
}
var addUtterances = () => {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://utteranc.es/client.js";
script.async = "async";
script.setAttribute("repo", "LearningOS/rust-based-os-comp2022");
script.setAttribute("issue-term", "pathname");
script.setAttribute("theme", "github-light");
script.setAttribute("label", "comments");
script.setAttribute("crossorigin", "anonymous");
sections = document.querySelectorAll("div.section");
if (sections !== null) {
section = sections[sections.length-1];
section.appendChild(script);
}
}
commentsRunWhenDOMLoaded(addUtterances);
</script>
<script src="../_static/translations.js"></script>
</body>
</html>