f2fs系列文章truncate

本文详细介绍了f2fs文件系统中truncate函数的工作流程,包括f2fs_truncate、truncate_blocks、truncate_inline_inode等核心步骤,涉及内联数据处理、dnode和indnode的截断与清理,以及元数据的更新等关键环节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    这篇文章讲f2fs文件系统的截断,在调用这个函数之前会设置inode的i_size,这个函数完成在文件中i_size之后的数据的删除。其起始的函数是f2fs_truncate。

    f2fs_truncate:检查inode的mode,如果不是REG或者是目录或者是LNK,那么直接返回。然后再调用f2fs_may_inline_data检查文件是否可以以内联的形式存放,如果不行,调用f2fs_convert_inline_inode来将内联的数据转换成正常索引的形式(目前还不知道这个地方有什么用)。接着调用truncate_blocks来进行真正的截断。最后修改inode的修改时间i_mtime,然后将inode设置为dirty。

int f2fs_truncate(struct inode *inode)
{
	int err;

	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
		return 0;

	trace_f2fs_truncate(inode);

	if (!f2fs_may_inline_data(inode)) {
		err = f2fs_convert_inline_inode(inode);
		if (err)
			return err;
	}

	err = truncate_blocks(inode, i_size_read(inode), true);
	if (err)
		return err;

	inode->i_mtime = inode->i_ctime = current_time(inode);
	f2fs_mark_inode_dirty_sync(inode);
	return 0;
}

    truncate_blocks:完成真正的所有的截断。首先计算截断位置下一个block的块索引free_from,然后调用get_node_page读取inode对应的f2fs_inode。f2fs_has_inline_data检查是否存放的是内联数据,如果是就调用truncate_inline对内联数据进行truncate操作,然后马上将修改后的f2fs_inode进行set_dirty操作。如果没有内联数据就按照正常索引的形式进行截断:首先通过set_new_dnode和get_dnode_of_data来获取free_from所在的dnode,通过计算得到dnode中大于等于free_from的块地址的个数count。如果dnode中的ofs或者是当前的dnode是f2fs_inode,那么就调用函数truncate_data_blocks_range把当前dnode(这里拥有923个块地址的f2fs_inode姑且也算一个dnode)中索引大于等于free_from的块地址全部删除,上述操作是为了删除部分的块地址来消除dnode中的零头,后面的删除可以以dnode为单位进行删除了。接下来的截断就由truncate_inode_blcoks来完成剩余的block的删除,最后调用truncate_partial_data_page对from所在的block中剩余的部分进行块内的截断。

int truncate_blocks(struct inode *inode, u64 from, bool lock)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	unsigned int blocksize = inode->i_sb->s_blocksize;
	struct dnode_of_data dn;
	pgoff_t free_from;
	int count = 0, err = 0;
	struct page *ipage;
	bool truncate_page = false;

	trace_f2fs_truncate_blocks_enter(inode, from);

	free_from = (pgoff_t)F2FS_BYTES_TO_BLK(from + blocksize - 1);
	if (free_from >= sbi->max_file_blocks)
		goto free_partial;
	if (lock)
		f2fs_lock_op(sbi);
	ipage = get_node_page(sbi, inode->i_ino);
	if (IS_ERR(ipage)) {
		err = PTR_ERR(ipage);
		goto out;
	}

	if (f2fs_has_inline_data(inode)) {
		if (truncate_inline_inode(ipage, from))
			set_page_dirty(ipage);
		f2fs_put_page(ipage, 1);
		truncate_page = true;
		goto out;
	}

	set_new_dnode(&dn, inode, ipage, NULL, 0);
	err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE_RA);
	if (err) {
		if (err == -ENOENT)
			goto free_next;
		goto out;
	}
	count = ADDRS_PER_PAGE(dn.node_page, inode);
	count -= dn.ofs_in_node;
	f2fs_bug_on(sbi, count < 0);
	if (dn.ofs_in_node || IS_INODE(dn.node_page)) {
		truncate_data_blocks_range(&dn, count);
		free_from += count;
	}
	
	f2fs_put_dnode(&dn);
free_next:
	err = truncate_inode_blocks(inode, free_from);
out:
	if (lock)
		f2fs_unlock_op(sbi);
free_partial:
	if (!err)
		err = truncate_partial_data_page(inode, from, truncate_page);

	trace_f2fs_truncate_blocks_exit(inode, err);
	return err;
}

    truncate_inline_inode首先检查截断的位置f

