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

Configure Feed

Select the types of activity you want to include in your feed.

pidfs: adapt to rhashtable-based simple_xattrs

Adapt pidfs to use the rhashtable-based xattr path by switching from a
dedicated slab cache to simple_xattrs_alloc().

Previously pidfs used a custom kmem_cache (pidfs_xattr_cachep) that
allocated a struct containing an embedded simple_xattrs plus
simple_xattrs_init(). Replace this with simple_xattrs_alloc() which
combines kzalloc + rhashtable_init, and drop the dedicated slab cache
entirely.

Use simple_xattr_free_rcu() for replaced xattr entries to allow
concurrent RCU readers to finish.

Link: https://patch.msgid.link/20260216-work-xattr-socket-v1-5-c2efa4f74cb7@kernel.org
Acked-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>

+40 -24
+40 -24
fs/pidfs.c
··· 22 22 #include <net/net_namespace.h> 23 23 #include <linux/coredump.h> 24 24 #include <linux/rhashtable.h> 25 + #include <linux/llist.h> 25 26 #include <linux/xattr.h> 26 27 #include <linux/cookie.h> 27 28 ··· 32 31 #define PIDFS_PID_DEAD ERR_PTR(-ESRCH) 33 32 34 33 static struct kmem_cache *pidfs_attr_cachep __ro_after_init; 35 - static struct kmem_cache *pidfs_xattr_cachep __ro_after_init; 36 34 37 35 static struct path pidfs_root_path = {}; 38 36 ··· 46 46 PIDFS_ATTR_BIT_COREDUMP = 1, 47 47 }; 48 48 49 - struct pidfs_attr { 49 + struct pidfs_anon_attr { 50 50 unsigned long attr_mask; 51 - struct simple_xattrs *xattrs; 52 51 struct /* exit info */ { 53 52 __u64 cgroupid; 54 53 __s32 exit_code; ··· 92 93 * inode number and the inode generation number to compare or 93 94 * use file handles. 94 95 */ 96 + struct pidfs_attr { 97 + struct simple_xattrs *xattrs; 98 + union { 99 + struct pidfs_anon_attr; 100 + struct llist_node pidfs_llist; 101 + }; 102 + }; 95 103 96 104 #if BITS_PER_LONG == 32 97 105 ··· 184 178 pidfs_ino_ht_params); 185 179 } 186 180 181 + static LLIST_HEAD(pidfs_free_list); 182 + 183 + static void pidfs_free_attr_work(struct work_struct *work) 184 + { 185 + struct pidfs_attr *attr, *next; 186 + struct llist_node *head; 187 + 188 + head = llist_del_all(&pidfs_free_list); 189 + llist_for_each_entry_safe(attr, next, head, pidfs_llist) { 190 + struct simple_xattrs *xattrs = attr->xattrs; 191 + 192 + if (xattrs) { 193 + simple_xattrs_free(xattrs, NULL); 194 + kfree(xattrs); 195 + } 196 + kfree(attr); 197 + } 198 + } 199 + 200 + static DECLARE_WORK(pidfs_free_work, pidfs_free_attr_work); 201 + 187 202 void pidfs_free_pid(struct pid *pid) 188 203 { 189 - struct pidfs_attr *attr __free(kfree) = no_free_ptr(pid->attr); 190 - struct simple_xattrs *xattrs __free(kfree) = NULL; 204 + struct pidfs_attr *attr = pid->attr; 191 205 192 206 /* 193 207 * Any dentry must've been wiped from the pid by now. ··· 226 200 if (IS_ERR(attr)) 227 201 return; 228 202 229 - xattrs = no_free_ptr(attr->xattrs); 230 - if (xattrs) 231 - simple_xattrs_free(xattrs, NULL); 203 + if (likely(!attr->xattrs)) 204 + kfree(attr); 205 + else if (llist_add(&attr->pidfs_llist, &pidfs_free_list)) 206 + schedule_work(&pidfs_free_work); 232 207 } 233 208 234 209 #ifdef CONFIG_PROC_FS ··· 1038 1011 1039 1012 xattrs = READ_ONCE(attr->xattrs); 1040 1013 if (!xattrs) 1041 - return 0; 1014 + return -ENODATA; 1042 1015 1043 1016 name = xattr_full_name(handler, suffix); 1044 1017 return simple_xattr_get(xattrs, name, value, size); ··· 1058 1031 /* Ensure we're the only one to set @attr->xattrs. */ 1059 1032 WARN_ON_ONCE(!inode_is_locked(inode)); 1060 1033 1061 - xattrs = READ_ONCE(attr->xattrs); 1062 - if (!xattrs) { 1063 - xattrs = kmem_cache_zalloc(pidfs_xattr_cachep, GFP_KERNEL); 1064 - if (!xattrs) 1065 - return -ENOMEM; 1066 - 1067 - simple_xattrs_init(xattrs); 1068 - smp_store_release(&pid->attr->xattrs, xattrs); 1069 - } 1034 + xattrs = simple_xattrs_lazy_alloc(&attr->xattrs, value, flags); 1035 + if (IS_ERR_OR_NULL(xattrs)) 1036 + return PTR_ERR(xattrs); 1070 1037 1071 1038 name = xattr_full_name(handler, suffix); 1072 1039 old_xattr = simple_xattr_set(xattrs, name, value, size, flags); 1073 1040 if (IS_ERR(old_xattr)) 1074 1041 return PTR_ERR(old_xattr); 1075 1042 1076 - simple_xattr_free(old_xattr); 1043 + simple_xattr_free_rcu(old_xattr); 1077 1044 return 0; 1078 1045 } 1079 1046 ··· 1144 1123 pidfs_attr_cachep = kmem_cache_create("pidfs_attr_cache", sizeof(struct pidfs_attr), 0, 1145 1124 (SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT | 1146 1125 SLAB_ACCOUNT | SLAB_PANIC), NULL); 1147 - 1148 - pidfs_xattr_cachep = kmem_cache_create("pidfs_xattr_cache", 1149 - sizeof(struct simple_xattrs), 0, 1150 - (SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT | 1151 - SLAB_ACCOUNT | SLAB_PANIC), NULL); 1152 1126 1153 1127 pidfs_mnt = kern_mount(&pidfs_type); 1154 1128 if (IS_ERR(pidfs_mnt))