轻量级虚拟化技术草稿

news2024/10/5 18:24:03

Support Tech

ST.1 virtiofs

ST.1.1 fuse framework

引用wiki中关于fuse的定义:

Filesystem in Userspace (FUSE) is a software interface for Unix and Unix-like computer operating systems that lets non-privileged users create their own file systems without editing kernel code. This is achieved by running file system code in user space while the FUSE module provides only a bridge to the actual kernel interfaces.

其代码框架如下: 

主要分为三部分:

  •  内核Fuse Filsystem Client,对接Linux Kernel的VFS
  • Fuse协议,其中包括了op code及其参数格式,参考GitHub - libfuse/libfuse: The reference implementation of the Linux FUSE (Filesystem in Userspace) interfaceThe reference implementation of the Linux FUSE (Filesystem in Userspace) interface - GitHub - libfuse/libfuse: The reference implementation of the Linux FUSE (Filesystem in Userspace) interfaceicon-default.png?t=N7T8https://github.com/libfuse/libfuse
  •  Fuse传输层,目前包括两种,本地char设备和virtio

参考代码:

fuse_do_readpage()
---
	...
	loff_t pos = page_offset(page);
	struct fuse_page_desc desc = { .length = PAGE_SIZE };
	struct fuse_io_args ia = {
		.ap.args.page_zeroing = true,
		.ap.args.out_pages = true,
		.ap.num_pages = 1,
		.ap.pages = &page,
		.ap.descs = &desc,
	};
	...
	fuse_wait_on_page_writeback(inode, page->index);
	...
	fuse_read_args_fill(&ia, file, pos, desc.length, FUSE_READ);
	res = fuse_simple_request(fm, &ia.ap.args);
	...
	SetPageUptodate(page);
---

fuse_lookup_name()
---
	fuse_lookup_init(fm->fc, &args, nodeid, name, outarg);
	---
		args->opcode = FUSE_LOOKUP;
		args->nodeid = nodeid;
		args->in_numargs = 1;
		args->in_args[0].size = name->len + 1;
		args->in_args[0].value = name->name;
		args->out_numargs = 1;
		args->out_args[0].size = sizeof(struct fuse_entry_out);
		args->out_args[0].value = outarg;
		// fuse_entry_out.attr includes all of inode attributes, such as ino/size/blocks/atime/mtime/ctime/nlink/mode/uid/gid ...
	---
	err = fuse_simple_request(fm, &args);
	...
	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
			   &outarg->attr, entry_attr_timeout(outarg),
			   attr_version);
---


fuse_simple_request()
---
	if (args->force) {
		atomic_inc(&fc->num_waiting);
    	req = fuse_request_alloc(fm, GFP_KERNEL | __GFP_NOFAIL);
		...
		__set_bit(FR_WAITING, &req->flags);
		__set_bit(FR_FORCE, &req->flags);
	} else {
		req = fuse_get_req(fm, false);
		...
	}
	...
	__fuse_request_send(req);
	...
	fuse_put_request(req);
---

__fuse_request_send()
  -> spin_lock(&fiq->lock);
  -> queue_request_and_unlock()
	 ---
		list_add_tail(&req->list, &fiq->pending);
		fiq->ops->wake_pending_and_unlock(fiq);
	 ---
  -> request_wait_answer()
	 ---
	 	if (!fc->no_interrupt) {
			/* Any signal may interrupt this */
			err = wait_event_interruptible(req->waitq,
						test_bit(FR_FINISHED, &req->flags));
			...
		}

		if (!test_bit(FR_FORCE, &req->flags)) {
			/* Only fatal signals may interrupt this */
			err = wait_event_killable(req->waitq,
						test_bit(FR_FINISHED, &req->flags));
			...
		}
		/*
		 * Either request is already in userspace, or it was forced.
		 * Wait it out.
		 */
		wait_event(req->waitq, test_bit(FR_FINISHED, &req->flags));
	 ---

以上代码中列举了两个常见的文件系统操作,readpage和lookup,它们都是同步的,所以,需要request_wait_answer()。

write page的处理代码如下:

