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

xattr: simplify listxattr helpers

The generic_listxattr() and simple_xattr_list() helpers list xattrs and
contain duplicated code. Add two helpers that both generic_listxattr()
and simple_xattr_list() can use.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>

+64 -54
+25
fs/posix_acl.c
··· 957 957 } 958 958 EXPORT_SYMBOL(set_posix_acl); 959 959 960 + int posix_acl_listxattr(struct inode *inode, char **buffer, 961 + ssize_t *remaining_size) 962 + { 963 + int err; 964 + 965 + if (!IS_POSIXACL(inode)) 966 + return 0; 967 + 968 + if (inode->i_acl) { 969 + err = xattr_list_one(buffer, remaining_size, 970 + XATTR_NAME_POSIX_ACL_ACCESS); 971 + if (err) 972 + return err; 973 + } 974 + 975 + if (inode->i_default_acl) { 976 + err = xattr_list_one(buffer, remaining_size, 977 + XATTR_NAME_POSIX_ACL_DEFAULT); 978 + if (err) 979 + return err; 980 + } 981 + 982 + return 0; 983 + } 984 + 960 985 static bool 961 986 posix_acl_xattr_list(struct dentry *dentry) 962 987 {
+31 -54
fs/xattr.c
··· 949 949 return error; 950 950 } 951 951 952 + int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name) 953 + { 954 + size_t len; 955 + 956 + len = strlen(name) + 1; 957 + if (*buffer) { 958 + if (*remaining_size < len) 959 + return -ERANGE; 960 + memcpy(*buffer, name, len); 961 + *buffer += len; 962 + } 963 + *remaining_size -= len; 964 + return 0; 965 + } 966 + 952 967 /* 953 968 * Combine the results of the list() operation from every xattr_handler in the 954 969 * list. ··· 972 957 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) 973 958 { 974 959 const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr; 975 - unsigned int size = 0; 960 + ssize_t remaining_size = buffer_size; 961 + int err = 0; 976 962 977 - if (!buffer) { 978 - for_each_xattr_handler(handlers, handler) { 979 - if (!handler->name || 980 - (handler->list && !handler->list(dentry))) 981 - continue; 982 - size += strlen(handler->name) + 1; 983 - } 984 - } else { 985 - char *buf = buffer; 986 - size_t len; 963 + err = posix_acl_listxattr(d_inode(dentry), &buffer, &remaining_size); 964 + if (err) 965 + return err; 987 966 988 - for_each_xattr_handler(handlers, handler) { 989 - if (!handler->name || 990 - (handler->list && !handler->list(dentry))) 991 - continue; 992 - len = strlen(handler->name); 993 - if (len + 1 > buffer_size) 994 - return -ERANGE; 995 - memcpy(buf, handler->name, len + 1); 996 - buf += len + 1; 997 - buffer_size -= len + 1; 998 - } 999 - size = buf - buffer; 967 + for_each_xattr_handler(handlers, handler) { 968 + if (!handler->name || (handler->list && !handler->list(dentry))) 969 + continue; 970 + err = xattr_list_one(&buffer, &remaining_size, handler->name); 971 + if (err) 972 + return err; 1000 973 } 1001 - return size; 974 + 975 + return err ? err : buffer_size - remaining_size; 1002 976 } 1003 977 EXPORT_SYMBOL(generic_listxattr); 1004 978 ··· 1249 1245 return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); 1250 1246 } 1251 1247 1252 - static int xattr_list_one(char **buffer, ssize_t *remaining_size, 1253 - const char *name) 1254 - { 1255 - size_t len = strlen(name) + 1; 1256 - if (*buffer) { 1257 - if (*remaining_size < len) 1258 - return -ERANGE; 1259 - memcpy(*buffer, name, len); 1260 - *buffer += len; 1261 - } 1262 - *remaining_size -= len; 1263 - return 0; 1264 - } 1265 - 1266 1248 /** 1267 1249 * simple_xattr_list - list all xattr objects 1268 1250 * @inode: inode from which to get the xattrs ··· 1277 1287 ssize_t remaining_size = size; 1278 1288 int err = 0; 1279 1289 1280 - #ifdef CONFIG_FS_POSIX_ACL 1281 - if (IS_POSIXACL(inode)) { 1282 - if (inode->i_acl) { 1283 - err = xattr_list_one(&buffer, &remaining_size, 1284 - XATTR_NAME_POSIX_ACL_ACCESS); 1285 - if (err) 1286 - return err; 1287 - } 1288 - if (inode->i_default_acl) { 1289 - err = xattr_list_one(&buffer, &remaining_size, 1290 - XATTR_NAME_POSIX_ACL_DEFAULT); 1291 - if (err) 1292 - return err; 1293 - } 1294 - } 1295 - #endif 1290 + err = posix_acl_listxattr(inode, &buffer, &remaining_size); 1291 + if (err) 1292 + return err; 1296 1293 1297 1294 read_lock(&xattrs->lock); 1298 1295 for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) {
+7
include/linux/posix_acl.h
··· 106 106 struct dentry *dentry, const char *acl_name); 107 107 int vfs_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, 108 108 const char *acl_name); 109 + int posix_acl_listxattr(struct inode *inode, char **buffer, 110 + ssize_t *remaining_size); 109 111 #else 110 112 static inline int posix_acl_chmod(struct mnt_idmap *idmap, 111 113 struct dentry *dentry, umode_t mode) ··· 154 152 struct dentry *dentry, const char *acl_name) 155 153 { 156 154 return -EOPNOTSUPP; 155 + } 156 + static inline int posix_acl_listxattr(struct inode *inode, char **buffer, 157 + ssize_t *remaining_size) 158 + { 159 + return 0; 157 160 } 158 161 #endif /* CONFIG_FS_POSIX_ACL */ 159 162
+1
include/linux/xattr.h
··· 109 109 char *buffer, size_t size); 110 110 void simple_xattr_add(struct simple_xattrs *xattrs, 111 111 struct simple_xattr *new_xattr); 112 + int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name); 112 113 113 114 #endif /* _LINUX_XATTR_H */