<think>好的,用户遇到了F2FS文件系统调整大小失败的问题,可能和lseek错误有关。我需要先理解用户的问题场景。用户可能在尝试调整F2FS格式的磁盘映像时遇到了错误,可能与lseek系统调用有关。lseek通常用于移动文件指针的位置,可能在调整大小时用于定位元数据或数据区域。 首先,我得回忆F2FS文件系统的结构以及调整大小的机制。F2FS(Flash-Friendly File System)是为闪存设计的文件系统,其调整大小可能涉及元数据更新和数据块的重新分配。resize.f2fs工具用于调整映像大小,但用户遇到了失败的情况,可能与lseek错误相关。 接下来,我需要考虑lseek可能出错的原因。lseek可能会在文件定位时返回错误,比如文件描述符无效、偏移量超出范围,或者文件系统处于只读模式。根据用户提供的引用,之前有类似问题是因为文件系统挂载为只读导致调整失败,需要重新挂载为读写模式。例如,引用[3]和[4]提到,无法调整只读文件系统的大小,需要remount为rw。这可能同样适用于F2FS的情况。 另外,用户提到的引用[1]提到resize.f2fs工具在保留数据的情况下调整映像大小,如果工具本身在执行过程中调用lseek时出错,可能是映像文件本身存在问题,例如损坏或者权限问题。需要检查映像是否可写,是否有足够的空间,或者是否存在文件系统错误。 可能的解决步骤包括: 1. 检查文件系统是否挂载为只读,并重新挂载为读写模式。 2. 使用fsck.f2fs检查并修复文件系统错误。 3. 确保调整大小工具的参数正确,特别是偏移量和大小参数。 4. 检查存储设备的空间是否足够,避免lseek超出设备限制。 5. 更新工具或内核模块到最新版本,以修复可能的已知问题。 同时,需要确认用户的具体操作步骤,比如是否在调整大小前正确卸载文件系统,或者是否使用了正确的命令参数。如果用户是在挂载状态下调整,需要先卸载,或者使用在线调整的方法(如果支持)。 此外,lseek错误可能涉及到文件系统的元数据区域损坏,导致工具无法正确访问所需的位置。这时,修复文件系统或使用备份恢复可能是必要的。 总结可能的解决方案后,需要将这些步骤结构化,并引用相关的资料,如用户提供的引用中的解决方法,例如重新挂载为读写模式,检查文件系统错误等。同时,生成相关问题来帮助用户进一步排查问题,比如工具版本、参数是否正确、存储设备状态等。</think>### F2FS文件系统调整大小失败与lseek错误的解决方案 #### 1. 检查文件系统挂载模式 F2FS文件系统调整大小前需确保处于**可读写状态**。若系统报错`read-only file system`,需重新挂载: ```bash sudo mount -o remount,rw /dev/[设备名] [挂载点] ``` 例如挂载点为根目录时: ```bash sudo mount -o remount,rw / ``` 该操作可解除只读限制,参考类似EXT4文件系统的解决方法[^3][^4]。 #### 2. 验证文件系统完整性 使用`fsck.f2fs`检查并修复文件系统错误: ```bash sudo fsck.f2fs -f /dev/[设备名] ``` 若发现元数据损坏或索引错误,工具会自动修复或提示手动干预。 #### 3. 检查存储设备空间 - **映像文件调整**:使用`resize.f2fs`时需确保目标设备/文件有**足够的剩余空间**。例如扩展磁盘映像前,需通过`truncate`或`dd`增加文件大小: ```bash truncate -s +10G image.f2fs ``` - **物理设备调整**:通过`fdisk`或`parted`确认分区已正确扩展到物理存储空间末尾[^2]。 #### 4. 排查lseek相关错误 若错误明确提示`lseek`失败,可能涉及以下原因: - **文件描述符无效**:确认调整工具以正确权限访问设备文件(如使用`sudo`)。 - **偏移量越界**:检查调整目标大小是否超出设备/文件的实际容量限制。 - **内核兼容性问题**:更新F2FS工具和内核模块至最新版本: ```bash sudo apt update && sudo apt install f2fs-tools linux-image-generic ``` #### 5. 操作示例 完整调整流程如下: ```bash # 卸载目标设备 sudo umount /dev/sdb1 # 扩展物理分区大小(假设已通过LVM或分区工具完成) sudo fdisk /dev/sdb # 修复文件系统并调整大小 sudo fsck.f2fs -f /dev/sdb1 sudo resize.f2fs /dev/sdb1 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值