Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

9p: xattr simplifications

Now that the xattr handler is passed to the xattr handler operations, we
can use the same get and set operations for the user, trusted, and security
xattr namespaces. In those namespaces, we can access the full attribute
name by "reattaching" the name prefix the vfs has skipped for us. Add a
xattr_full_name helper to make this obvious in the code.

For the "system.posix_acl_access" and "system.posix_acl_default"
attributes, handler->prefix is the full attribute name; the suffix is the
empty string.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Cc: Eric Van Hensbergen <ericvh@gmail.com>
Cc: Ron Minnich <rminnich@sandia.gov>
Cc: Latchesar Ionkov <lucho@ionkov.net>
Cc: v9fs-developer@lists.sourceforge.net
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

authored by

Andreas Gruenbacher and committed by
Al Viro
e409de99 d9a82a04

+83 -306
+1 -4
fs/9p/Makefile
··· 10 10 vfs_dentry.o \ 11 11 v9fs.o \ 12 12 fid.o \ 13 - xattr.o \ 14 - xattr_user.o \ 15 - xattr_trusted.o 13 + xattr.o 16 14 17 15 9p-$(CONFIG_9P_FSCACHE) += cache.o 18 16 9p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o 19 - 9p-$(CONFIG_9P_FS_SECURITY) += xattr_security.o
+5 -46
fs/9p/acl.c
··· 212 212 return 0; 213 213 } 214 214 215 - static int v9fs_remote_get_acl(struct dentry *dentry, const char *name, 216 - void *buffer, size_t size, int type) 217 - { 218 - char *full_name; 219 - 220 - switch (type) { 221 - case ACL_TYPE_ACCESS: 222 - full_name = POSIX_ACL_XATTR_ACCESS; 223 - break; 224 - case ACL_TYPE_DEFAULT: 225 - full_name = POSIX_ACL_XATTR_DEFAULT; 226 - break; 227 - default: 228 - BUG(); 229 - } 230 - return v9fs_xattr_get(dentry, full_name, buffer, size); 231 - } 232 - 233 215 static int v9fs_xattr_get_acl(const struct xattr_handler *handler, 234 216 struct dentry *dentry, const char *name, 235 217 void *buffer, size_t size) 236 218 { 237 219 struct v9fs_session_info *v9ses; 238 220 struct posix_acl *acl; 239 - int type = handler->flags; 240 221 int error; 241 222 242 223 if (strcmp(name, "") != 0) ··· 228 247 * We allow set/get/list of acl when access=client is not specified 229 248 */ 230 249 if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) 231 - return v9fs_remote_get_acl(dentry, name, buffer, size, type); 250 + return v9fs_xattr_get(dentry, handler->prefix, buffer, size); 232 251 233 - acl = v9fs_get_cached_acl(d_inode(dentry), type); 252 + acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags); 234 253 if (IS_ERR(acl)) 235 254 return PTR_ERR(acl); 236 255 if (acl == NULL) ··· 240 259 241 260 return error; 242 261 } 243 - 244 - static int v9fs_remote_set_acl(struct dentry *dentry, const char *name, 245 - const void *value, size_t size, 246 - int flags, int type) 247 - { 248 - char *full_name; 249 - 250 - switch (type) { 251 - case ACL_TYPE_ACCESS: 252 - full_name = POSIX_ACL_XATTR_ACCESS; 253 - break; 254 - case ACL_TYPE_DEFAULT: 255 - full_name = POSIX_ACL_XATTR_DEFAULT; 256 - break; 257 - default: 258 - BUG(); 259 - } 260 - return v9fs_xattr_set(dentry, full_name, value, size, flags); 261 - } 262 - 263 262 264 263 static int v9fs_xattr_set_acl(const struct xattr_handler *handler, 265 264 struct dentry *dentry, const char *name, ··· 259 298 * xattr value. We leave it to the server to validate 260 299 */ 261 300 if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) 262 - return v9fs_remote_set_acl(dentry, name, 263 - value, size, flags, handler->flags); 301 + return v9fs_xattr_set(dentry, handler->prefix, value, size, 302 + flags); 264 303 265 304 if (S_ISLNK(inode->i_mode)) 266 305 return -EOPNOTSUPP; ··· 281 320 282 321 switch (handler->flags) { 283 322 case ACL_TYPE_ACCESS: 284 - name = POSIX_ACL_XATTR_ACCESS; 285 323 if (acl) { 286 324 umode_t mode = inode->i_mode; 287 325 retval = posix_acl_equiv_mode(acl, &mode); ··· 311 351 } 312 352 break; 313 353 case ACL_TYPE_DEFAULT: 314 - name = POSIX_ACL_XATTR_DEFAULT; 315 354 if (!S_ISDIR(inode->i_mode)) { 316 355 retval = acl ? -EINVAL : 0; 317 356 goto err_out; ··· 319 360 default: 320 361 BUG(); 321 362 } 322 - retval = v9fs_xattr_set(dentry, name, value, size, flags); 363 + retval = v9fs_xattr_set(dentry, handler->prefix, value, size, flags); 323 364 if (!retval) 324 365 set_cached_acl(inode, handler->flags, acl); 325 366 err_out:
+42
fs/9p/xattr.c
··· 137 137 return v9fs_xattr_get(dentry, NULL, buffer, buffer_size); 138 138 } 139 139 140 + static int v9fs_xattr_handler_get(const struct xattr_handler *handler, 141 + struct dentry *dentry, const char *name, 142 + void *buffer, size_t size) 143 + { 144 + const char *full_name = xattr_full_name(handler, name); 145 + 146 + if (strcmp(name, "") == 0) 147 + return -EINVAL; 148 + return v9fs_xattr_get(dentry, full_name, buffer, size); 149 + } 150 + 151 + static int v9fs_xattr_handler_set(const struct xattr_handler *handler, 152 + struct dentry *dentry, const char *name, 153 + const void *value, size_t size, int flags) 154 + { 155 + const char *full_name = xattr_full_name(handler, name); 156 + 157 + if (strcmp(name, "") == 0) 158 + return -EINVAL; 159 + return v9fs_xattr_set(dentry, full_name, value, size, flags); 160 + } 161 + 162 + static struct xattr_handler v9fs_xattr_user_handler = { 163 + .prefix = XATTR_USER_PREFIX, 164 + .get = v9fs_xattr_handler_get, 165 + .set = v9fs_xattr_handler_set, 166 + }; 167 + 168 + static struct xattr_handler v9fs_xattr_trusted_handler = { 169 + .prefix = XATTR_TRUSTED_PREFIX, 170 + .get = v9fs_xattr_handler_get, 171 + .set = v9fs_xattr_handler_set, 172 + }; 173 + 174 + #ifdef CONFIG_9P_FS_SECURITY 175 + static struct xattr_handler v9fs_xattr_security_handler = { 176 + .prefix = XATTR_SECURITY_PREFIX, 177 + .get = v9fs_xattr_handler_get, 178 + .set = v9fs_xattr_handler_set, 179 + }; 180 + #endif 181 + 140 182 const struct xattr_handler *v9fs_xattr_handlers[] = { 141 183 &v9fs_xattr_user_handler, 142 184 &v9fs_xattr_trusted_handler,
-3
fs/9p/xattr.h
··· 19 19 #include <net/9p/client.h> 20 20 21 21 extern const struct xattr_handler *v9fs_xattr_handlers[]; 22 - extern struct xattr_handler v9fs_xattr_user_handler; 23 - extern struct xattr_handler v9fs_xattr_trusted_handler; 24 - extern struct xattr_handler v9fs_xattr_security_handler; 25 22 extern const struct xattr_handler v9fs_xattr_acl_access_handler; 26 23 extern const struct xattr_handler v9fs_xattr_acl_default_handler; 27 24
-82
fs/9p/xattr_security.c
··· 1 - /* 2 - * Copyright IBM Corporation, 2010 3 - * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 4 - * 5 - * This program is free software; you can redistribute it and/or modify it 6 - * under the terms of version 2.1 of the GNU Lesser General Public License 7 - * as published by the Free Software Foundation. 8 - * 9 - * This program is distributed in the hope that it would be useful, but 10 - * WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 - * 13 - */ 14 - 15 - 16 - #include <linux/module.h> 17 - #include <linux/string.h> 18 - #include <linux/fs.h> 19 - #include <linux/slab.h> 20 - #include "xattr.h" 21 - 22 - static int v9fs_xattr_security_get(const struct xattr_handler *handler, 23 - struct dentry *dentry, const char *name, 24 - void *buffer, size_t size) 25 - { 26 - int retval; 27 - char *full_name; 28 - size_t name_len; 29 - size_t prefix_len = XATTR_SECURITY_PREFIX_LEN; 30 - 31 - if (name == NULL) 32 - return -EINVAL; 33 - 34 - if (strcmp(name, "") == 0) 35 - return -EINVAL; 36 - 37 - name_len = strlen(name); 38 - full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); 39 - if (!full_name) 40 - return -ENOMEM; 41 - memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len); 42 - memcpy(full_name+prefix_len, name, name_len); 43 - full_name[prefix_len + name_len] = '\0'; 44 - 45 - retval = v9fs_xattr_get(dentry, full_name, buffer, size); 46 - kfree(full_name); 47 - return retval; 48 - } 49 - 50 - static int v9fs_xattr_security_set(const struct xattr_handler *handler, 51 - struct dentry *dentry, const char *name, 52 - const void *value, size_t size, int flags) 53 - { 54 - int retval; 55 - char *full_name; 56 - size_t name_len; 57 - size_t prefix_len = XATTR_SECURITY_PREFIX_LEN; 58 - 59 - if (name == NULL) 60 - return -EINVAL; 61 - 62 - if (strcmp(name, "") == 0) 63 - return -EINVAL; 64 - 65 - name_len = strlen(name); 66 - full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); 67 - if (!full_name) 68 - return -ENOMEM; 69 - memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len); 70 - memcpy(full_name + prefix_len, name, name_len); 71 - full_name[prefix_len + name_len] = '\0'; 72 - 73 - retval = v9fs_xattr_set(dentry, full_name, value, size, flags); 74 - kfree(full_name); 75 - return retval; 76 - } 77 - 78 - struct xattr_handler v9fs_xattr_security_handler = { 79 - .prefix = XATTR_SECURITY_PREFIX, 80 - .get = v9fs_xattr_security_get, 81 - .set = v9fs_xattr_security_set, 82 - };
-82
fs/9p/xattr_trusted.c
··· 1 - /* 2 - * Copyright IBM Corporation, 2010 3 - * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 4 - * 5 - * This program is free software; you can redistribute it and/or modify it 6 - * under the terms of version 2.1 of the GNU Lesser General Public License 7 - * as published by the Free Software Foundation. 8 - * 9 - * This program is distributed in the hope that it would be useful, but 10 - * WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 - * 13 - */ 14 - 15 - 16 - #include <linux/module.h> 17 - #include <linux/string.h> 18 - #include <linux/fs.h> 19 - #include <linux/slab.h> 20 - #include "xattr.h" 21 - 22 - static int v9fs_xattr_trusted_get(const struct xattr_handler *handler, 23 - struct dentry *dentry, const char *name, 24 - void *buffer, size_t size) 25 - { 26 - int retval; 27 - char *full_name; 28 - size_t name_len; 29 - size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN; 30 - 31 - if (name == NULL) 32 - return -EINVAL; 33 - 34 - if (strcmp(name, "") == 0) 35 - return -EINVAL; 36 - 37 - name_len = strlen(name); 38 - full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); 39 - if (!full_name) 40 - return -ENOMEM; 41 - memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len); 42 - memcpy(full_name+prefix_len, name, name_len); 43 - full_name[prefix_len + name_len] = '\0'; 44 - 45 - retval = v9fs_xattr_get(dentry, full_name, buffer, size); 46 - kfree(full_name); 47 - return retval; 48 - } 49 - 50 - static int v9fs_xattr_trusted_set(const struct xattr_handler *handler, 51 - struct dentry *dentry, const char *name, 52 - const void *value, size_t size, int flags) 53 - { 54 - int retval; 55 - char *full_name; 56 - size_t name_len; 57 - size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN; 58 - 59 - if (name == NULL) 60 - return -EINVAL; 61 - 62 - if (strcmp(name, "") == 0) 63 - return -EINVAL; 64 - 65 - name_len = strlen(name); 66 - full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); 67 - if (!full_name) 68 - return -ENOMEM; 69 - memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len); 70 - memcpy(full_name + prefix_len, name, name_len); 71 - full_name[prefix_len + name_len] = '\0'; 72 - 73 - retval = v9fs_xattr_set(dentry, full_name, value, size, flags); 74 - kfree(full_name); 75 - return retval; 76 - } 77 - 78 - struct xattr_handler v9fs_xattr_trusted_handler = { 79 - .prefix = XATTR_TRUSTED_PREFIX, 80 - .get = v9fs_xattr_trusted_get, 81 - .set = v9fs_xattr_trusted_set, 82 - };
-82
fs/9p/xattr_user.c
··· 1 - /* 2 - * Copyright IBM Corporation, 2010 3 - * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 4 - * 5 - * This program is free software; you can redistribute it and/or modify it 6 - * under the terms of version 2.1 of the GNU Lesser General Public License 7 - * as published by the Free Software Foundation. 8 - * 9 - * This program is distributed in the hope that it would be useful, but 10 - * WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 - * 13 - */ 14 - 15 - 16 - #include <linux/module.h> 17 - #include <linux/string.h> 18 - #include <linux/fs.h> 19 - #include <linux/slab.h> 20 - #include "xattr.h" 21 - 22 - static int v9fs_xattr_user_get(const struct xattr_handler *handler, 23 - struct dentry *dentry, const char *name, 24 - void *buffer, size_t size) 25 - { 26 - int retval; 27 - char *full_name; 28 - size_t name_len; 29 - size_t prefix_len = XATTR_USER_PREFIX_LEN; 30 - 31 - if (name == NULL) 32 - return -EINVAL; 33 - 34 - if (strcmp(name, "") == 0) 35 - return -EINVAL; 36 - 37 - name_len = strlen(name); 38 - full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); 39 - if (!full_name) 40 - return -ENOMEM; 41 - memcpy(full_name, XATTR_USER_PREFIX, prefix_len); 42 - memcpy(full_name+prefix_len, name, name_len); 43 - full_name[prefix_len + name_len] = '\0'; 44 - 45 - retval = v9fs_xattr_get(dentry, full_name, buffer, size); 46 - kfree(full_name); 47 - return retval; 48 - } 49 - 50 - static int v9fs_xattr_user_set(const struct xattr_handler *handler, 51 - struct dentry *dentry, const char *name, 52 - const void *value, size_t size, int flags) 53 - { 54 - int retval; 55 - char *full_name; 56 - size_t name_len; 57 - size_t prefix_len = XATTR_USER_PREFIX_LEN; 58 - 59 - if (name == NULL) 60 - return -EINVAL; 61 - 62 - if (strcmp(name, "") == 0) 63 - return -EINVAL; 64 - 65 - name_len = strlen(name); 66 - full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); 67 - if (!full_name) 68 - return -ENOMEM; 69 - memcpy(full_name, XATTR_USER_PREFIX, prefix_len); 70 - memcpy(full_name + prefix_len, name, name_len); 71 - full_name[prefix_len + name_len] = '\0'; 72 - 73 - retval = v9fs_xattr_set(dentry, full_name, value, size, flags); 74 - kfree(full_name); 75 - return retval; 76 - } 77 - 78 - struct xattr_handler v9fs_xattr_user_handler = { 79 - .prefix = XATTR_USER_PREFIX, 80 - .get = v9fs_xattr_user_get, 81 - .set = v9fs_xattr_user_set, 82 - };
+24
fs/xattr.c
··· 790 790 EXPORT_SYMBOL(generic_setxattr); 791 791 EXPORT_SYMBOL(generic_removexattr); 792 792 793 + /** 794 + * xattr_full_name - Compute full attribute name from suffix 795 + * 796 + * @handler: handler of the xattr_handler operation 797 + * @name: name passed to the xattr_handler operation 798 + * 799 + * The get and set xattr handler operations are called with the remainder of 800 + * the attribute name after skipping the handler's prefix: for example, "foo" 801 + * is passed to the get operation of a handler with prefix "user." to get 802 + * attribute "user.foo". The full name is still "there" in the name though. 803 + * 804 + * Note: the list xattr handler operation when called from the vfs is passed a 805 + * NULL name; some file systems use this operation internally, with varying 806 + * semantics. 807 + */ 808 + const char *xattr_full_name(const struct xattr_handler *handler, 809 + const char *name) 810 + { 811 + size_t prefix_len = strlen(handler->prefix); 812 + 813 + return name - prefix_len; 814 + } 815 + EXPORT_SYMBOL(xattr_full_name); 816 + 793 817 /* 794 818 * Allocate new xattr and copy in the value; but leave the name to callers. 795 819 */
+11 -7
include/linux/xattr.h
··· 21 21 22 22 struct xattr_handler { 23 23 const char *prefix; 24 - int flags; /* fs private flags passed back to the handlers */ 25 - size_t (*list)(struct dentry *dentry, char *list, size_t list_size, 26 - const char *name, size_t name_len, int handler_flags); 27 - int (*get)(struct dentry *dentry, const char *name, void *buffer, 28 - size_t size, int handler_flags); 29 - int (*set)(struct dentry *dentry, const char *name, const void *buffer, 30 - size_t size, int flags, int handler_flags); 24 + int flags; /* fs private flags */ 25 + size_t (*list)(const struct xattr_handler *, struct dentry *dentry, 26 + char *list, size_t list_size, const char *name, 27 + size_t name_len); 28 + int (*get)(const struct xattr_handler *, struct dentry *dentry, 29 + const char *name, void *buffer, size_t size); 30 + int (*set)(const struct xattr_handler *, struct dentry *dentry, 31 + const char *name, const void *buffer, size_t size, 32 + int flags); 31 33 }; 34 + 35 + const char *xattr_full_name(const struct xattr_handler *, const char *); 32 36 33 37 struct xattr { 34 38 const char *name;