ext2文件系统源代码之xattr.c

本文详细剖析了ext2文件系统中处理扩展属性(xattr)的关键源代码文件xattr.c,涵盖了宏定义、函数声明及主要功能,如设置、获取、缓存和删除扩展属性等操作。通过对代码的分析,揭示了ext2_xattr_handler_map和ext2_xattr_handlers映射关系,以及ext2_xattr_get和ext2_xattr_list等核心函数的工作原理。
摘要由CSDN通过智能技术生成
今天我们来看ext2的扩展属性的主要文件xattr.c,内部有扩展属性的最重要的代码实现,但是文件也真的很长,我们来开始吧。
/* 作者版权信息
 * linux/fs/ext2/xattr.c
 *
 * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
 * 被Harrison Xing修改过
 * Fix by Harrison Xing <harrison@mountainviewdata.com>.
 * Extended attributes for symlinks and special files added per
 *  suggestion of Luka Renko <luka.renko@hermes.si>.
 * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
 *  Red Hat Inc.
 *
 */


#include <linux/buffer_head.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mbcache.h>
#include <linux/quotaops.h>
#include <linux/rwsem.h>
#include "ext2.h"
#include "xattr.h"
#include "acl.h"
/*宏定义,参数是buffer_head就诶勾踢指针,得到ext2_xattr_header类型的指针,指向buffer的头部*/
#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
/*将指针转化为ext2_xattr_entry类型的*/
#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
/*获得buffer的第一个项指针*/
#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
/*判断当前的项是不是最后一个*/
#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)


/*调试信息*/
#ifdef EXT2_XATTR_DEBUG
# define ea_idebug(inode, f...) do { \
		printk(KERN_DEBUG "inode %s:%ld: ", \
			inode->i_sb->s_id, inode->i_ino); \
		printk(f); \
		printk("\n"); \
	} while (0)
# define ea_bdebug(bh, f...) do { \
		char b[BDEVNAME_SIZE]; \
		printk(KERN_DEBUG "block %s:%lu: ", \
			bdevname(bh->b_bdev, b), \
			(unsigned long) bh->b_blocknr); \
		printk(f); \
		printk("\n"); \
	} while (0)
#else
# define ea_idebug(f...)
# define ea_bdebug(f...)
#endif
/*一些用到的函数声明*/
static int ext2_xattr_set2(struct inode *, struct buffer_head *,
			   struct ext2_xattr_header *);


static int ext2_xattr_cache_insert(struct buffer_head *);
static struct buffer_head *ext2_xattr_cache_find(struct inode *,
						 struct ext2_xattr_header *);
static void ext2_xattr_rehash(struct ext2_xattr_header *,
			      struct ext2_xattr_entry *);
/*系统存储的属性缓存*/
static struct mb_cache *ext2_xattr_cache;
/*属性的名称和处理函数的映射*/
static struct xattr_handler *ext2_xattr_handler_map[] = {
	[EXT2_XATTR_INDEX_USER]		     = &ext2_xattr_user_handler,
#ifdef CONFIG_EXT2_FS_POSIX_ACL
	[EXT2_XATTR_INDEX_POSIX_ACL_ACCESS]  = &ext2_xattr_acl_access_handler,
	[EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext2_xattr_acl_default_handler,
#endif
	[EXT2_XATTR_INDEX_TRUSTED]	     = &ext2_xattr_trusted_handler,
#ifdef CONFIG_EXT2_FS_SECURITY
	[EXT2_XATTR_INDEX_SECURITY]	     = &ext2_xattr_security_handler,
#endif
};
/*扩展属性的集合*/
struct xattr_handler *ext2_xattr_handlers[] = {
	&ext2_xattr_user_handler,
	&ext2_xattr_trusted_handler,
#ifdef CONFIG_EXT2_FS_POSIX_ACL
	&ext2_xattr_acl_access_handler,
	&ext2_xattr_acl_default_handler,
#endif
#ifdef CONFIG_EXT2_FS_SECURITY
	&ext2_xattr_security_handler,
#endif
	NULL
};
/*由扩展属性在数组里的下表,获得对应的处理函数结构体,参数name_index就是下表*/
static inline struct xattr_handler *
ext2_xattr_handler(int name_index)
{
	struct xattr_handler *handler = NULL;
	/*如果参数合法,返回对应的结构体*/
	if (name_index > 0 && name_index < ARRAY_SIZE(ext2_xattr_handler_map))
		/*上边刚说过的结构体*/
		handler = ext2_xattr_handler_map[name_index];
	return handler;
}


/*ext2_xattr_get()函数,复制一个扩展属性结构体到一个给定的buffer里,或者是计算需要的buffer大小,参数buffer如果是NULL的话,就计算需要的buffer大小,当失败的时候返回负的错误编号,成功时候返回消耗的字节数目*/
int
ext2_xattr_get(struct inode *inode, int name_index, const char *name,
	       void *buffer, size_t buffer_size)
{
	struct buffer_head *bh = NULL;
	struct ext2_xattr_entry *entry;
	size_t name_len, size;
	char *end;
	int error;
	/*调试信息,不管了*/
	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
		  name_index, name, buffer, (long)buffer_size);
	/*如果要求的属性名称为NULL,说明传入参数有问题*/
	if (name == NULL)
		return -EINVAL;
	/*读i_file_acl之前必须上锁*/
	down_read(&EXT2_I(inode)->xattr_sem);
	error = -ENODATA;
	/*i_file_acl指向属性的文件块号,如果为空,直接返回*/
	if (!EXT2_I(inode)->i_file_acl)
		goto cleanup;
	ea_idebug(inode, "reading block %d", EXT2_I(inode)->i_file_acl);
	/*读取这个块进入内存*/
	bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
	error = -EIO;
	if (!bh)
		goto cleanup;
	ea_bdebug(bh, "b_count=%d, refcount=%d",
		atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
	/*end指向buffer的末尾*/
	end = bh->b_data + bh->b_size;
	/*检查读取的缓冲区,看看这个块是不是坏块*/
	if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
	    HDR(bh)->h_blocks != cpu_to_le32(1)) {
	    /*如果是坏块,报错并返回IO错误*/
bad_block:	ext2_error(inode->i_sb, "ext2_xattr_get",
			"inode %ld: bad block %d", inode->i_ino,
			EXT2_I(inode)->i_file_acl);
		error = -EIO;
		goto cleanup;
	}
	/* 根据属性的名字寻找这个属性 */
	/*先获得属性名字长度*/
	name_len = strlen(name);


