user extended attributes for tmpfs

"Jerry Epplin" <[email protected]> Fri, 6 Apr 2007 14:05:03 -0500
Newsgroups gmane.linux.file-systems.acl.devel
Message-ID <E2EC54FAF6B9D4429F747476CDCD623A10C9F1@GVDC02.GLOBALVELOCITY.LOCAL>
This is a multi-part message in MIME format.

--===============2143732843==
Content-class: urn:content-classes:message
Content-Type: multipart/alternative;
	boundary="----_=_NextPart_001_01C7787E.7B3E43DF"

This is a multi-part message in MIME format.

------_=_NextPart_001_01C7787E.7B3E43DF
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

I'd be grateful for your feedback on whether this patch is the right =
approach
to implementing user xattrs for tmpfs.  Also, if there is a better forum
for this topic, please let me know.

Thanks,
Jerry Epplin

diff -urNp linux-2.6.20.4/fs/Kconfig =
linux-2.6.20.4-tmpfs-user-xattr/fs/Kconfig
--- linux-2.6.20.4/fs/Kconfig	2007-03-23 19:52:51.000000000 +0000
+++ linux-2.6.20.4-tmpfs-user-xattr/fs/Kconfig	2007-04-06 =
14:24:47.000000000 +0000
@@ -987,6 +987,16 @@ config TMPFS
=20
 	  See <file:Documentation/filesystems/tmpfs.txt> for details.
=20
+config TMPFS_USER_XATTR
+	bool "Tmpfs user extended attributes"
+	depends on TMPFS
+	help
+	  Extended attributes are name:value pairs associated with inodes by
+	  the kernel or by users (see the attr(5) manual page, or visit
+	  <http://acl.bestbits.at/> for details).
+
+	  If unsure, say N.
+
 config TMPFS_POSIX_ACL
 	bool "Tmpfs POSIX Access Control Lists"
 	depends on TMPFS
diff -urNp linux-2.6.20.4/mm/shmem.c =
linux-2.6.20.4-tmpfs-user-xattr/mm/shmem.c
--- linux-2.6.20.4/mm/shmem.c	2007-03-23 19:52:51.000000000 +0000
+++ linux-2.6.20.4-tmpfs-user-xattr/mm/shmem.c	2007-04-06 =
14:24:47.000000000 +0000
@@ -688,6 +688,15 @@ static int shmem_notify_change(struct de
 	return error;
 }
=20
+#ifdef CONFIG_TMPFS_USER_XATTR
+struct shmem_xattr_user_entry {
+	struct shmem_xattr_user_entry *next;
+	char *name;
+	char *val;
+	size_t val_size;
+};
+#endif
+
 static void shmem_delete_inode(struct inode *inode)
 {
 	struct shmem_sb_info *sbinfo =3D SHMEM_SB(inode->i_sb);
@@ -710,6 +719,18 @@ static void shmem_delete_inode(struct in
 		sbinfo->free_inodes++;
 		spin_unlock(&sbinfo->stat_lock);
 	}
+#ifdef CONFIG_TMPFS_USER_XATTR
+	/* remove any user xattrs */
+	{
+		struct shmem_xattr_user_entry *entry, *next_entry;
+		for (entry =3D inode->i_private; entry; entry =3D next_entry) {
+			next_entry =3D entry->next;
+			kfree(entry->name);
+			kfree(entry->val);
+			kfree(entry);
+		}
+	}
+#endif
 	clear_inode(inode);
 }
=20
@@ -1954,11 +1975,105 @@ static struct xattr_handler shmem_xattr_
 	.get    =3D shmem_xattr_security_get,
 	.set    =3D shmem_xattr_security_set,
 };
