首先来看ext2 inode结构:
引用:/*
* second extended file system inode data in memory
*/
struct ext2_inode_info {
__le32 i_data[15];
__u32 i_flags;
__u32 i_faddr;
__u8 i_frag_no;
__u8 i_frag_size;
__u16 i_state;
__u32 i_file_acl;
__u32 i_dir_acl;
__u32 i_dtime;
__u32 i_block_group;
__u32 i_next_alloc_block;
__u32 i_next_alloc_goal;
__u32 i_prealloc_block;
__u32 i_prealloc_count;
__u32 i_dir_start_lookup;
#ifdef CONFIG_EXT2_FS_XATTR
struct rw_semaphore xattr_sem;
#endif
#ifdef CONFIG_EXT2_FS_POSIX_ACL
struct posix_acl *i_acl;
struct posix_acl *i_default_acl;
#endif
rwlock_t i_meta_lock;
struct inode vfs_inode;
};
这里的i_file_acl指向inode对应的extended attribute(以下简写为EA),而EA本身所在的block是没有inode与之对应的。
至于EA在block里的保存方式,首先在block里保存一个header,
引用:struct ext2_xattr_header {
__le32 h_magic; /* magic number for identification */
__le32 h_refcount; /* reference count */
__le32 h_blocks; /* number of disk blocks used */
__le32 h_hash; /* hash value of all attributes */
__u32 h_reserved[4]; /* zero right now */
};
h_magic是EXT2_XATTR_MAGIC的magic number。
h_refcount是此EA的reference count。如果多个inode有相同的EA,则都指向此block,以节约磁盘空间。h_refcount的最大值是EXT2_XATTR_REFCOUNT_MAX。
h_blocks是此EA用了多少块block。
h_hash是整个EA的hash值,用于判断两个EA是否相等。(相等的话就reference同一个EA,上述h_refcount加一)
h_reserved目前还没用到。
header之后就是一个又一个的entry
引用:struct ext2_xattr_entry {
__u8 e_name_len; /* length of name */
__u8 e_name_index; /* attribute name index */
__le16 e_value_offs; /* offset in disk block of value */
__le32 e_value_block; /* disk block attribute is stored on (n/i) */
__le32 e_value_size; /* size of attribute value */
__le32 e_hash; /* hash value of name and value */
char e_name[0]; /* attribute name */
};
以上,header在block头,entry们紧随其后向下增长,并且entry们是以attribute name排序的,这样便于比较。当然这样插入entry的复杂度就增加了。
而entry指向的value则是在block底部,向上增长。value没有特别的存放顺序,在entry结构里指好了的,直接seek过去就能用。但这样就有新的问题:删除一个value之后,回收其空间需要遍历所有entry以确定其空间是空闲的。这里ext2具体如何实现,有待继续看源码。
先看到这里,接下来分析设置EA和修改EA的代码。