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.

Merge patch series "ns: rework reference counting"

Christian Brauner <brauner@kernel.org> says:

Stop open accesses to the reference counts and cargo-culting the same
code in all namespace. Use a set of dedicated helpers and make the
actual count private.

* patches from https://lore.kernel.org/20250918-work-namespace-ns_ref-v1-0-1b0a98ee041e@kernel.org:
ns: rename to __ns_ref
nsfs: port to ns_ref_*() helpers
net: port to ns_ref_*() helpers
uts: port to ns_ref_*() helpers
ipv4: use check_net()
net: use check_net()
net-sysfs: use check_net()
user: port to ns_ref_*() helpers
time: port to ns_ref_*() helpers
pid: port to ns_ref_*() helpers
ipc: port to ns_ref_*() helpers
cgroup: port to ns_ref_*() helpers
mnt: port to ns_ref_*() helpers
ns: add reference count helpers

Signed-off-by: Christian Brauner <brauner@kernel.org>

+74 -49
+1 -1
fs/mount.h
··· 143 143 144 144 static inline void get_mnt_ns(struct mnt_namespace *ns) 145 145 { 146 - refcount_inc(&ns->ns.count); 146 + ns_ref_inc(ns); 147 147 } 148 148 149 149 extern seqlock_t mount_lock;
+3 -3
fs/namespace.c
··· 2110 2110 * the mount namespace and it might already be on its 2111 2111 * deathbed. 2112 2112 */ 2113 - if (!refcount_inc_not_zero(&mntns->ns.count)) 2113 + if (!ns_ref_get(mntns)) 2114 2114 continue; 2115 2115 2116 2116 return mntns; ··· 6015 6015 .ns.inum = PROC_MNT_INIT_INO, 6016 6016 .ns.ops = &mntns_operations, 6017 6017 .user_ns = &init_user_ns, 6018 - .ns.count = REFCOUNT_INIT(1), 6018 + .ns.__ns_ref = REFCOUNT_INIT(1), 6019 6019 .passive = REFCOUNT_INIT(1), 6020 6020 .mounts = RB_ROOT, 6021 6021 .poll = __WAIT_QUEUE_HEAD_INITIALIZER(init_mnt_ns.poll), ··· 6084 6084 6085 6085 void put_mnt_ns(struct mnt_namespace *ns) 6086 6086 { 6087 - if (!refcount_dec_and_test(&ns->ns.count)) 6087 + if (!ns_ref_put(ns)) 6088 6088 return; 6089 6089 namespace_lock(); 6090 6090 emptied_ns = ns;
+1 -1
fs/nsfs.c
··· 492 492 VFS_WARN_ON_ONCE(ns->ops->type != fid->ns_type); 493 493 VFS_WARN_ON_ONCE(ns->inum != fid->ns_inum); 494 494 495 - if (!refcount_inc_not_zero(&ns->count)) 495 + if (!__ns_ref_get(ns)) 496 496 return NULL; 497 497 } 498 498
+2 -2
include/linux/cgroup_namespace.h
··· 29 29 30 30 static inline void get_cgroup_ns(struct cgroup_namespace *ns) 31 31 { 32 - refcount_inc(&ns->ns.count); 32 + ns_ref_inc(ns); 33 33 } 34 34 35 35 static inline void put_cgroup_ns(struct cgroup_namespace *ns) 36 36 { 37 - if (refcount_dec_and_test(&ns->ns.count)) 37 + if (ns_ref_put(ns)) 38 38 free_cgroup_ns(ns); 39 39 } 40 40
+2 -2
include/linux/ipc_namespace.h
··· 140 140 static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns) 141 141 { 142 142 if (ns) 143 - refcount_inc(&ns->ns.count); 143 + ns_ref_inc(ns); 144 144 return ns; 145 145 } 146 146 147 147 static inline struct ipc_namespace *get_ipc_ns_not_zero(struct ipc_namespace *ns) 148 148 { 149 149 if (ns) { 150 - if (refcount_inc_not_zero(&ns->ns.count)) 150 + if (ns_ref_get(ns)) 151 151 return ns; 152 152 } 153 153
+36 -11
include/linux/ns_common.h
··· 29 29 struct dentry *stashed; 30 30 const struct proc_ns_operations *ops; 31 31 unsigned int inum; 32 - refcount_t count; 32 + refcount_t __ns_ref; /* do not use directly */ 33 33 union { 34 34 struct { 35 35 u64 ns_id; ··· 43 43 int __ns_common_init(struct ns_common *ns, const struct proc_ns_operations *ops, int inum); 44 44 void __ns_common_free(struct ns_common *ns); 45 45 46 - #define to_ns_common(__ns) \ 47 - _Generic((__ns), \ 48 - struct cgroup_namespace *: &(__ns)->ns, \ 49 - struct ipc_namespace *: &(__ns)->ns, \ 50 - struct mnt_namespace *: &(__ns)->ns, \ 51 - struct net *: &(__ns)->ns, \ 52 - struct pid_namespace *: &(__ns)->ns, \ 53 - struct time_namespace *: &(__ns)->ns, \ 54 - struct user_namespace *: &(__ns)->ns, \ 55 - struct uts_namespace *: &(__ns)->ns) 46 + #define to_ns_common(__ns) \ 47 + _Generic((__ns), \ 48 + struct cgroup_namespace *: &(__ns)->ns, \ 49 + const struct cgroup_namespace *: &(__ns)->ns, \ 50 + struct ipc_namespace *: &(__ns)->ns, \ 51 + const struct ipc_namespace *: &(__ns)->ns, \ 52 + struct mnt_namespace *: &(__ns)->ns, \ 53 + const struct mnt_namespace *: &(__ns)->ns, \ 54 + struct net *: &(__ns)->ns, \ 55 + const struct net *: &(__ns)->ns, \ 56 + struct pid_namespace *: &(__ns)->ns, \ 57 + const struct pid_namespace *: &(__ns)->ns, \ 58 + struct time_namespace *: &(__ns)->ns, \ 59 + const struct time_namespace *: &(__ns)->ns, \ 60 + struct user_namespace *: &(__ns)->ns, \ 61 + const struct user_namespace *: &(__ns)->ns, \ 62 + struct uts_namespace *: &(__ns)->ns, \ 63 + const struct uts_namespace *: &(__ns)->ns) 56 64 57 65 #define ns_init_inum(__ns) \ 58 66 _Generic((__ns), \ ··· 90 82 #define ns_common_init_inum(__ns, __ops, __inum) __ns_common_init(to_ns_common(__ns), __ops, __inum) 91 83 92 84 #define ns_common_free(__ns) __ns_common_free(to_ns_common((__ns))) 85 + 86 + static __always_inline __must_check bool __ns_ref_put(struct ns_common *ns) 87 + { 88 + return refcount_dec_and_test(&ns->__ns_ref); 89 + } 90 + 91 + static __always_inline __must_check bool __ns_ref_get(struct ns_common *ns) 92 + { 93 + return refcount_inc_not_zero(&ns->__ns_ref); 94 + } 95 + 96 + #define ns_ref_read(__ns) refcount_read(&to_ns_common((__ns))->__ns_ref) 97 + #define ns_ref_inc(__ns) refcount_inc(&to_ns_common((__ns))->__ns_ref) 98 + #define ns_ref_get(__ns) __ns_ref_get(to_ns_common((__ns))) 99 + #define ns_ref_put(__ns) __ns_ref_put(to_ns_common((__ns))) 100 + #define ns_ref_put_and_lock(__ns, __lock) \ 101 + refcount_dec_and_lock(&to_ns_common((__ns))->__ns_ref, (__lock)) 93 102 94 103 #endif
+1 -1
include/linux/pid_namespace.h
··· 62 62 static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns) 63 63 { 64 64 if (ns != &init_pid_ns) 65 - refcount_inc(&ns->ns.count); 65 + ns_ref_inc(ns); 66 66 return ns; 67 67 } 68 68
+2 -2
include/linux/time_namespace.h
··· 44 44 45 45 static inline struct time_namespace *get_time_ns(struct time_namespace *ns) 46 46 { 47 - refcount_inc(&ns->ns.count); 47 + ns_ref_inc(ns); 48 48 return ns; 49 49 } 50 50 ··· 57 57 58 58 static inline void put_time_ns(struct time_namespace *ns) 59 59 { 60 - if (refcount_dec_and_test(&ns->ns.count)) 60 + if (ns_ref_put(ns)) 61 61 free_time_ns(ns); 62 62 } 63 63
+2 -2
include/linux/user_namespace.h
··· 176 176 static inline struct user_namespace *get_user_ns(struct user_namespace *ns) 177 177 { 178 178 if (ns) 179 - refcount_inc(&ns->ns.count); 179 + ns_ref_inc(ns); 180 180 return ns; 181 181 } 182 182 ··· 186 186 187 187 static inline void put_user_ns(struct user_namespace *ns) 188 188 { 189 - if (ns && refcount_dec_and_test(&ns->ns.count)) 189 + if (ns && ns_ref_put(ns)) 190 190 __put_user_ns(ns); 191 191 } 192 192
+2 -2
include/linux/uts_namespace.h
··· 25 25 26 26 static inline void get_uts_ns(struct uts_namespace *ns) 27 27 { 28 - refcount_inc(&ns->ns.count); 28 + ns_ref_inc(ns); 29 29 } 30 30 31 31 extern struct uts_namespace *copy_utsname(unsigned long flags, ··· 34 34 35 35 static inline void put_uts_ns(struct uts_namespace *ns) 36 36 { 37 - if (refcount_dec_and_test(&ns->ns.count)) 37 + if (ns_ref_put(ns)) 38 38 free_uts_ns(ns); 39 39 } 40 40
+4 -4
include/net/net_namespace.h
··· 270 270 /* Try using get_net_track() instead */ 271 271 static inline struct net *get_net(struct net *net) 272 272 { 273 - refcount_inc(&net->ns.count); 273 + ns_ref_inc(net); 274 274 return net; 275 275 } 276 276 ··· 281 281 * exists. If the reference count is zero this 282 282 * function fails and returns NULL. 283 283 */ 284 - if (!refcount_inc_not_zero(&net->ns.count)) 284 + if (!ns_ref_get(net)) 285 285 net = NULL; 286 286 return net; 287 287 } ··· 289 289 /* Try using put_net_track() instead */ 290 290 static inline void put_net(struct net *net) 291 291 { 292 - if (refcount_dec_and_test(&net->ns.count)) 292 + if (ns_ref_put(net)) 293 293 __put_net(net); 294 294 } 295 295 ··· 301 301 302 302 static inline int check_net(const struct net *net) 303 303 { 304 - return refcount_read(&net->ns.count) != 0; 304 + return ns_ref_read(net) != 0; 305 305 } 306 306 307 307 void net_drop_ns(void *);
+1 -1
init/version-timestamp.c
··· 8 8 #include <linux/utsname.h> 9 9 10 10 struct uts_namespace init_uts_ns = { 11 - .ns.count = REFCOUNT_INIT(2), 11 + .ns.__ns_ref = REFCOUNT_INIT(2), 12 12 .name = { 13 13 .sysname = UTS_SYSNAME, 14 14 .nodename = UTS_NODENAME,
+1 -1
ipc/msgutil.c
··· 27 27 * and not CONFIG_IPC_NS. 28 28 */ 29 29 struct ipc_namespace init_ipc_ns = { 30 - .ns.count = REFCOUNT_INIT(1), 30 + .ns.__ns_ref = REFCOUNT_INIT(1), 31 31 .user_ns = &init_user_ns, 32 32 .ns.inum = PROC_IPC_INIT_INO, 33 33 #ifdef CONFIG_IPC_NS
+1 -1
ipc/namespace.c
··· 199 199 */ 200 200 void put_ipc_ns(struct ipc_namespace *ns) 201 201 { 202 - if (refcount_dec_and_lock(&ns->ns.count, &mq_lock)) { 202 + if (ns_ref_put_and_lock(ns, &mq_lock)) { 203 203 mq_clear_sbinfo(ns); 204 204 spin_unlock(&mq_lock); 205 205
+1 -1
kernel/cgroup/cgroup.c
··· 219 219 220 220 /* cgroup namespace for init task */ 221 221 struct cgroup_namespace init_cgroup_ns = { 222 - .ns.count = REFCOUNT_INIT(2), 222 + .ns.__ns_ref = REFCOUNT_INIT(2), 223 223 .user_ns = &init_user_ns, 224 224 .ns.ops = &cgroupns_operations, 225 225 .ns.inum = PROC_CGROUP_INIT_INO,
+1 -1
kernel/nscommon.c
··· 5 5 6 6 int __ns_common_init(struct ns_common *ns, const struct proc_ns_operations *ops, int inum) 7 7 { 8 - refcount_set(&ns->count, 1); 8 + refcount_set(&ns->__ns_ref, 1); 9 9 ns->stashed = NULL; 10 10 ns->ops = ops; 11 11 ns->ns_id = 0;
+1 -1
kernel/pid.c
··· 71 71 * the scheme scales to up to 4 million PIDs, runtime. 72 72 */ 73 73 struct pid_namespace init_pid_ns = { 74 - .ns.count = REFCOUNT_INIT(2), 74 + .ns.__ns_ref = REFCOUNT_INIT(2), 75 75 .idr = IDR_INIT(init_pid_ns.idr), 76 76 .pid_allocated = PIDNS_ADDING, 77 77 .level = 0,
+2 -2
kernel/pid_namespace.c
··· 169 169 parent = ns->parent; 170 170 destroy_pid_namespace(ns); 171 171 ns = parent; 172 - } while (ns != &init_pid_ns && refcount_dec_and_test(&ns->ns.count)); 172 + } while (ns != &init_pid_ns && ns_ref_put(ns)); 173 173 } 174 174 175 175 struct pid_namespace *copy_pid_ns(unsigned long flags, ··· 184 184 185 185 void put_pid_ns(struct pid_namespace *ns) 186 186 { 187 - if (ns && ns != &init_pid_ns && refcount_dec_and_test(&ns->ns.count)) 187 + if (ns && ns != &init_pid_ns && ns_ref_put(ns)) 188 188 schedule_work(&ns->work); 189 189 } 190 190 EXPORT_SYMBOL_GPL(put_pid_ns);
+1 -1
kernel/time/namespace.c
··· 480 480 }; 481 481 482 482 struct time_namespace init_time_ns = { 483 - .ns.count = REFCOUNT_INIT(3), 483 + .ns.__ns_ref = REFCOUNT_INIT(3), 484 484 .user_ns = &init_user_ns, 485 485 .ns.inum = PROC_TIME_INIT_INO, 486 486 .ns.ops = &timens_operations,
+1 -1
kernel/user.c
··· 65 65 .nr_extents = 1, 66 66 }, 67 67 }, 68 - .ns.count = REFCOUNT_INIT(3), 68 + .ns.__ns_ref = REFCOUNT_INIT(3), 69 69 .owner = GLOBAL_ROOT_UID, 70 70 .group = GLOBAL_ROOT_GID, 71 71 .ns.inum = PROC_USER_INIT_INO,
+1 -1
kernel/user_namespace.c
··· 225 225 kfree_rcu(ns, ns.ns_rcu); 226 226 dec_user_namespaces(ucounts); 227 227 ns = parent; 228 - } while (refcount_dec_and_test(&parent->ns.count)); 228 + } while (ns_ref_put(parent)); 229 229 } 230 230 231 231 void __put_user_ns(struct user_namespace *ns)
+3 -3
net/core/net-sysfs.c
··· 1328 1328 struct netdev_rx_queue *queue = &dev->_rx[i]; 1329 1329 struct kobject *kobj = &queue->kobj; 1330 1330 1331 - if (!refcount_read(&dev_net(dev)->ns.count)) 1331 + if (!check_net(dev_net(dev))) 1332 1332 kobj->uevent_suppress = 1; 1333 1333 if (dev->sysfs_rx_queue_group) 1334 1334 sysfs_remove_group(kobj, dev->sysfs_rx_queue_group); ··· 2061 2061 while (--i >= new_num) { 2062 2062 struct netdev_queue *queue = dev->_tx + i; 2063 2063 2064 - if (!refcount_read(&dev_net(dev)->ns.count)) 2064 + if (!check_net(dev_net(dev))) 2065 2065 queue->kobj.uevent_suppress = 1; 2066 2066 2067 2067 if (netdev_uses_bql(dev)) ··· 2315 2315 { 2316 2316 struct device *dev = &ndev->dev; 2317 2317 2318 - if (!refcount_read(&dev_net(ndev)->ns.count)) 2318 + if (!check_net(dev_net(ndev))) 2319 2319 dev_set_uevent_suppress(dev, 1); 2320 2320 2321 2321 kobject_get(&dev->kobj);
+1 -1
net/core/net_namespace.c
··· 315 315 { 316 316 int id; 317 317 318 - if (refcount_read(&net->ns.count) == 0) 318 + if (!check_net(net)) 319 319 return NETNSA_NSID_NOT_ASSIGNED; 320 320 321 321 spin_lock(&net->nsid_lock);
+2 -2
net/ipv4/inet_timewait_sock.c
··· 329 329 TCPF_NEW_SYN_RECV)) 330 330 continue; 331 331 332 - if (refcount_read(&sock_net(sk)->ns.count)) 332 + if (check_net(sock_net(sk))) 333 333 continue; 334 334 335 335 if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt))) 336 336 continue; 337 337 338 - if (refcount_read(&sock_net(sk)->ns.count)) { 338 + if (check_net(sock_net(sk))) { 339 339 sock_gen_put(sk); 340 340 goto restart; 341 341 }
+1 -1
net/ipv4/tcp_metrics.c
··· 912 912 spin_lock_bh(&tcp_metrics_lock); 913 913 for (tm = deref_locked(*pp); tm; tm = deref_locked(*pp)) { 914 914 match = net ? net_eq(tm_net(tm), net) : 915 - !refcount_read(&tm_net(tm)->ns.count); 915 + !check_net(tm_net(tm)); 916 916 if (match) { 917 917 rcu_assign_pointer(*pp, tm->tcpm_next); 918 918 kfree_rcu(tm, rcu_head);