+#endif
+
+#ifdef CONFIG_TMPFS_USER_XATTR
+
+static size_t shmem_xattr_user_list(struct inode *inode, char *list,
+					size_t list_len, const char *name,
+					size_t name_len)
+{
+	size_t retlen =3D 0, cur_name_len;
+	struct shmem_xattr_user_entry *entry;
+	for (entry =3D inode->i_private; entry; entry =3D entry->next) {
+		if (list_len >=3D XATTR_USER_PREFIX_LEN) {
+			memcpy(list, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
+			list +=3D XATTR_USER_PREFIX_LEN;
+			list_len -=3D XATTR_USER_PREFIX_LEN;
+		}
+		retlen +=3D XATTR_USER_PREFIX_LEN;
+		cur_name_len =3D strlen(entry->name);
+		if (list_len >=3D cur_name_len) {
+			memcpy(list, entry->name, cur_name_len);
+			list +=3D cur_name_len;
+			list_len -=3D cur_name_len;
+		}
+		retlen +=3D cur_name_len;
+		if (list_len >=3D 1) {
+			*list++ =3D '\0';
+			--list_len;
+		}
+		++retlen;
+	}
+	return retlen;
+}
+
+static int shmem_xattr_user_get(struct inode *inode, const char *name,
+				    void *buffer, size_t size)
+{
+	struct shmem_xattr_user_entry *entry;
+	if (strcmp(name, "") =3D=3D 0)
+		return -EINVAL;
+	for (entry =3D inode->i_private; entry; entry =3D entry->next) {
+		if (!strcmp(entry->name, name)) {
+			if (entry->val_size < size)
+				size =3D entry->val_size;
+			memcpy(buffer, entry->val, size);
+			return entry->val_size;
+		}
+	}
+	return -ENODATA;
+}
+
+static int shmem_xattr_user_set(struct inode *inode, const char *name,
+				    const void *value, size_t size, int flags)
+{
+	struct shmem_xattr_user_entry *entry;
+	int namelen =3D strlen(name) + 1;
+	if (strcmp(name, "") =3D=3D 0)
+		return -EINVAL;
+	for (entry =3D inode->i_private; entry; entry =3D entry->next)
+		if (!strcmp(entry->name, name)) {
+			if (flags & XATTR_CREATE)
+				return -EEXIST;
+			else {
+				kfree(entry->val);
+				break;
+			}
+		}
+	if (!entry) {
+		if (flags & XATTR_REPLACE)
+			return -ENODATA;
+		entry =3D kmalloc(sizeof(*entry), GFP_KERNEL);
+		entry->next =3D inode->i_private;
+		inode->i_private =3D entry;
+		entry->name =3D kmalloc(namelen, GFP_KERNEL);
+		memcpy(entry->name, name, namelen);
+	}
+	entry->val =3D kmalloc(size, GFP_KERNEL);
+	memcpy(entry->val, value, size);
+	entry->val_size =3D size;
+	return 0;
+}
+
+static struct xattr_handler shmem_xattr_user_handler =3D {
+	.prefix =3D XATTR_USER_PREFIX,
+	.list   =3D shmem_xattr_user_list,
+	.get    =3D shmem_xattr_user_get,
+	.set    =3D shmem_xattr_user_set,
+};
+#endif
=20
+#if defined(CONFIG_TMPFS_POSIX_ACL) || defined(CONFIG_TMPFS_USER_XATTR)
 static struct xattr_handler *shmem_xattr_handlers[] =3D {
+#ifdef CONFIG_TMPFS_POSIX_ACL
 	&shmem_xattr_acl_access_handler,
 	&shmem_xattr_acl_default_handler,
 	&shmem_xattr_security_handler,
+#endif
+#ifdef CONFIG_TMPFS_USER_XATTR
+	&shmem_xattr_user_handler,
+#endif
 	NULL
 };
 #endif
@@ -2240,8 +2355,10 @@ static int shmem_fill_super(struct super
 	sb->s_magic =3D TMPFS_MAGIC;
 	sb->s_op =3D &shmem_ops;
 	sb->s_time_gran =3D 1;
-#ifdef CONFIG_TMPFS_POSIX_ACL
+#if defined(CONFIG_TMPFS_POSIX_ACL) || defined(CONFIG_TMPFS_USER_XATTR)
 	sb->s_xattr =3D shmem_xattr_handlers;
+#endif
+#ifdef CONFIG_TMPFS_POSIX_ACL
 	sb->s_flags |=3D MS_POSIXACL;
 #endif
=20
@@ -2339,13 +2456,15 @@ static struct inode_operations shmem_ino
 	.truncate	=3D shmem_truncate,
 	.setattr	=3D shmem_notify_change,
 	.truncate_range	=3D shmem_truncate_range,
-#ifdef CONFIG_TMPFS_POSIX_ACL
+#if defined(CONFIG_TMPFS_POSIX_ACL) || defined(CONFIG_TMPFS_USER_XATTR)
 	.setxattr	=3D generic_setxattr,
 	.getxattr	=3D generic_getxattr,
 	.listxattr	=3D generic_listxattr,
 	.removexattr	=3D generic_removexattr,
+#ifdef CONFIG_TMPFS_POSIX_ACL
 	.permission	=3D shmem_permission,
 #endif
+#endif
=20
 };
=20
@@ -2361,25 +2480,29 @@ static struct inode_operations shmem_dir
 	.mknod		=3D shmem_mknod,
 	.rename		=3D shmem_rename,
 #endif
-#ifdef CONFIG_TMPFS_POSIX_ACL
+#if defined(CONFIG_TMPFS_POSIX_ACL) || defined(CONFIG_TMPFS_USER_XATTR)
 	.setattr	=3D shmem_notify_change,
 	.setxattr	=3D generic_setxattr,
 	.getxattr	=3D generic_getxattr,
 	.listxattr	=3D generic_listxattr,
 	.removexattr	=3D generic_removexattr,
+#ifdef CONFIG_TMPFS_POSIX_ACL
 	.permission	=3D shmem_permission,
 #endif
+#endif
 };
