Extended file attributes (EA) are extensions to the normal attributes which are associated with inodes in a file system. They are simply name:value pairs associated with files and directories and whose purpose is to provide additional functionality which is either defined by the operating system or a user application. An EA may be defined or undefined. If an EA is defined, its value may be empty or non-empty. Most of the initial work to support EAs in Linux was done by Andreas Gruenbacher in the 2001 to 2004 timeframe and is based on work done in the SGI XFS file system.
EAs are stored directly in inodes and on additional disk blocks if necessary. Currently all EAs associated with a file must fit in an inode and one additional block. Blocks that contain the identical set of EAs may be shared among several inodes. EAs in inodes and on blocks have a different header followed by multiple entry descriptors. Entry descriptors are sorted in disk blocks but are left unsorted in inodes.
EA names are zero-terminated strings and are always specified using a fully qualified namespace.attribute e.g. system.posix_acl_access or security.selinux. Namespaces are used to define different classes of EAs. Different EA classes are required because the permissions and capabilities required for manipulating EAs in one namespace may differ from one to another. Currently Linux supports EA namespaces for SELinux (security.), system (system.), trusted (trusted.) and user (user.).
Fedora 11 comes with EA support in the Linux kernel and hence it is the kernel which must be modified in order to add another EA namespace. In my case I wanted to add an EA namespace called snia in order to support XAM XSet metadata (see below).
Here is the patch file for the Fedora 11 2.6.29.4-167.fc11 kernel which implements the snia namespace. It should work for both 32-bit and 64-bit kernels but I have only tested it on a 64-bit kernel.
diff -uNrp kernel-2.6.29.orig/fs/ext4/Makefile kernel-2.6.29.new/fs/ext4/Makefile
--- kernel-2.6.29.orig/fs/ext4/Makefile 2009-06-14 22:07:12.191464615 -0400
+++ kernel-2.6.29.new/fs/ext4/Makefile 2009-06-14 22:06:20.009399924 -0400
@@ -8,6 +8,6 @@ ext4-y := balloc.o bitmap.o dir.o file.o
ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
ext4_jbd2.o migrate.o mballoc.o
-ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
+ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o xattr_snia.o
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o
diff -uNrp kernel-2.6.29.orig/fs/ext4/xattr.c kernel-2.6.29.new/fs/ext4/xattr.c
--- kernel-2.6.29.orig/fs/ext4/xattr.c 2009-06-14 22:11:20.699475221 -0400
+++ kernel-2.6.29.new/fs/ext4/xattr.c 2009-06-14 22:09:48.242839367 -0400
@@ -107,6 +107,7 @@ static struct xattr_handler *ext4_xattr_
#ifdef CONFIG_EXT4_FS_SECURITY
[EXT4_XATTR_INDEX_SECURITY] = &ext4_xattr_security_handler,
#endif
+ [EXT4_XATTR_INDEX_SNIA] = &ext4_xattr_snia_handler,
};
struct xattr_handler *ext4_xattr_handlers[] = {
@@ -119,6 +120,7 @@ struct xattr_handler *ext4_xattr_handler
#ifdef CONFIG_EXT4_FS_SECURITY
&ext4_xattr_security_handler,
#endif
+ &ext4_xattr_snia_handler,
NULL
};
diff -uNrp kernel-2.6.29.orig/fs/ext4/xattr.h kernel-2.6.29.new/fs/ext4/xattr.h
--- kernel-2.6.29.orig/fs/ext4/xattr.h 2009-06-14 22:09:27.016464602 -0400
+++ kernel-2.6.29.new/fs/ext4/xattr.h 2009-06-14 22:07:44.887839381 -0400
@@ -21,6 +21,7 @@
#define EXT4_XATTR_INDEX_TRUSTED 4
#define EXT4_XATTR_INDEX_LUSTRE 5
#define EXT4_XATTR_INDEX_SECURITY 6
+#define EXT4_XATTR_INDEX_SNIA 7
struct ext4_xattr_header {
__le32 h_magic; /* magic number for identification */
@@ -70,6 +71,7 @@ extern struct xattr_handler ext4_xattr_t
extern struct xattr_handler ext4_xattr_acl_access_handler;
extern struct xattr_handler ext4_xattr_acl_default_handler;
extern struct xattr_handler ext4_xattr_security_handler;
+extern struct xattr_handler ext4_xattr_snia_handler;
extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
diff -uNrp kernel-2.6.29.orig/fs/ext4/xattr_snia.c kernel-2.6.29.new/fs/ext4/xattr_snia.c
--- kernel-2.6.29.orig/fs/ext4/xattr_snia.c 1969-12-31 19:00:00.000000000 -0500
+++ kernel-2.6.29.new/fs/ext4/xattr_snia.c 2009-06-14 13:37:02.551476954 -0400
@@ -0,0 +1,68 @@
+/*
+ * linux/fs/ext4/xattr_snia.c
+ * Handler for extended user attributes.
+ *
+ * Copyright (C) 2001 by Andreas Gruenbacher,
+ * Copyright (C) 2009 by Finnbarr P. Murphy,
+ */
+
+#include
+#include
+#include
+#include "ext4_jbd2.h"
+#include "ext4.h"
+#include "xattr.h"
+
+static size_t
+ext4_xattr_snia_list(struct inode *inode, char *list, size_t list_size,
+ const char *name, size_t name_len)
+{
+ const size_t prefix_len = XATTR_SNIA_PREFIX_LEN;
+ const size_t total_len = prefix_len + name_len + 1;
+
+#if FPM
+ if (!test_opt(inode->i_sb, XATTR_USER))
+ return 0;
+#endif
+
+ if (list && total_len <= list_size) {
+ memcpy(list, XATTR_SNIA_PREFIX, prefix_len);
+ memcpy(list+prefix_len, name, name_len);
+ list[prefix_len + name_len] = '\0';
+ }
+ return total_len;
+}
+
+static int
+ext4_xattr_snia_get(struct inode *inode, const char *name,
+ void *buffer, size_t size)
+{
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+#if FPM
+ if (!test_opt(inode->i_sb, XATTR_USER))
+ return -EOPNOTSUPP;
+#endif
+ return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SNIA, name, buffer, size);
+}
+
+static int
+ext4_xattr_snia_set(struct inode *inode, const char *name,
+ const void *value, size_t size, int flags)
+{
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+#if FPM
+ if (!test_opt(inode->i_sb, XATTR_USER))
+ return -EOPNOTSUPP;
+#endif
+ return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SNIA, name,
+ value, size, flags);
+}
+
+struct xattr_handler ext4_xattr_snia_handler = {
+ .prefix = XATTR_SNIA_PREFIX,
+ .list = ext4_xattr_snia_list,
+ .get = ext4_xattr_snia_get,
+ .set = ext4_xattr_snia_set,
+};
diff -uNrp kernel-2.6.29.orig/fs/xattr.c kernel-2.6.29.new/fs/xattr.c
--- kernel-2.6.29.orig/fs/xattr.c 2009-06-14 22:04:37.472464234 -0400
+++ kernel-2.6.29.new/fs/xattr.c 2009-06-14 22:05:56.759530990 -0400
@@ -42,6 +42,7 @@ xattr_permission(struct inode *inode, co
* on these is left to the underlying filesystem / security module.
*/
if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
+ !strncmp(name, XATTR_SNIA_PREFIX, XATTR_SNIA_PREFIX_LEN) ||
!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
return 0;
diff -uNrp kernel-2.6.29.orig/include/linux/xattr.h kernel-2.6.29.new/include/linux/xattr.h
--- kernel-2.6.29.orig/include/linux/xattr.h 2009-06-14 14:53:02.350464255 -0400
+++ kernel-2.6.29.new/include/linux/xattr.h 2009-06-14 14:51:07.585839446 -0400
@@ -33,6 +33,9 @@
#define XATTR_USER_PREFIX "user."
#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
+#define XATTR_SNIA_PREFIX "snia."
+#define XATTR_SNIA_PREFIX_LEN (sizeof (XATTR_SNIA_PREFIX) - 1)
+
struct inode;
struct dentry;
Once you are running on the new kernel, you can set and get EAs in the snia namespace as shown in this simple example.
$ touch testfile
$ setfattr -n snia.test -v "hello world" testfile
$ getfattr -n snia.test testfile
# file: testfile
snia.test="hello world"
$
$ cat xamtest
# file: testfile
snia.xset.hold.type="application/vnd.snia.xam.boolean"
snia.xset.hold.binding="false"
snia.xset.hold.readOnly="true"
snia.xset.hold.length="1"
snia.xset.hold="0"
snia.xset.management.policy.type="application/vnd.snia.xam.string"
snia.xset.management.policy.binding="true"
snia.xset.management.policy.readOnly="true"
snia.xset.management.policy.length="36"
snia.xset.management.policy="org.snia.refvim.default.mgmt.policy"
snia.xset.retention.base.enabled.type="application/vnd.snia.xam.boolean"
snia.xset.retention.base.enabled.binding="true"
snia.xset.retention.base.enabled.readOnly="true"
snia.xset.retention.base.enabled.length="1"
snia.xset.retention.base="1"
snia.xset.retention.base.starttime.type="application/vnd.snia.xam.datetime"
snia.xset.retention.base.starttime.binding="true"
snia.xset.retention.base.starttime.readOnly="true"
snia.xset.retention.base.starttime.length="29"
snia.xset.retention.base.starttime="2009-06-12T22:34:35.350-05:00"
snia.xset.retention.list.base.type="application/vnd.snia.xam.string"
snia.xset.retention.list.base.binding="true"
snia.xset.retention.list.base.readOnly="true"
snia.xset.retention.list.base.length="4"
snia.xset.retention.list.base="base"
snia.xset.retention.list.event.type="application/vnd.snia.xam.string"
snia.xset.retention.list.event.binding="true"
snia.xset.retention.list.event.readOnly="true"
snia.xset.retention.list.event.length="5"
snia.xset.retention.list.event="event"
snia.xset.time.access.type="application/vnd.snia.xam.datetime"
snia.xset.time.access.binding="false"
snia.xset.time.access.readOnly="true"
snia.xset.time.access.length="29"
snia.xset.time.access="2009-06-12T22:34:35.350-05:00"
snia.xset.time.commit.type="application/vnd.snia.xam.datetime"
snia.xset.time.commit.binding="false"
snia.xset.time.commit.readOnly="true"
snia.xset.time.commit.length="29"
snia.xset.time.commit="2009-06-12T22:34:35.350-05:00"
snia.xset.time.access.type="application/vnd.snia.xam.datetime"
snia.xset.time.access.binding="false"
snia.xset.time.access.readOnly="true"
snia.xset.time.access.length="29"
snia.xset.time.access="2009-06-12T22:34:35.350-05:00"
snia.xset.time.commit.type="application/vnd.snia.xam.datetime"
snia.xset.time.commit.binding="false"
snia.xset.time.commit.readOnly="true"
snia.xset.time.commit.length="29"
snia.xset.time.commit="2009-06-12T22:34:35.350-05:00"
snia.xset.time.creation.type="application/vnd.snia.xam.datetime"
snia.xset.time.creation.binding="true"
snia.xset.time.creation.readOnly="true"
snia.xset.time.creation.length="29"
snia.xset.time.creation="2009-06-12T22:34:35.331-05:00"
snia.xset.time.xuid.type="application/vnd.snia.xam.datetime"
snia.xset.time.xuid.binding="false"
snia.xset.time.xuid.readOnly="true"
snia.xset.time.xuid.length="29"
snia.xset.time.xuid="2009-06-12T22:34:35.331-05:00"
snia.xset.xuid.type="application/vnd.snia.xam.xuid"
snia.xset.xuid.binding="true"
snia.xset.xuid.readOnly="true"
snia.xset.xuid.length="30"
snia.xset.xuid="AAA6AwAeVG4xMjQ0ODY0MDc1MzU4AQWDedILNL7Q"
$ setfattr --restore=xamtest
$ getfattr -m snia. -d testfile
# file: testfile
snia.test="hello world"
snia.xset.hold="0"
snia.xset.hold.binding="false"
snia.xset.hold.length="1"
snia.xset.hold.readOnly="true"
snia.xset.hold.type="\"application/vnd.snia.xam.boolean\" "
snia.xset.management.policy="org.snia.refvim.default.mgmt.policy"
snia.xset.management.policy.binding="true"
snia.xset.management.policy.length="36"
snia.xset.management.policy.readOnly="true"
snia.xset.management.policy.type="application/vnd.snia.xam.string"
snia.xset.retention.base="1"
snia.xset.retention.base.enabled.binding="\"true\" "
snia.xset.retention.base.enabled.length="1"
snia.xset.retention.base.enabled.readOnly="true"
snia.xset.retention.base.enabled.type="application/vnd.snia.xam.boolean"
snia.xset.retention.base.starttime="2009-06-12T22:34:35.350-05:00"
snia.xset.retention.base.starttime.binding="true"
snia.xset.retention.base.starttime.length="29"
snia.xset.retention.base.starttime.readOnly="true"
snia.xset.retention.base.starttime.type="\"application/vnd.snia.xam.datetime\" "
snia.xset.retention.list.base="base"
snia.xset.retention.list.base.binding="true"
snia.xset.retention.list.base.length="4"
snia.xset.retention.list.base.readOnly="true"
snia.xset.retention.list.base.type="application/vnd.snia.xam.string"
snia.xset.retention.list.event="event"
snia.xset.retention.list.event.binding="true"
snia.xset.retention.list.event.length="5"
snia.xset.retention.list.event.readOnly="true"
snia.xset.retention.list.event.type="application/vnd.snia.xam.string"
snia.xset.time.access="2009-06-12T22:34:35.350-05:00"
snia.xset.time.access.binding="false"
snia.xset.time.access.length="29"
snia.xset.time.access.readOnly="true"
snia.xset.time.access.type="application/vnd.snia.xam.datetime"
snia.xset.time.commit="2009-06-12T22:34:35.350-05:00"
snia.xset.time.commit.binding="false"
snia.xset.time.commit.length="29"
snia.xset.time.commit.readOnly="true"
snia.xset.time.commit.type="application/vnd.snia.xam.datetime"
snia.xset.time.creation="2009-06-12T22:34:35.331-05:00"
snia.xset.time.creation.binding="true"
snia.xset.time.creation.length="29"
snia.xset.time.creation.readOnly="true"
snia.xset.time.creation.type="application/vnd.snia.xam.datetime"
snia.xset.time.xuid="2009-06-12T22:34:35.331-05:00"
snia.xset.time.xuid.binding="false"
snia.xset.time.xuid.length="29"
snia.xset.time.xuid.readOnly="true"
snia.xset.time.xuid.type="application/vnd.snia.xam.datetime"
snia.xset.xuid="AAA6AwAeVG4xMjQ0ODY0MDc1MzU4AQWDedILNL7Q"
snia.xset.xuid.binding="true"
snia.xset.xuid.length="30"
snia.xset.xuid.readOnly="true"
snia.xset.xuid.type="application/vnd.snia.xam.xuid"
$
If anybody else is interested in working with me in this space I would welcome their involvement.
0 comments:
Post a Comment