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

xattr: Stop calling {get,set,remove}xattr inode operations

All filesystems that support xattrs by now do so via xattr handlers.
They all define sb->s_xattr, and their getxattr, setxattr, and
removexattr inode operations use the generic inode operations. On
filesystems that don't support xattrs, the xattr inode operations are
all NULL, and sb->s_xattr is also NULL.

This means that we can remove the getxattr, setxattr, and removexattr
inode operations and directly call the generic handlers, or better,
inline expand those handlers into fs/xattr.c.

Filesystems that do not support xattrs on some inodes should clear the
IOP_XATTR i_opflags flag in those inodes. (Right now, some filesystems
have checks to disable xattrs on some inodes in the ->list, ->get, and
->set xattr handler operations instead.) The IOP_XATTR flag is
automatically cleared in inodes of filesystems that don't have xattr
support.

In orangefs, symlinks do have a setxattr iop but no getxattr iop. Add a
check for symlinks to orangefs_inode_getxattr to preserve the current,
weird behavior; that check may not be necessary though.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

authored by

Andreas Gruenbacher and committed by
Al Viro
6c6ef9f2 bf3ee713

+85 -39
+18 -6
Documentation/filesystems/Locking
··· 61 61 int (*get_acl)(struct inode *, int); 62 62 int (*setattr) (struct dentry *, struct iattr *); 63 63 int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *); 64 - int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); 65 - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); 66 64 ssize_t (*listxattr) (struct dentry *, char *, size_t); 67 - int (*removexattr) (struct dentry *, const char *); 68 65 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); 69 66 void (*update_time)(struct inode *, struct timespec *, int); 70 67 int (*atomic_open)(struct inode *, struct dentry *, ··· 88 91 permission: no (may not block if called in rcu-walk mode) 89 92 get_acl: no 90 93 getattr: no 91 - setxattr: yes 92 - getxattr: no 93 94 listxattr: no 94 - removexattr: yes 95 95 fiemap: no 96 96 update_time: no 97 97 atomic_open: yes 98 98 tmpfile: no 99 + 99 100 100 101 Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on 101 102 victim. ··· 102 107 103 108 See Documentation/filesystems/directory-locking for more detailed discussion 104 109 of the locking scheme for directory operations. 110 + 111 + ----------------------- xattr_handler operations ----------------------- 112 + prototypes: 113 + bool (*list)(struct dentry *dentry); 114 + int (*get)(const struct xattr_handler *handler, struct dentry *dentry, 115 + struct inode *inode, const char *name, void *buffer, 116 + size_t size); 117 + int (*set)(const struct xattr_handler *handler, struct dentry *dentry, 118 + struct inode *inode, const char *name, const void *buffer, 119 + size_t size, int flags); 120 + 121 + locking rules: 122 + all may block 123 + i_mutex(inode) 124 + list: no 125 + get: no 126 + set: yes 105 127 106 128 --------------------------- super_operations --------------------------- 107 129 prototypes:
+30 -15
Documentation/filesystems/vfs.txt
··· 323 323 is a pointer to a "struct inode_operations" which describes the methods that 324 324 can be performed on individual inodes. 325 325 326 + struct xattr_handlers 327 + --------------------- 328 + 329 + On filesystems that support extended attributes (xattrs), the s_xattr 330 + superblock field points to a NULL-terminated array of xattr handlers. Extended 331 + attributes are name:value pairs. 332 + 333 + name: Indicates that the handler matches attributes with the specified name 334 + (such as "system.posix_acl_access"); the prefix field must be NULL. 335 + 336 + prefix: Indicates that the handler matches all attributes with the specified 337 + name prefix (such as "user."); the name field must be NULL. 338 + 339 + list: Determine if attributes matching this xattr handler should be listed 340 + for a particular dentry. Used by some listxattr implementations like 341 + generic_listxattr. 342 + 343 + get: Called by the VFS to get the value of a particular extended attribute. 344 + This method is called by the getxattr(2) system call. 345 + 346 + set: Called by the VFS to set the value of a particular extended attribute. 347 + When the new value is NULL, called to remove a particular extended 348 + attribute. This method is called by the the setxattr(2) and 349 + removexattr(2) system calls. 350 + 351 + When none of the xattr handlers of a filesystem match the specified attribute 352 + name or when a filesystem doesn't support extended attributes, the various 353 + *xattr(2) system calls return -EOPNOTSUPP. 354 + 326 355 327 356 The Inode Object 328 357 ================ ··· 385 356 int (*get_acl)(struct inode *, int); 386 357 int (*setattr) (struct dentry *, struct iattr *); 387 358 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); 388 - int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); 389 - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); 390 359 ssize_t (*listxattr) (struct dentry *, char *, size_t); 391 - int (*removexattr) (struct dentry *, const char *); 392 360 void (*update_time)(struct inode *, struct timespec *, int); 393 361 int (*atomic_open)(struct inode *, struct dentry *, struct file *, 394 362 unsigned open_flag, umode_t create_mode, int *opened); ··· 489 463 getattr: called by the VFS to get attributes of a file. This method 490 464 is called by stat(2) and related system calls. 491 465 492 - setxattr: called by the VFS to set an extended attribute for a file. 493 - Extended attribute is a name:value pair associated with an 494 - inode. This method is called by setxattr(2) system call. 495 - 496 - getxattr: called by the VFS to retrieve the value of an extended 497 - attribute name. This method is called by getxattr(2) function 498 - call. 499 - 500 466 listxattr: called by the VFS to list all extended attributes for a 501 - given file. This method is called by listxattr(2) system call. 502 - 503 - removexattr: called by the VFS to remove an extended attribute from 504 - a file. This method is called by removexattr(2) system call. 467 + given file. This method is called by the listxattr(2) system call. 505 468 506 469 update_time: called by the VFS to update a specific time or the i_version of 507 470 an inode. If this is not defined the VFS will update the inode itself
+3
fs/orangefs/xattr.c
··· 73 73 "%s: name %s, buffer_size %zd\n", 74 74 __func__, name, size); 75 75 76 + if (S_ISLNK(inode->i_mode)) 77 + return -EOPNOTSUPP; 78 + 76 79 if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) { 77 80 gossip_err("Invalid key length (%d)\n", 78 81 (int)strlen(name));
+34 -18
fs/xattr.c
··· 36 36 37 37 /* 38 38 * In order to implement different sets of xattr operations for each xattr 39 - * prefix with the generic xattr API, a filesystem should create a 40 - * null-terminated array of struct xattr_handler (one for each prefix) and 41 - * hang a pointer to it off of the s_xattr field of the superblock. 42 - * 43 - * The generic_fooxattr() functions will use this list to dispatch xattr 44 - * operations to the correct xattr_handler. 39 + * prefix, a filesystem should create a null-terminated array of struct 40 + * xattr_handler (one for each prefix) and hang a pointer to it off of the 41 + * s_xattr field of the superblock. 45 42 */ 46 43 #define for_each_xattr_handler(handlers, handler) \ 47 44 if (handlers) \ ··· 137 140 __vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name, 138 141 const void *value, size_t size, int flags) 139 142 { 140 - if (!inode->i_op->setxattr) 143 + const struct xattr_handler *handler; 144 + 145 + handler = xattr_resolve_name(inode, &name); 146 + if (IS_ERR(handler)) 147 + return PTR_ERR(handler); 148 + if (!handler->set) 141 149 return -EOPNOTSUPP; 142 - return inode->i_op->setxattr(dentry, inode, name, value, size, flags); 150 + if (size == 0) 151 + value = ""; /* empty EA, do not remove */ 152 + return handler->set(handler, dentry, inode, name, value, size, flags); 143 153 } 144 154 EXPORT_SYMBOL(__vfs_setxattr); 145 155 ··· 176 172 177 173 if (issec) 178 174 inode->i_flags &= ~S_NOSEC; 179 - if (inode->i_op->setxattr) { 175 + if (inode->i_opflags & IOP_XATTR) { 180 176 error = __vfs_setxattr(dentry, inode, name, value, size, flags); 181 177 if (!error) { 182 178 fsnotify_xattr(dentry); ··· 261 257 vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, 262 258 size_t xattr_size, gfp_t flags) 263 259 { 260 + const struct xattr_handler *handler; 264 261 struct inode *inode = dentry->d_inode; 265 262 char *value = *xattr_value; 266 263 int error; ··· 270 265 if (error) 271 266 return error; 272 267 273 - if (!inode->i_op->getxattr) 268 + handler = xattr_resolve_name(inode, &name); 269 + if (IS_ERR(handler)) 270 + return PTR_ERR(handler); 271 + if (!handler->get) 274 272 return -EOPNOTSUPP; 275 - 276 - error = inode->i_op->getxattr(dentry, inode, name, NULL, 0); 273 + error = handler->get(handler, dentry, inode, name, NULL, 0); 277 274 if (error < 0) 278 275 return error; 279 276 ··· 286 279 memset(value, 0, error + 1); 287 280 } 288 281 289 - error = inode->i_op->getxattr(dentry, inode, name, value, error); 282 + error = handler->get(handler, dentry, inode, name, value, error); 290 283 *xattr_value = value; 291 284 return error; 292 285 } ··· 295 288 __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, 296 289 void *value, size_t size) 297 290 { 298 - if (!inode->i_op->getxattr) 291 + const struct xattr_handler *handler; 292 + 293 + handler = xattr_resolve_name(inode, &name); 294 + if (IS_ERR(handler)) 295 + return PTR_ERR(handler); 296 + if (!handler->get) 299 297 return -EOPNOTSUPP; 300 - return inode->i_op->getxattr(dentry, inode, name, value, size); 298 + return handler->get(handler, dentry, inode, name, value, size); 301 299 } 302 300 EXPORT_SYMBOL(__vfs_getxattr); 303 301 ··· 361 349 int 362 350 __vfs_removexattr(struct dentry *dentry, const char *name) 363 351 { 364 - struct inode *inode = dentry->d_inode; 352 + struct inode *inode = d_inode(dentry); 353 + const struct xattr_handler *handler; 365 354 366 - if (!inode->i_op->removexattr) 355 + handler = xattr_resolve_name(inode, &name); 356 + if (IS_ERR(handler)) 357 + return PTR_ERR(handler); 358 + if (!handler->set) 367 359 return -EOPNOTSUPP; 368 - return inode->i_op->removexattr(dentry, name); 360 + return handler->set(handler, dentry, inode, name, NULL, 0, XATTR_REPLACE); 369 361 } 370 362 EXPORT_SYMBOL(__vfs_removexattr); 371 363