	error = -ERANGE;
	/*最大名字长度是255*/
	if (name_len > 255)
		goto cleanup;
	/*获得属性的第一项*/
	entry = FIRST_ENTRY(bh);
	/*遍历属性的每一项*/
	while (!IS_LAST_ENTRY(entry)) {
		struct ext2_xattr_entry *next =
			EXT2_XATTR_NEXT(entry);
		/*检验当前项是不是合法*/
		if ((char *)next >= end)
			goto bad_block;
		/*匹配,是不是我们想要的*/
		if (name_index == entry->e_name_index &&
		    name_len == entry->e_name_len &&
		    memcmp(name, entry->e_name, name_len) == 0)
			goto found;
		entry = next;
	}
	/* 检查余下的项,看看有没有坏的 */
	while (!IS_LAST_ENTRY(entry)) {
		struct ext2_xattr_entry *next =
			EXT2_XATTR_NEXT(entry);
		if ((char *)next >= end)
			goto bad_block;
		entry = next;
	}
	/*创建一个新的扩展属性项,并且插入它*/
	if (ext2_xattr_cache_insert(bh))
		ea_idebug(
由于Linux内核ext4文件系统实现非常复杂,涉及的源代码也非常庞大,因此无法在此进行逐行注释。以下是一些重要的源代码文件和函数,以及它们的作用和功能: 1. fs/ext4/super.c:定义了ext4文件系统的超级块结构体和相关函数,用于管理文件系统的元数据和数据结构。 2. fs/ext4/inode.c:定义了ext4文件系统的inode结构体和相关函数,用于管理文件和目录的元数据信息。 3. fs/ext4/dir.c:定义了ext4文件系统的目录结构体和相关函数,用于管理目录的元数据信息和目录项。 4. fs/ext4/namei.c:定义了ext4文件系统的名称解析函数,用于将路径名转换为inode结构体。 5. fs/ext4/file.c:定义了ext4文件系统的文件操作函数,用于读写文件和管理文件的元数据信息。 6. fs/ext4/extents.c:定义了ext4文件系统的扩展块结构体和相关函数,用于管理大文件的数据块。 7. fs/ext4/mballoc.c:定义了ext4文件系统的块分配函数,用于管理文件系统的空闲块和块位图。 8. fs/ext4/balloc.c:定义了ext4文件系统的数据块分配函数,用于管理文件系统的数据块和块位图。 9. fs/ext4/page-io.c:定义了ext4文件系统的页缓存管理函数,用于管理文件系统的数据缓存。 10. fs/ext4/xattr.c:定义了ext4文件系统的扩展属性结构体和相关函数,用于管理文件和目录的扩展属性。 这些源代码文件和函数涵盖了ext4文件系统的主要功能和特性,对于深入了解和掌握ext4文件系统的实现原理和操作方法非常有帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值