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.

fs/proc/task_mmu: factor out proc_maps_private fields used by PROCMAP_QUERY

Refactor struct proc_maps_private so that the fields used by PROCMAP_QUERY
ioctl are moved into a separate structure. In the next patch this allows
ioctl to reuse some of the functions used for reading /proc/pid/maps
without using file->private_data. This prevents concurrent modification
of file->private_data members by ioctl and /proc/pid/maps readers.

The change is pure code refactoring and has no functional changes.

Link: https://lkml.kernel.org/r/20250808152850.2580887-3-surenb@google.com
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: SeongJae Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: David Hildenbrand <david@redhat.com>
Cc: Jann Horn <jannh@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Josef Bacik <josef@toxicpanda.com>
Cc: Kalesh Singh <kaleshsingh@google.com>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: "Paul E . McKenney" <paulmck@kernel.org>
Cc: Peter Xu <peterx@redhat.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Thomas Weißschuh <linux@weissschuh.net>
Cc: T.J. Mercier <tjmercier@google.com>
Cc: Ye Bin <yebin10@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Suren Baghdasaryan and committed by
Andrew Morton
ee737a5a 41f10558

+63 -53
+10 -5
fs/proc/internal.h
··· 378 378 * task_[no]mmu.c 379 379 */ 380 380 struct mem_size_stats; 381 - struct proc_maps_private { 382 - struct inode *inode; 383 - struct task_struct *task; 381 + 382 + struct proc_maps_locking_ctx { 384 383 struct mm_struct *mm; 385 - struct vma_iterator iter; 386 - loff_t last_pos; 387 384 #ifdef CONFIG_PER_VMA_LOCK 388 385 bool mmap_locked; 389 386 struct vm_area_struct *locked_vma; 390 387 #endif 388 + }; 389 + 390 + struct proc_maps_private { 391 + struct inode *inode; 392 + struct task_struct *task; 393 + struct vma_iterator iter; 394 + loff_t last_pos; 395 + struct proc_maps_locking_ctx lock_ctx; 391 396 #ifdef CONFIG_NUMA 392 397 struct mempolicy *task_mempolicy; 393 398 #endif
+46 -41
fs/proc/task_mmu.c
··· 132 132 133 133 #ifdef CONFIG_PER_VMA_LOCK 134 134 135 - static void unlock_vma(struct proc_maps_private *priv) 135 + static void unlock_ctx_vma(struct proc_maps_locking_ctx *lock_ctx) 136 136 { 137 - if (priv->locked_vma) { 138 - vma_end_read(priv->locked_vma); 139 - priv->locked_vma = NULL; 137 + if (lock_ctx->locked_vma) { 138 + vma_end_read(lock_ctx->locked_vma); 139 + lock_ctx->locked_vma = NULL; 140 140 } 141 141 } 142 142 143 143 static const struct seq_operations proc_pid_maps_op; 144 144 145 145 static inline bool lock_vma_range(struct seq_file *m, 146 - struct proc_maps_private *priv) 146 + struct proc_maps_locking_ctx *lock_ctx) 147 147 { 148 148 /* 149 149 * smaps and numa_maps perform page table walk, therefore require ··· 151 151 * walking the vma tree under rcu read protection. 152 152 */ 153 153 if (m->op != &proc_pid_maps_op) { 154 - if (mmap_read_lock_killable(priv->mm)) 154 + if (mmap_read_lock_killable(lock_ctx->mm)) 155 155 return false; 156 156 157 - priv->mmap_locked = true; 157 + lock_ctx->mmap_locked = true; 158 158 } else { 159 159 rcu_read_lock(); 160 - priv->locked_vma = NULL; 161 - priv->mmap_locked = false; 160 + lock_ctx->locked_vma = NULL; 161 + lock_ctx->mmap_locked = false; 162 162 } 163 163 164 164 return true; 165 165 } 166 166 167 - static inline void unlock_vma_range(struct proc_maps_private *priv) 167 + static inline void unlock_vma_range(struct proc_maps_locking_ctx *lock_ctx) 168 168 { 169 - if (priv->mmap_locked) { 170 - mmap_read_unlock(priv->mm); 169 + if (lock_ctx->mmap_locked) { 170 + mmap_read_unlock(lock_ctx->mm); 171 171 } else { 172 - unlock_vma(priv); 172 + unlock_ctx_vma(lock_ctx); 173 173 rcu_read_unlock(); 174 174 } 175 175 } ··· 177 177 static struct vm_area_struct *get_next_vma(struct proc_maps_private *priv, 178 178 loff_t last_pos) 179 179 { 180 + struct proc_maps_locking_ctx *lock_ctx = &priv->lock_ctx; 180 181 struct vm_area_struct *vma; 181 182 182 - if (priv->mmap_locked) 183 + if (lock_ctx->mmap_locked) 183 184 return vma_next(&priv->iter); 184 185 185 - unlock_vma(priv); 186 - vma = lock_next_vma(priv->mm, &priv->iter, last_pos); 186 + unlock_ctx_vma(lock_ctx); 187 + vma = lock_next_vma(lock_ctx->mm, &priv->iter, last_pos); 187 188 if (!IS_ERR_OR_NULL(vma)) 188 - priv->locked_vma = vma; 189 + lock_ctx->locked_vma = vma; 189 190 190 191 return vma; 191 192 } ··· 194 193 static inline bool fallback_to_mmap_lock(struct proc_maps_private *priv, 195 194 loff_t pos) 196 195 { 197 - if (priv->mmap_locked) 196 + struct proc_maps_locking_ctx *lock_ctx = &priv->lock_ctx; 197 + 198 + if (lock_ctx->mmap_locked) 198 199 return false; 199 200 200 201 rcu_read_unlock(); 201 - mmap_read_lock(priv->mm); 202 + mmap_read_lock(lock_ctx->mm); 202 203 /* Reinitialize the iterator after taking mmap_lock */ 203 204 vma_iter_set(&priv->iter, pos); 204 - priv->mmap_locked = true; 205 + lock_ctx->mmap_locked = true; 205 206 206 207 return true; 207 208 } ··· 211 208 #else /* CONFIG_PER_VMA_LOCK */ 212 209 213 210 static inline bool lock_vma_range(struct seq_file *m, 214 - struct proc_maps_private *priv) 211 + struct proc_maps_locking_ctx *lock_ctx) 215 212 { 216 - return mmap_read_lock_killable(priv->mm) == 0; 213 + return mmap_read_lock_killable(lock_ctx->mm) == 0; 217 214 } 218 215 219 - static inline void unlock_vma_range(struct proc_maps_private *priv) 216 + static inline void unlock_vma_range(struct proc_maps_locking_ctx *lock_ctx) 220 217 { 221 - mmap_read_unlock(priv->mm); 218 + mmap_read_unlock(lock_ctx->mm); 222 219 } 223 220 224 221 static struct vm_area_struct *get_next_vma(struct proc_maps_private *priv, ··· 261 258 *ppos = vma->vm_end; 262 259 } else { 263 260 *ppos = SENTINEL_VMA_GATE; 264 - vma = get_gate_vma(priv->mm); 261 + vma = get_gate_vma(priv->lock_ctx.mm); 265 262 } 266 263 267 264 return vma; ··· 270 267 static void *m_start(struct seq_file *m, loff_t *ppos) 271 268 { 272 269 struct proc_maps_private *priv = m->private; 270 + struct proc_maps_locking_ctx *lock_ctx; 273 271 loff_t last_addr = *ppos; 274 272 struct mm_struct *mm; 275 273 ··· 282 278 if (!priv->task) 283 279 return ERR_PTR(-ESRCH); 284 280 285 - mm = priv->mm; 281 + lock_ctx = &priv->lock_ctx; 282 + mm = lock_ctx->mm; 286 283 if (!mm || !mmget_not_zero(mm)) { 287 284 put_task_struct(priv->task); 288 285 priv->task = NULL; 289 286 return NULL; 290 287 } 291 288 292 - if (!lock_vma_range(m, priv)) { 289 + if (!lock_vma_range(m, lock_ctx)) { 293 290 mmput(mm); 294 291 put_task_struct(priv->task); 295 292 priv->task = NULL; ··· 323 318 static void m_stop(struct seq_file *m, void *v) 324 319 { 325 320 struct proc_maps_private *priv = m->private; 326 - struct mm_struct *mm = priv->mm; 321 + struct mm_struct *mm = priv->lock_ctx.mm; 327 322 328 323 if (!priv->task) 329 324 return; 330 325 331 326 release_task_mempolicy(priv); 332 - unlock_vma_range(priv); 327 + unlock_vma_range(&priv->lock_ctx); 333 328 mmput(mm); 334 329 put_task_struct(priv->task); 335 330 priv->task = NULL; ··· 344 339 return -ENOMEM; 345 340 346 341 priv->inode = inode; 347 - priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); 348 - if (IS_ERR(priv->mm)) { 349 - int err = PTR_ERR(priv->mm); 342 + priv->lock_ctx.mm = proc_mem_open(inode, PTRACE_MODE_READ); 343 + if (IS_ERR(priv->lock_ctx.mm)) { 344 + int err = PTR_ERR(priv->lock_ctx.mm); 350 345 351 346 seq_release_private(inode, file); 352 347 return err; ··· 360 355 struct seq_file *seq = file->private_data; 361 356 struct proc_maps_private *priv = seq->private; 362 357 363 - if (priv->mm) 364 - mmdrop(priv->mm); 358 + if (priv->lock_ctx.mm) 359 + mmdrop(priv->lock_ctx.mm); 365 360 366 361 return seq_release_private(inode, file); 367 362 } ··· 615 610 if (!!karg.build_id_size != !!karg.build_id_addr) 616 611 return -EINVAL; 617 612 618 - mm = priv->mm; 613 + mm = priv->lock_ctx.mm; 619 614 if (!mm || !mmget_not_zero(mm)) 620 615 return -ESRCH; 621 616 ··· 1316 1311 { 1317 1312 struct proc_maps_private *priv = m->private; 1318 1313 struct mem_size_stats mss = {}; 1319 - struct mm_struct *mm = priv->mm; 1314 + struct mm_struct *mm = priv->lock_ctx.mm; 1320 1315 struct vm_area_struct *vma; 1321 1316 unsigned long vma_start = 0, last_vma_end = 0; 1322 1317 int ret = 0; ··· 1461 1456 goto out_free; 1462 1457 1463 1458 priv->inode = inode; 1464 - priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); 1465 - if (IS_ERR_OR_NULL(priv->mm)) { 1466 - ret = priv->mm ? PTR_ERR(priv->mm) : -ESRCH; 1459 + priv->lock_ctx.mm = proc_mem_open(inode, PTRACE_MODE_READ); 1460 + if (IS_ERR_OR_NULL(priv->lock_ctx.mm)) { 1461 + ret = priv->lock_ctx.mm ? PTR_ERR(priv->lock_ctx.mm) : -ESRCH; 1467 1462 1468 1463 single_release(inode, file); 1469 1464 goto out_free; ··· 1481 1476 struct seq_file *seq = file->private_data; 1482 1477 struct proc_maps_private *priv = seq->private; 1483 1478 1484 - if (priv->mm) 1485 - mmdrop(priv->mm); 1479 + if (priv->lock_ctx.mm) 1480 + mmdrop(priv->lock_ctx.mm); 1486 1481 1487 1482 kfree(priv); 1488 1483 return single_release(inode, file);
+7 -7
fs/proc/task_nommu.c
··· 204 204 if (!priv->task) 205 205 return ERR_PTR(-ESRCH); 206 206 207 - mm = priv->mm; 207 + mm = priv->lock_ctx.mm; 208 208 if (!mm || !mmget_not_zero(mm)) { 209 209 put_task_struct(priv->task); 210 210 priv->task = NULL; ··· 226 226 static void m_stop(struct seq_file *m, void *v) 227 227 { 228 228 struct proc_maps_private *priv = m->private; 229 - struct mm_struct *mm = priv->mm; 229 + struct mm_struct *mm = priv->lock_ctx.mm; 230 230 231 231 if (!priv->task) 232 232 return; ··· 259 259 return -ENOMEM; 260 260 261 261 priv->inode = inode; 262 - priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); 263 - if (IS_ERR_OR_NULL(priv->mm)) { 264 - int err = priv->mm ? PTR_ERR(priv->mm) : -ESRCH; 262 + priv->lock_ctx.mm = proc_mem_open(inode, PTRACE_MODE_READ); 263 + if (IS_ERR_OR_NULL(priv->lock_ctx.mm)) { 264 + int err = priv->lock_ctx.mm ? PTR_ERR(priv->lock_ctx.mm) : -ESRCH; 265 265 266 266 seq_release_private(inode, file); 267 267 return err; ··· 276 276 struct seq_file *seq = file->private_data; 277 277 struct proc_maps_private *priv = seq->private; 278 278 279 - if (priv->mm) 280 - mmdrop(priv->mm); 279 + if (priv->lock_ctx.mm) 280 + mmdrop(priv->lock_ctx.mm); 281 281 282 282 return seq_release_private(inode, file); 283 283 }