fuse_writepage_locked()
---
	tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
	...
	fuse_write_args_fill(&wpa->ia, wpa->ia.ff, page_offset(page), 0);

	copy_highpage(tmp_page, page);
	wpa->ia.write.in.write_flags |= FUSE_WRITE_CACHE;
	wpa->next = NULL;
	ap->args.in_pages = true;
	ap->num_pages = 1;
	ap->pages[0] = tmp_page;
	ap->descs[0].offset = 0;
	ap->descs[0].length = PAGE_SIZE;
	ap->args.end = fuse_writepage_end;
	wpa->inode = inode;

	inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK);
	inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP);

	spin_lock(&fi->lock);
	tree_insert(&fi->writepages, wpa);
	list_add_tail(&wpa->queue_entry, &fi->queued_writes);
	fuse_flush_writepages(inode);
	spin_unlock(&fi->lock);

	end_page_writeback(page);
---

fuse_writepages()
---
	err = write_cache_pages(mapping, wbc, fuse_writepages_fill, &data);
	if (data.wpa) {
		WARN_ON(!data.wpa->ia.ap.num_pages);
		fuse_writepages_send(&data);
	}
---

fuse_writepages_send()
---
	spin_lock(&fi->lock);
	list_add_tail(&wpa->queue_entry, &fi->queued_writes);
	fuse_flush_writepages(inode);
	spin_unlock(&fi->lock);

	for (i = 0; i < num_pages; i++)
		end_page_writeback(data->orig_pages[i]);
---

fuse_flush_writepages()
  -> fuse_send_writepage()
	-> fuse_simple_background()
	  -> fuse_request_queue_background()
	     ---
			if (likely(fc->connected)) {
				fc->num_background++;
				if (fc->num_background == fc->max_background)
					fc->blocked = 1;
				if (fc->num_background == fc->congestion_threshold && fm->sb) {
					set_bdi_congested(fm->sb->s_bdi, BLK_RW_SYNC);
					set_bdi_congested(fm->sb->s_bdi, BLK_RW_ASYNC);
				}
				list_add_tail(&req->list, &fc->bg_queue);
				flush_bg_queue(fc);
				queued = true;
			}
		 ---

fuse_send_writepage()
---
	fi->writectr++;
---

fuse_writepage_end()
---
	fi->writectr--;
	fuse_writepage_finish(fm, wpa);
	---
		for (i = 0; i < ap->num_pages; i++) {
			dec_wb_stat(&bdi->wb, WB_WRITEBACK);
			dec_node_page_state(ap->pages[i], NR_WRITEBACK_TEMP);
			wb_writeout_inc(&bdi->wb);
		}
		wake_up(&fi->page_waitq);
	---
---

fuse_fsync()
  -> file_write_and_wait_range()
  -> fuse_sync_writes(inode)
	-> fuse_set_nowrite()
	   ---
		spin_lock(&fi->lock);
		BUG_ON(fi->writectr < 0);
		fi->writectr += FUSE_NOWRITE;
		spin_unlock(&fi->lock);
		wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
	   ---
---

write page中最大的不同在于:fuse申请了一个tmp_page,然后使用这个tmp_page去承载数据,并发给对端;发出去之后,立刻就调用了end_page_writeback(),此时page cache中的数据还没有真正落盘;数据落盘的语义最终是通过fsync保证的。这样就避免了用户态fuse daemon故障导致系统dirty pages无人处理。

对与这个设计,fuse的commit的comment中做了解释:

    Fuse page writeback design
    --------------------------
    
    fuse_writepage() allocates a new temporary page with GFP_NOFS|__GFP_HIGHMEM.
    It copies the contents of the original page, and queues a WRITE request to the
    userspace filesystem using this temp page.
    
    The writeback is finished instantly from the MM's point of view: the page is
    removed from the radix trees, and the PageDirty and PageWriteback flags are
    cleared.
    
    For the duration of the actual write, the NR_WRITEBACK_TEMP counter is
    incremented.  The per-bdi writeback count is not decremented until the actual
    write completes.
    
    On dirtying the page, fuse waits for a previous write to finish before
    proceeding.  This makes sure, there can only be one temporary page used at a
    time for one cached page.
    
    This approach is wasteful in both memory and CPU bandwidth, so why is this
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    complication needed?
    
    The basic problem is that there can be no guarantee about the time in which
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    the userspace filesystem will complete a write.  It may be buggy or even
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    malicious, and fail to complete WRITE requests.  We don't want unrelated parts
    of the system to grind to a halt in such cases.
    
    Also a filesystem may need additional resources (particularly memory) to
    complete a WRITE request.  There's a great danger of a deadlock if that
    allocation may wait for the writepage to finish.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1077272.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 编程基础概念

