ext2_new_inode()函数详解

news2024/11/29 9:49:06

函数概览

  • 位置:fs/ext2/ialloc.c
  • 目标:在ext2 文件系统中为目录或普通文件分配新的 inode(从 inode 位图中查找空闲 inode并初始化相关结构)
  • 返回值:成功时返回新分配的 inode 结构指针;失败时返回一个错误指针。

函数源码

struct inode *ext2_new_inode(struct inode *dir, umode_t mode,
			     const struct qstr *qstr)
{
	struct super_block *sb;
	struct buffer_head *bitmap_bh = NULL;
	struct buffer_head *bh2;
	int group, i;
	ino_t ino = 0;
	struct inode * inode;
	struct ext2_group_desc *gdp;
	struct ext2_super_block *es;
	struct ext2_inode_info *ei;
	struct ext2_sb_info *sbi;
	int err;

	sb = dir->i_sb;
	inode = new_inode(sb);
	if (!inode)
		return ERR_PTR(-ENOMEM);

	ei = EXT2_I(inode);
	sbi = EXT2_SB(sb);
	es = sbi->s_es;
	if (S_ISDIR(mode)) {
		if (test_opt(sb, OLDALLOC))
			group = find_group_dir(sb, dir);
		else
			group = find_group_orlov(sb, dir);
	} else 
		group = find_group_other(sb, dir);

	if (group == -1) {
		err = -ENOSPC;
		goto fail;
	}

	for (i = 0; i < sbi->s_groups_count; i++) {
		gdp = ext2_get_group_desc(sb, group, &bh2);
		if (!gdp) {
			if (++group == sbi->s_groups_count)
				group = 0;
			continue;
		}
		brelse(bitmap_bh);
		bitmap_bh = read_inode_bitmap(sb, group);
		if (!bitmap_bh) {
			err = -EIO;
			goto fail;
		}
		ino = 0;

repeat_in_this_group:
		ino = ext2_find_next_zero_bit((unsigned long *)bitmap_bh->b_data,
					      EXT2_INODES_PER_GROUP(sb), ino);
		if (ino >= EXT2_INODES_PER_GROUP(sb)) {
			/*
			 * Rare race: find_group_xx() decided that there were
			 * free inodes in this group, but by the time we tried
			 * to allocate one, they're all gone.  This can also
			 * occur because the counters which find_group_orlov()
			 * uses are approximate.  So just go and search the
			 * next block group.
			 */
			if (++group == sbi->s_groups_count)
				group = 0;
			continue;
		}
		if (ext2_set_bit_atomic(sb_bgl_lock(sbi, group),
						ino, bitmap_bh->b_data)) {
			/* we lost this inode */
			if (++ino >= EXT2_INODES_PER_GROUP(sb)) {
				/* this group is exhausted, try next group */
				if (++group == sbi->s_groups_count)
					group = 0;
				continue;
			}
			/* try to find free inode in the same group */
			goto repeat_in_this_group;
		}
		goto got;
	}

	/*
	 * Scanned all blockgroups.
	 */
	brelse(bitmap_bh);
	err = -ENOSPC;
	goto fail;
got:
	mark_buffer_dirty(bitmap_bh);
	if (sb->s_flags & SB_SYNCHRONOUS)
		sync_dirty_buffer(bitmap_bh);
	brelse(bitmap_bh);

	ino += group * EXT2_INODES_PER_GROUP(sb) + 1;
	if (ino < EXT2_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
		ext2_error (sb, "ext2_new_inode",
			    "reserved inode or inode > inodes count - "
			    "block_group = %d,inode=%lu", group,
			    (unsigned long) ino);
		err = -EIO;
		goto fail;
	}

	percpu_counter_dec(&sbi->s_freeinodes_counter);
	if (S_ISDIR(mode))
		percpu_counter_inc(&sbi->s_dirs_counter);

	spin_lock(sb_bgl_lock(sbi, group));
	le16_add_cpu(&gdp->bg_free_inodes_count, -1);
	if (S_ISDIR(mode)) {
		if (sbi->s_debts[group] < 255)
			sbi->s_debts[group]++;
		le16_add_cpu(&gdp->bg_used_dirs_count, 1);
	} else {
		if (sbi->s_debts[group])
			sbi->s_debts[group]--;
	}
	spin_unlock(sb_bgl_lock(sbi, group));

	mark_buffer_dirty(bh2);
	if (test_opt(sb, GRPID)) {
		inode->i_mode = mode;
		inode->i_uid = current_fsuid();
		inode->i_gid = dir->i_gid;
	} else
		inode_init_owner(&init_user_ns, inode, dir, mode);

	inode->i_ino = ino;
	inode->i_blocks = 0;
	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
	memset(ei->i_data, 0, sizeof(ei->i_data));
	ei->i_flags =
		ext2_mask_flags(mode, EXT2_I(dir)->i_flags & EXT2_FL_INHERITED);
	ei->i_faddr = 0;
	ei->i_frag_no = 0;
	ei->i_frag_size = 0;
	ei->i_file_acl = 0;
	ei->i_dir_acl = 0;
	ei->i_dtime = 0;
	ei->i_block_alloc_info = NULL;
	ei->i_block_group = group;
	ei->i_dir_start_lookup = 0;
	ei->i_state = EXT2_STATE_NEW;
	ext2_set_inode_flags(inode);
	spin_lock(&sbi->s_next_gen_lock);
	inode->i_generation = sbi->s_next_generation++;
	spin_unlock(&sbi->s_next_gen_lock);
	if (insert_inode_locked(inode) < 0) {
		ext2_error(sb, "ext2_new_inode",
			   "inode number already in use - inode=%lu",
			   (unsigned long) ino);
		err = -EIO;
		goto fail;
	}

	err = dquot_initialize(inode);
	if (err)
		goto fail_drop;

	err = dquot_alloc_inode(inode);
	if (err)
		goto fail_drop;

	err = ext2_init_acl(inode, dir);
	if (err)
		goto fail_free_drop;

	err = ext2_init_security(inode, dir, qstr);
	if (err)
		goto fail_free_drop;

	mark_inode_dirty(inode);
	ext2_debug("allocating inode %lu\n", inode->i_ino);
	ext2_preread_inode(inode);
	return inode;

fail_free_drop:
	dquot_free_inode(inode);

fail_drop:
	dquot_drop(inode);
	inode->i_flags |= S_NOQUOTA;
	clear_nlink(inode);
	discard_new_inode(inode);
	return ERR_PTR(err);

fail:
	make_bad_inode(inode);
	iput(inode);
	return ERR_PTR(err);
}