=20
 static struct inode_operations shmem_special_inode_operations =3D {
-#ifdef CONFIG_TMPFS_POSIX_ACL
+#if defined(CONFIG_TMPFS_POSIX_ACL) || defined(CONFIG_TMPFS_USER_XATTR)
 	.setattr	=3D shmem_notify_change,
 	.setxattr	=3D generic_setxattr,
 	.getxattr	=3D generic_getxattr,
 	.listxattr	=3D generic_listxattr,
 	.removexattr	=3D generic_removexattr,
+#ifdef CONFIG_TMPFS_POSIX_ACL
 	.permission	=3D shmem_permission,
 #endif
+#endif
 };
=20
 static struct super_operations shmem_ops =3D {

------_=_NextPart_001_01C7787E.7B3E43DF
Content-Type: text/html;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
charset=3Diso-8859-1">
<META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version =
6.5.7651.59">
<TITLE>user extended attributes for tmpfs</TITLE>
</HEAD>
<BODY>
<!-- Converted from text/plain format -->

<P><FONT SIZE=3D2>I'd be grateful for your feedback on whether this =
patch is the right approach<BR>
to implementing user xattrs for tmpfs.&nbsp; Also, if there is a better =
forum<BR>
for this topic, please let me know.<BR>
<BR>
Thanks,<BR>
Jerry Epplin<BR>
<BR>
diff -urNp linux-2.6.20.4/fs/Kconfig =
linux-2.6.20.4-tmpfs-user-xattr/fs/Kconfig<BR>
--- linux-2.6.20.4/fs/Kconfig&nbsp;&nbsp; 2007-03-23 19:52:51.000000000 =
+0000<BR>
+++ linux-2.6.20.4-tmpfs-user-xattr/fs/Kconfig&nbsp; 2007-04-06 =
14:24:47.000000000 +0000<BR>
@@ -987,6 +987,16 @@ config TMPFS<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; See &lt;<A =
HREF=3D"file:Documentation/filesystems/tmpfs.txt">file:Documentation/file=
systems/tmpfs.txt</A>&gt; for details.<BR>
<BR>
+config TMPFS_USER_XATTR<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool &quot;Tmpfs user extended =
attributes&quot;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; depends on TMPFS<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; help<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; Extended attributes are =
name:value pairs associated with inodes by<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; the kernel or by users (see =
the attr(5) manual page, or visit<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &lt;<A =
HREF=3D"http://acl.bestbits.at/">http://acl.bestbits.at/</A>&gt; for =
details).<BR>
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; If unsure, say N.<BR>
+<BR>
&nbsp;config TMPFS_POSIX_ACL<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool &quot;Tmpfs POSIX Access =
Control Lists&quot;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; depends on TMPFS<BR>
diff -urNp linux-2.6.20.4/mm/shmem.c =
linux-2.6.20.4-tmpfs-user-xattr/mm/shmem.c<BR>
--- linux-2.6.20.4/mm/shmem.c&nbsp;&nbsp; 2007-03-23 19:52:51.000000000 =
+0000<BR>
+++ linux-2.6.20.4-tmpfs-user-xattr/mm/shmem.c&nbsp; 2007-04-06 =
14:24:47.000000000 +0000<BR>
@@ -688,6 +688,15 @@ static int shmem_notify_change(struct de<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return error;<BR>
&nbsp;}<BR>
<BR>
+#ifdef CONFIG_TMPFS_USER_XATTR<BR>
+struct shmem_xattr_user_entry {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct shmem_xattr_user_entry =
*next;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *name;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *val;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t val_size;<BR>
+};<BR>
+#endif<BR>
+<BR>
&nbsp;static void shmem_delete_inode(struct inode *inode)<BR>
&nbsp;{<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct shmem_sb_info *sbinfo =
=3D SHMEM_SB(inode-&gt;i_sb);<BR>
@@ -710,6 +719,18 @@ static void shmem_delete_inode(struct in<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sbinfo-&gt;free_inodes++;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
spin_unlock(&amp;sbinfo-&gt;stat_lock);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+#ifdef CONFIG_TMPFS_USER_XATTR<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* remove any user xattrs */<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct shmem_xattr_user_entry =
*entry, *next_entry;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (entry =3D =
inode-&gt;i_private; entry; entry =3D next_entry) {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; next_entry =3D =
entry-&gt;next;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kfree(entry-&gt;name);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kfree(entry-&gt;val);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kfree(entry);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+#endif<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clear_inode(inode);<BR>
&nbsp;}<BR>
<BR>
@@ -1954,11 +1975,105 @@ static struct xattr_handler shmem_xattr_<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .get&nbsp;&nbsp;&nbsp; =3D =
shmem_xattr_security_get,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .set&nbsp;&nbsp;&nbsp; =3D =
shmem_xattr_security_set,<BR>
&nbsp;};<BR>
+#endif<BR>
+<BR>
+#ifdef CONFIG_TMPFS_USER_XATTR<BR>
+<BR>
+static size_t shmem_xattr_user_list(struct inode *inode, char =
*list,<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t list_len, const char =
*name,<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t name_len)<BR>
+{<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t retlen =3D 0, =
cur_name_len;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct shmem_xattr_user_entry =
*entry;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (entry =3D =
inode-&gt;i_private; entry; entry =3D entry-&gt;next) {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (list_len &gt;=3D =
XATTR_USER_PREFIX_LEN) {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memcpy(list, =
XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list +=3D =
XATTR_USER_PREFIX_LEN;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list_len -=3D =
XATTR_USER_PREFIX_LEN;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; retlen +=3D =
XATTR_USER_PREFIX_LEN;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cur_name_len =3D =
strlen(entry-&gt;name);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (list_len &gt;=3D =
cur_name_len) {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memcpy(list, entry-&gt;name, =
cur_name_len);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list +=3D cur_name_len;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list_len -=3D =
cur_name_len;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; retlen +=3D cur_name_len;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (list_len &gt;=3D 1) {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *list++ =3D '\0';<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --list_len;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++retlen;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return retlen;<BR>
+}<BR>
+<BR>
+static int shmem_xattr_user_get(struct inode *inode, const char =
*name,<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void =
*buffer, size_t size)<BR>
+{<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct shmem_xattr_user_entry =
*entry;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (strcmp(name, &quot;&quot;) =
=3D=3D 0)<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -EINVAL;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (entry =3D =
inode-&gt;i_private; entry; entry =3D entry-&gt;next) {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!strcmp(entry-&gt;name, =
name)) {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (entry-&gt;val_size &lt; =
size)<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size =3D =
entry-&gt;val_size;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memcpy(buffer, entry-&gt;val, =
size);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return =
entry-&gt;val_size;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -ENODATA;<BR>
+}<BR>
+<BR>
+static int shmem_xattr_user_set(struct inode *inode, const char =
*name,<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; const void =
*value, size_t size, int flags)<BR>
+{<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct shmem_xattr_user_entry =
*entry;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int namelen =3D strlen(name) + =
1;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (strcmp(name, &quot;&quot;) =
=3D=3D 0)<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -EINVAL;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (entry =3D =
inode-&gt;i_private; entry; entry =3D entry-&gt;next)<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!strcmp(entry-&gt;name, =
name)) {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flags &amp; =
XATTR_CREATE)<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -EEXIST;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kfree(entry-&gt;val);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!entry) {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flags &amp; =
XATTR_REPLACE)<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -ENODATA;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; entry =3D =
kmalloc(sizeof(*entry), GFP_KERNEL);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; entry-&gt;next =3D =
inode-&gt;i_private;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode-&gt;i_private =3D =
entry;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; entry-&gt;name =3D =
kmalloc(namelen, GFP_KERNEL);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memcpy(entry-&gt;name, name, =
namelen);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; entry-&gt;val =3D kmalloc(size, =
GFP_KERNEL);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memcpy(entry-&gt;val, value, =
size);<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; entry-&gt;val_size =3D size;<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>
+}<BR>
+<BR>
+static struct xattr_handler shmem_xattr_user_handler =3D {<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .prefix =3D XATTR_USER_PREFIX,<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .list&nbsp;&nbsp; =3D =
shmem_xattr_user_list,<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .get&nbsp;&nbsp;&nbsp; =3D =
shmem_xattr_user_get,<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .set&nbsp;&nbsp;&nbsp; =3D =
shmem_xattr_user_set,<BR>
+};<BR>
+#endif<BR>
<BR>
+#if defined(CONFIG_TMPFS_POSIX_ACL) || =
defined(CONFIG_TMPFS_USER_XATTR)<BR>
&nbsp;static struct xattr_handler *shmem_xattr_handlers[] =3D {<BR>
+#ifdef CONFIG_TMPFS_POSIX_ACL<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&amp;shmem_xattr_acl_access_handler,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&amp;shmem_xattr_acl_default_handler,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&amp;shmem_xattr_security_handler,<BR>
+#endif<BR>
+#ifdef CONFIG_TMPFS_USER_XATTR<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;shmem_xattr_user_handler,<BR>
+#endif<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL<BR>
&nbsp;};<BR>
&nbsp;#endif<BR>
@@ -2240,8 +2355,10 @@ static int shmem_fill_super(struct super<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb-&gt;s_magic =3D =
TMPFS_MAGIC;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb-&gt;s_op =3D =
&amp;shmem_ops;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb-&gt;s_time_gran =3D 1;<BR>
-#ifdef CONFIG_TMPFS_POSIX_ACL<BR>
+#if defined(CONFIG_TMPFS_POSIX_ACL) || =
defined(CONFIG_TMPFS_USER_XATTR)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb-&gt;s_xattr =3D =
shmem_xattr_handlers;<BR>
+#endif<BR>
+#ifdef CONFIG_TMPFS_POSIX_ACL<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb-&gt;s_flags |=3D =
MS_POSIXACL;<BR>
&nbsp;#endif<BR>
<BR>
@@ -2339,13 +2456,15 @@ static struct inode_operations shmem_ino<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.truncate&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D shmem_truncate,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.setattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D =
shmem_notify_change,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .truncate_range =3D =
shmem_truncate_range,<BR>
-#ifdef CONFIG_TMPFS_POSIX_ACL<BR>
+#if defined(CONFIG_TMPFS_POSIX_ACL) || =
defined(CONFIG_TMPFS_USER_XATTR)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.setxattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D generic_setxattr,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.getxattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D generic_getxattr,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.listxattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D generic_listxattr,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.removexattr&nbsp;&nbsp;&nbsp; =3D generic_removexattr,<BR>
+#ifdef CONFIG_TMPFS_POSIX_ACL<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.permission&nbsp;&nbsp;&nbsp;&nbsp; =3D shmem_permission,<BR>
&nbsp;#endif<BR>
+#endif<BR>
<BR>
&nbsp;};<BR>
<BR>
@@ -2361,25 +2480,29 @@ static struct inode_operations shmem_dir<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .mknod&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D shmem_mknod,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .rename =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D shmem_rename,<BR>
&nbsp;#endif<BR>
-#ifdef CONFIG_TMPFS_POSIX_ACL<BR>
+#if defined(CONFIG_TMPFS_POSIX_ACL) || =
defined(CONFIG_TMPFS_USER_XATTR)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.setattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D =
shmem_notify_change,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.setxattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D generic_setxattr,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.getxattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D generic_getxattr,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.listxattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D generic_listxattr,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.removexattr&nbsp;&nbsp;&nbsp; =3D generic_removexattr,<BR>
+#ifdef CONFIG_TMPFS_POSIX_ACL<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.permission&nbsp;&nbsp;&nbsp;&nbsp; =3D shmem_permission,<BR>
&nbsp;#endif<BR>
+#endif<BR>
&nbsp;};<BR>
<BR>
&nbsp;static struct inode_operations shmem_special_inode_operations =3D =
{<BR>
-#ifdef CONFIG_TMPFS_POSIX_ACL<BR>
+#if defined(CONFIG_TMPFS_POSIX_ACL) || =
defined(CONFIG_TMPFS_USER_XATTR)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.setattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D =
shmem_notify_change,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.setxattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D generic_setxattr,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.getxattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D generic_getxattr,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.listxattr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =3D generic_listxattr,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.removexattr&nbsp;&nbsp;&nbsp; =3D generic_removexattr,<BR>
+#ifdef CONFIG_TMPFS_POSIX_ACL<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
.permission&nbsp;&nbsp;&nbsp;&nbsp; =3D shmem_permission,<BR>
&nbsp;#endif<BR>
+#endif<BR>
&nbsp;};<BR>
<BR>
&nbsp;static struct super_operations shmem_ops =3D {<BR>
</FONT>
</P>

</BODY>
</HTML>
------_=_NextPart_001_01C7787E.7B3E43DF--

--===============2143732843==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
acl-devel mailing list
[email protected]
http://acl.bestbits.at/mailman/listinfo/acl-devel

--===============2143732843==--