目录 1 Python程序的构成1.1 使用\行连接符 2 对象3 引用4 标识符4.1 Python标识符命名规则 5 变量和简单赋值语句5.1 变量的声明和赋值5.2 删除变量和垃圾回收机制5.3 链式赋值5.4 系列解包赋值5.5 常量 6 最基本内置数据类型和运算符6.1 基本运算符6.2 整数6.3 浮点数6.4 类型…

华为数通方向HCIP-DataCom H12-831题库(多选题:241-259)

第241题 设备产生的信息可以向多个方向输出信息,为了便于各个方向信息的输出控制,信息中心定义了10条信息通道,使通道之间独立输出,缺省情况下,以下哪些通道对应的输出方向可以接收Trap信息? A、console通道 B、logbuffer通道 C、snmpagent通道 D、trapbuffer通道 答案:…

山西电力市场日前价格预测【2023-10-11】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-10-11&#xff09;山西电力市场全天平均日前电价为507.37元/MWh。其中&#xff0c;最高日前电价为873.70元/MWh&#xff0c;预计出现在18: 45。最低日前电价为313.23元/MWh&#xff0c;预计…

互联网从业者如何调节压力

互联网从业者面临着多种压力源&#xff0c;如工作性质、竞争、项目失败、对失败的恐惧等&#xff0c;这些压力会影响身心健康以及工作效率。因此&#xff0c;采取有效的压力调节方法是必要的&#xff0c;接下来我们从三个方向探讨下互联网从业者有关压力来源、应对压力的方法及…

leetcode每日一练-第977题-有序数组的平方

一、思路 双指针 二、 解题方法 i指向起始位置&#xff0c;j指向终止位置。 定义一个新数组result&#xff0c;和A数组一样的大小&#xff0c;让k指向result数组终止位置。 如果A[i] * A[i] < A[j] * A[j] 那么result[k--] A[j] * A[j]; 。 如果A[i] * A[i] > A[j…

Echarts使用感受

目录 数据处理 遇到的问题 更换echart主题 Y轴数字后添加百分比号 eCharts饼图显示百分比 echarts自定义主题的手把手教学 查看UI图 点击下方链接页面的定制主题按钮 点击下载主题 点击主题下载的JSON版本&#xff0c;点击复制 ​编辑 新建js文件&#xff0c;把复制的…

【Java】什么是API

API (Application Programming Interface,应用程序编程接口) Java中的API 指的就是 JDK 中提供的各种功能的 Java类&#xff0c;这些类将底层封装起来&#xff0c;我们不需要关心这些类是如何实现的&#xff0c;只需要学习这些类如何使用即可&#xff0c;我们可以通过帮助文档…

二、监控搭建-Prometheus-采集端部署

二、监控搭建-Prometheus-采集端部署 1、背景2、目标3、传承4、操作 1、背景 在上一篇中我们搭建了Prometheus平台&#xff0c;平台的搭建跟Linux系统上面安装了vim软件一样&#xff0c;给的只是一个很好的铸剑玄铁&#xff0c;具体的使用需要打磨和配件的运用。 2、目标 使…

XGBoost 2.0:对基于树的方法进行了重大更新

XGBoost是处理不同类型表格数据的最著名的算法&#xff0c;LightGBM 和Catboost也是为了修改他的缺陷而发布的。9月12日XGBoost发布了新的2.0版&#xff0c;本文除了介绍让XGBoost的完整历史以外&#xff0c;还将介绍新机制和更新。 这是一篇很长的文章&#xff0c;因为我们首…

转守为攻,亚马逊云换帅背后的战略转向