函数参数

  • struct inode *dir:
    指向目标目录的 inode,表示新 inode 将被分配到的目录。

  • umode_t mode:
    指定新 inode 的模式(文件类型和权限)。

  • const struct qstr *qstr:
    与目录条目相关的名字字符串,用于安全性初始化等。


主要变量

  • struct super_block *sb:
    当前文件系统的超级块指针。

  • struct buffer_head *bitmap_bh:
    指向 inode 位图的缓冲区头,用于跟踪 inode 分配。

  • struct ext2_group_desc *gdp:
    表示块组描述符,用于获取块组相关的元数据。

  • struct ext2_sb_info *sbi:
    扩展超级块信息,包含了文件系统的全局信息。

  • ino_t ino:
    新分配的 inode 号。


主要逻辑

1. 初始化 inode 结构

sb = dir->i_sb:
inode = new_inode(sb);
if (!inode)
    return ERR_PTR(-ENOMEM);
  • 获取超级块。
  • 调用 new_inode 分配新的 struct inode 结构。如果失败返回错误指针。

2. 选择目标块组

if (S_ISDIR(mode)) {
    if (test_opt(sb, OLDALLOC))
        group = find_group_dir(sb, dir);
    else
        group = find_group_orlov(sb, dir);
} else 
    group = find_group_other(sb, dir);
  • 如果是目录(S_ISDIR(mode) 为真),采用适当的块组选择策略。
    • 旧分配策略(OLDALLOC:选择离父目录最近的块组。
    • Orlov 策略:更复杂,基于空间利用率和性能。
  • 如果不是目录,调用 find_group_other

3. 从位图中分配 inode

bitmap_bh = read_inode_bitmap(sb, group);
ino = ext2_find_next_zero_bit(...);
if (ext2_set_bit_atomic(...)) {
    ...
    goto repeat_in_this_group;
}
  • 调用 read_inode_bitmap 读取目标块组的 inode 位图。
  • ext2_find_next_zero_bit 找到第一个未分配的 inode。
  • 使用 ext2_set_bit_atomic 设置位图中的 inode 为已分配,确保原子性。

如果当前块组的 inode 分配失败,继续搜索下一个块组。


4. 更新全局和块组计数器

percpu_counter_dec(&sbi->s_freeinodes_counter);
if (S_ISDIR(mode))
    percpu_counter_inc(&sbi->s_dirs_counter);

le16_add_cpu(&gdp->bg_free_inodes_count, -1);
if (S_ISDIR(mode))
    le16_add_cpu(&gdp->bg_used_dirs_count, 1);
  • 减少全局空闲 inode 计数器。
  • 如果是目录,增加目录计数器。
  • 更新目标块组的空闲 inode 计数器和目录计数器。

5. 初始化新 inode

inode->i_ino = ino;
inode->i_blocks = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
...
ext2_set_inode_flags(inode);
  • 设置 inode 编号、时间戳、数据块计数等。
  • 调用 ext2_set_inode_flags 设置 inode 的标志。

6. 挂载安全属性和配额

err = ext2_init_acl(inode, dir);
if (err)
    goto fail_free_drop;

err = ext2_init_security(inode, dir, qstr);
if (err)
    goto fail_free_drop;
  • 初始化访问控制列表(ACL)。
  • 初始化安全属性(如 SELinux 标签)。

7. 错误处理

fail_free_drop:
    dquot_free_inode(inode);

fail_drop:
    dquot_drop(inode);
    ...
fail:
    make_bad_inode(inode);
    iput(inode);
    return ERR_PTR(err);
  • 出现错误时,释放资源并标记 inode 为坏节点。

8. 成功返回

mark_inode_dirty(inode);
return inode;
  • 标记 inode 为脏(需要写回磁盘)。
  • 返回已初始化的 inode。

功能总结

ext2_new_inode 的主要任务是:

  1. 根据分配策略选择块组。
  2. 在 inode 位图中找到一个空闲 inode。
  3. 初始化 inode 结构和相关的文件系统元数据。
  4. 处理配额、ACL 和安全性。
  5. 返回新分配的 inode 或错误代码。

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

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

相关文章

C++入门——“C++11-lambda”

引入 C11支持lambda表达式&#xff0c;lambda是一个匿名函数对象&#xff0c;它允许在函数体中直接定义。 一、初识lambda lambda的结构是&#xff1a;[ ] () -> 返回值类型 { }。从左到右依次是&#xff1a;捕捉列表 函数参数 -> 返回值类型 函数体。 以下是一段用lam…

【Linux网络编程】第二弹---Socket编程入门指南:从IP、端口号到传输层协议及编程接口全解析

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【Linux网络编程】 目录 1、Socket 编程预备 1.1、理解源 IP 和目的 IP 1.2、认识端口号 1.2.1、端口号范围划分 1.2.2、理解 &q…

《用Python实现3D动态旋转爱心模型》

简介 如果二维的爱心图案已经无法满足你的创意&#xff0c;那今天的内容一定适合你&#xff01;通过Python和matplotlib库&#xff0c;我们可以实现一个动态旋转的3D爱心模型&#xff0c;充满立体感和动感。# 实现代码&#xff08;完整代码底部名片私信&#xff09; 以下是完…

shell-函数调用进阶即重定向

shell-函数调用进阶 声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷…

【高等数学学习记录】微分中值定理

一、知识点 &#xff08;一&#xff09;罗尔定理 费马引理 设函数 f ( x ) f(x) f(x) 在点 x 0 x_0 x0​ 的某邻域 U ( x 0 ) U(x_0) U(x0​) 内有定义&#xff0c;并且在 x 0 x_0 x0​ 处可导&#xff0c;如果对任意的 x ∈ U ( x 0 ) x\in U(x_0) x∈U(x0​) &#xff0…

【vue-router】vue-router如何实现动态路由

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Web前端技术浅谈CooKieAG网址漏洞与XSS攻防策略

随着互联网技术的飞速发展,Web前端开发已经成为构建网站和应用程序的重要环节。然而,Web前端开发中存在许多安全问题,这些问题不仅会影响用户体验,还可能给企业和个人带来严重的经济损失。但是web前端安全方面技术包含的东西较多&#xff0c;我们这里着重聊一聊关于XSS 的危害与…

关于VNC连接时自动断联的问题

在服务器端打开VNC Server的选项设置对话框&#xff0c;点左边的“Expert”&#xff08;专家&#xff09;&#xff0c;然后找到“IdleTimeout”&#xff0c;将数值设置为0&#xff0c;点OK关闭对话框。搞定。 注意,服务端有两个vnc服务,这俩都要设置ide timeout为0才行 附件是v…

51c自动驾驶~合集35

我自己的原文哦~ https://blog.51cto.com/whaosoft/12206500 #纯视觉方案的智驾在大雾天还能用吗&#xff1f; 碰上大雾天气&#xff0c;纯视觉方案是如何识别车辆和障碍物的呢&#xff1f; 如果真的是纯纯的&#xff0c;特头铁的那种纯视觉方案的话。 可以简单粗暴的理解为…

计算分数的浮点数值

计算分数的浮点数值 C语言代码C 代码Java代码Python代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 两个整数a和b分别作为分子和分母&#xff0c;既分数 a/b &#xff0c;求它的浮点数值&#xff08;双精度浮点数&#xff0c;保留小数点…

戴尔电脑安装centos7系统遇到的问题

1&#xff0c;找不到启动盘&#xff08;Operation System Loader signature found in SecureBoot exclusion database(‘dbx’).All bootable devices failed secure Boot Verification&#xff09; 关闭 Secure Boot&#xff08;推荐&#xff09;&#xff1a; 进入 BIOS/UEFI…

简单获取json预览

data: JSON 数据。 collapsedNodeLength: 对象或数组的长度超过此阈值时会折叠 deep: json路径深度超过此值时会折叠 showLineNumber: 显示左侧行号 showIcon: 显示图标。 virtual: 使用虚拟滚动 height: 使用虚拟滚动时列表的高度 itemHeight: 使用虚拟滚动时节点的高…

ChatGPT/AI辅助网络安全运营之-数据解压缩

在网络安全的世界中&#xff0c;经常会遇到各种压缩的数据&#xff0c;比如zip压缩&#xff0c;比如bzip2压缩&#xff0c;gzip压缩&#xff0c;xz压缩&#xff0c;7z压缩等。网络安全运营中需要对这些不同的压缩数据进行解压缩&#xff0c;解读其本意&#xff0c;本文将探索一…

Cookie概念和API

Cookie概念 Cookie在HTTP中它表示服务器送给客户端浏览器的小甜点。其实Cookie就是一个键和一个值构成的&#xff0c;随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来&#xff0c;当下一次再访问服务器时把Cookie再发送给服务器。 Cookie是由服务器…

qt音频实战

一、Qt音频基础知识 1、QT multimedia 2、QMediaPlayer类&#xff1a;媒体播放器&#xff0c;主要用于播放歌曲、网络收音机等功能。 3、QMediaPlaylist类&#xff1a;专用于播放媒体内容的列表。 二、界面设计 三、代码 #include "mainwindow.h" #include "…

GDPU Android移动应用 数据存储

又是学到了数据持久化。 登录界面 题外话&#xff1a;有无动画大佬带带呀&#xff0c;前端移动端可免( •̀ .̫ •́ )&#xff0c;合作可私信哦。 1.用户登陆和“记住我”功能 该内容拥有两个Activity活动视图&#xff1a; &#xff08;1&#xff09;LoginActivity&#x…

Java算法OJ(11)双指针练习

目录 1.前言 2.正文 2.1存在重复数字 2.1.1题目 2.1.2解法一代码 解析&#xff1a; 2.1.3解法二代码 解析&#xff1a; 2.2存在重复数字plus 2.2.1题目 2.2.2代码 2.2.3解析 3.小结 1.前言 哈喽大家好吖&#xff0c;今天来给大家分享双指针算法的相关练习&…

天锐绿盾加密软件与Ping32联合打造企业级安全保护系统,确保敏感数据防泄密与加密管理

随着信息技术的飞速发展&#xff0c;企业在日常经营过程中产生和处理的大量敏感数据&#xff0c;面临着越来越复杂的安全威胁。尤其是在金融、医疗、法律等领域&#xff0c;数据泄漏不仅会造成企业巨大的经济损失&#xff0c;还可能破坏企业的信誉和客户信任。因此&#xff0c;…

Git上传本地项目到远程仓库(gitee/github)

目录 序言一、创建git本地版本库二、连接远程仓库&#xff08;以gitee为例&#xff09;三、将项目提交到git&#xff08;本地&#xff09;版本库1.由工作区添加到暂存区2.由暂存区添加到版本库 四、将代码由本地仓库上传到 gitee远程仓库1.获取远程库与本地同步2.把当前分支 ma…

C7.【C++ Cont】范围for的使用和auto关键字

目录 1.知识回顾 2.范围for 格式 使用 运行结果 运行过程 范围for的本意 作用 注意 3.底层分析范围for的执行过程 反汇编代码 分析 4.auto关键字 格式 基本用法 在范围for中使用auto 1.知识回顾 for循环的使用参见25.【C语言】循环结构之for文章 2.范围for C…