[Acl-Devel] user extended attributes for tmpfs
Jerry Epplin
jepplin at globalvelocity.com
Fri Apr 6 21:05:03 CEST 2007
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
See <file:Documentation/filesystems/tmpfs.txt> for details.
+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;
}
+#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 = 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 = inode->i_private; entry; entry = next_entry) {
+ next_entry = entry->next;
+ kfree(entry->name);
+ kfree(entry->val);
+ kfree(entry);
+ }
+ }
+#endif
clear_inode(inode);
}
@@ -1954,11 +1975,105 @@ static struct xattr_handler shmem_xattr_
.get = shmem_xattr_security_get,
.set = 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 = 0, cur_name_len;
+ struct shmem_xattr_user_entry *entry;
+ for (entry = inode->i_private; entry; entry = entry->next) {
+ if (list_len >= XATTR_USER_PREFIX_LEN) {
+ memcpy(list, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
+ list += XATTR_USER_PREFIX_LEN;
+ list_len -= XATTR_USER_PREFIX_LEN;
+ }
+ retlen += XATTR_USER_PREFIX_LEN;
+ cur_name_len = strlen(entry->name);
+ if (list_len >= cur_name_len) {
+ memcpy(list, entry->name, cur_name_len);
+ list += cur_name_len;
+ list_len -= cur_name_len;
+ }
+ retlen += cur_name_len;
+ if (list_len >= 1) {
+ *list++ = '\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, "") == 0)
+ return -EINVAL;
+ for (entry = inode->i_private; entry; entry = entry->next) {
+ if (!strcmp(entry->name, name)) {
+ if (entry->val_size < size)
+ size = 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 = strlen(name) + 1;
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+ for (entry = inode->i_private; entry; entry = 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 = kmalloc(sizeof(*entry), GFP_KERNEL);
+ entry->next = inode->i_private;
+ inode->i_private = entry;
+ entry->name = kmalloc(namelen, GFP_KERNEL);
+ memcpy(entry->name, name, namelen);
+ }
+ entry->val = kmalloc(size, GFP_KERNEL);
+ memcpy(entry->val, value, size);
+ entry->val_size = size;
+ return 0;
+}
+
+static struct xattr_handler shmem_xattr_user_handler = {
+ .prefix = XATTR_USER_PREFIX,
+ .list = shmem_xattr_user_list,
+ .get = shmem_xattr_user_get,
+ .set = shmem_xattr_user_set,
+};
+#endif
+#if defined(CONFIG_TMPFS_POSIX_ACL) || defined(CONFIG_TMPFS_USER_XATTR)
static struct xattr_handler *shmem_xattr_handlers[] = {
+#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 = TMPFS_MAGIC;
sb->s_op = &shmem_ops;
sb->s_time_gran = 1;
-#ifdef CONFIG_TMPFS_POSIX_ACL
+#if defined(CONFIG_TMPFS_POSIX_ACL) || defined(CONFIG_TMPFS_USER_XATTR)
sb->s_xattr = shmem_xattr_handlers;
+#endif
+#ifdef CONFIG_TMPFS_POSIX_ACL
sb->s_flags |= MS_POSIXACL;
#endif
@@ -2339,13 +2456,15 @@ static struct inode_operations shmem_ino
.truncate = shmem_truncate,
.setattr = shmem_notify_change,
.truncate_range = shmem_truncate_range,
-#ifdef CONFIG_TMPFS_POSIX_ACL
+#if defined(CONFIG_TMPFS_POSIX_ACL) || defined(CONFIG_TMPFS_USER_XATTR)
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = generic_listxattr,
.removexattr = generic_removexattr,
+#ifdef CONFIG_TMPFS_POSIX_ACL
.permission = shmem_permission,
#endif
+#endif
};
@@ -2361,25 +2480,29 @@ static struct inode_operations shmem_dir
.mknod = shmem_mknod,
.rename = shmem_rename,
#endif
-#ifdef CONFIG_TMPFS_POSIX_ACL
+#if defined(CONFIG_TMPFS_POSIX_ACL) || defined(CONFIG_TMPFS_USER_XATTR)
.setattr = shmem_notify_change,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = generic_listxattr,
.removexattr = generic_removexattr,
+#ifdef CONFIG_TMPFS_POSIX_ACL
.permission = shmem_permission,
#endif
+#endif
};
static struct inode_operations shmem_special_inode_operations = {
-#ifdef CONFIG_TMPFS_POSIX_ACL
+#if defined(CONFIG_TMPFS_POSIX_ACL) || defined(CONFIG_TMPFS_USER_XATTR)
.setattr = shmem_notify_change,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = generic_listxattr,
.removexattr = generic_removexattr,
+#ifdef CONFIG_TMPFS_POSIX_ACL
.permission = shmem_permission,
#endif
+#endif
};
static struct super_operations shmem_ops = {
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://acl.bestbits.at/pipermail/acl-devel/attachments/20070406/53c27cbc/attachment.htm
More information about the acl-devel
mailing list