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