点击关注 文&#xff5c;刘雨琦 一则人事任命&#xff0c;揭开了亚马逊云在大中华区反击战的序幕。 10月9日&#xff0c;亚马逊云科技全球销售、市场和服务高级副总裁 Matt Garman 宣布了大中华区领导人变更任命&#xff0c;储瑞松将接替张文翊担任该职位&#xff0c;继续带领…

2023年网络安全岗位有哪些?金九银十别错过秋招!

网络安全有哪些岗位&#xff1f; 1. 安全服务工程师 7-10k 网络安全工程师、安全项目经理&#xff1a;主要负责甲方设备安全调试工作。需精通服务器、网络技术以及安全设备原理与配置。 2. 安全运维工程师 7-10k 安全运维工程师&#xff0c;主要对己方安全防御体系的运维和应急…

如何在 Spring Boot 中提高应用程序的安全性

如何在 Spring Boot 中提高应用程序的安全性 Spring Boot是一种流行的Java开发框架&#xff0c;用于构建Web应用程序和微服务。在构建应用程序时&#xff0c;安全性是至关重要的因素。不论您的应用程序是面向公众用户还是企业内部使用&#xff0c;都需要采取适当的措施来确保数…

(java)(python)以代理IP的方式进行请求数据

文章目录 前言(java)(python)以代理IP的方式进行请求数据1. python2. java 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话…

洛谷100题DAY7

31.P1636 Einstein学画画 此题为欧拉通路&#xff0c;必须要满足奇点的个数为0或2个 奇点&#xff1a;度数&#xff08;入度出度&#xff09;为奇数的点 如果奇点为2个或者0个就可以直接一笔化成 eg. 我们发现奇数点个数每增加2个就多一笔 #include<bits/stdc.h> us…

数据结构和算法(11):红黑树

概述 伸展树实现简便、无需修改节点结构、分摊复杂度低&#xff0c;但可惜最坏情况下的单次操作需要O(n)时间。 AVL树尽管可以保证最坏情况下的单次操作速度&#xff0c;但需在节点中嵌入平衡因子等标识&#xff1b;更重要的是&#xff0c;删除操作之后的重平衡可能需做多达O(…

【DRAM存储器十三】DDR介绍-功能框图和模式寄存器解析

&#x1f449;个人主页&#xff1a;highman110 &#x1f449;作者简介&#xff1a;一名硬件工程师&#xff0c;持续学习&#xff0c;不断记录&#xff0c;保持思考&#xff0c;输出干货内容 参考资料&#xff1a;《镁光DDR数据手册》 目录 DDR SDRAM芯片引脚 DDR SDRAM芯片框…

校园跑腿小程序还受欢迎不?

校园跑腿小程序是如今大学生群体中越来越受欢迎的一种服务模式。它为大学生提供了一个便捷的平台&#xff0c;使他们能够在校园内完成各类生活事务&#xff0c;如购买食品、快递取送、打印复印等。这种形式的服务在过去几年里在全球范围内迅速发展&#xff0c;并取得了巨大的成…

大学专业分类及介绍 专业有哪些

大学的专业非常多样化&#xff0c;涵盖了哲学、经济学、法学、教育学、文学、历史学、理学、工学、农学、医学、管理学、艺术学等12个学科门类。每个学科门类下又设有多个具体专业。 哲学类下设专业有4个&#xff0c;包括哲学、逻辑学、宗教学、伦理学。 经济学类下设专业有17…

外汇天眼:CONSOB下令封禁5个非法金融服务网站 总数达945个!

负责监管意大利金融市场的监管机构意大利公司和交易委员会The Commissione Nazionale per le Societ e la Borsa &#xff08;CONSOB&#xff09;10月6日发布禁令&#xff0c;命令意大利互联网服务提供商&#xff08;ISP&#xff09;关闭5个在意大利境内提供非法金融服务的网站…

【Codeforces】Educational Codeforces Round 156 [Rated for Div. 2]

hh第一次记录cf。 复盘 ab题目比较清晰&#xff0c;只开了这两题&#xff0c;后面看了下cd&#xff0c;即使开了翻译也看不懂题目是什么意思&#xff0c;最后放弃睡觉了。。 a是一道思维题&#xff0c;翻了下别人写的发现大家写的各不相同hh b是一道数学题&#xff0c;过程有点…