| From: Alexey Dobriyan <adobriyan@gmail.com> |
| Subject: proc: add some (hopefully) insightful comments |
| Date: Sat, 23 Jul 2022 20:09:07 +0300 |
| |
| * /proc/${pid}/net status |
| * removing PDE vs last close stuff (again!) |
| * random small stuff |
| |
| Link: https://lkml.kernel.org/r/YtwrM6sDC0OQ53YB@localhost.localdomain |
| Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| fs/proc/array.c | 4 ++++ |
| fs/proc/inode.c | 17 ++++++++++++----- |
| fs/proc/proc_net.c | 6 ++++++ |
| fs/proc/root.c | 5 +++++ |
| 4 files changed, 27 insertions(+), 5 deletions(-) |
| |
| --- a/fs/proc/array.c~proc-add-some-hopefully-insightful-comments |
| +++ a/fs/proc/array.c |
| @@ -99,6 +99,10 @@ void proc_task_name(struct seq_file *m, |
| { |
| char tcomm[64]; |
| |
| + /* |
| + * Test before PF_KTHREAD because all workqueue worker threads are |
| + * kernel threads. |
| + */ |
| if (p->flags & PF_WQ_WORKER) |
| wq_worker_comm(tcomm, sizeof(tcomm), p); |
| else if (p->flags & PF_KTHREAD) |
| --- a/fs/proc/inode.c~proc-add-some-hopefully-insightful-comments |
| +++ a/fs/proc/inode.c |
| @@ -212,7 +212,15 @@ static void unuse_pde(struct proc_dir_en |
| complete(pde->pde_unload_completion); |
| } |
| |
| -/* pde is locked on entry, unlocked on exit */ |
| +/* |
| + * At most 2 contexts can enter this function: the one doing the last |
| + * close on the descriptor and whoever is deleting PDE itself. |
| + * |
| + * First to enter calls ->proc_release hook and signals its completion |
| + * to the second one which waits and then does nothing. |
| + * |
| + * PDE is locked on entry, unlocked on exit. |
| + */ |
| static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo) |
| __releases(&pde->pde_unload_lock) |
| { |
| @@ -222,9 +230,6 @@ static void close_pdeo(struct proc_dir_e |
| * |
| * rmmod (remove_proc_entry() et al) can't delete an entry and proceed: |
| * "struct file" needs to be available at the right moment. |
| - * |
| - * Therefore, first process to enter this function does ->release() and |
| - * signals its completion to the other process which does nothing. |
| */ |
| if (pdeo->closing) { |
| /* somebody else is doing that, just wait */ |
| @@ -238,10 +243,12 @@ static void close_pdeo(struct proc_dir_e |
| |
| pdeo->closing = true; |
| spin_unlock(&pde->pde_unload_lock); |
| + |
| file = pdeo->file; |
| pde->proc_ops->proc_release(file_inode(file), file); |
| + |
| spin_lock(&pde->pde_unload_lock); |
| - /* After ->release. */ |
| + /* Strictly after ->proc_release, see above. */ |
| list_del(&pdeo->lh); |
| c = pdeo->c; |
| spin_unlock(&pde->pde_unload_lock); |
| --- a/fs/proc/proc_net.c~proc-add-some-hopefully-insightful-comments |
| +++ a/fs/proc/proc_net.c |
| @@ -350,6 +350,12 @@ static __net_init int proc_net_ns_init(s |
| kgid_t gid; |
| int err; |
| |
| + /* |
| + * This PDE acts only as an anchor for /proc/${pid}/net hierarchy. |
| + * Corresponding inode (PDE(inode) == net->proc_net) is never |
| + * instantiated therefore blanket zeroing is fine. |
| + * net->proc_net_stat inode is instantiated normally. |
| + */ |
| err = -ENOMEM; |
| netd = kmem_cache_zalloc(proc_dir_entry_cache, GFP_KERNEL); |
| if (!netd) |
| --- a/fs/proc/root.c~proc-add-some-hopefully-insightful-comments |
| +++ a/fs/proc/root.c |
| @@ -302,6 +302,11 @@ void __init proc_root_init(void) |
| proc_mkdir("bus", NULL); |
| proc_sys_init(); |
| |
| + /* |
| + * Last things last. It is not like userspace processes eager |
| + * to open /proc files exist at this point but register last |
| + * anyway. |
| + */ |
| register_filesystem(&proc_fs_type); |
| } |
| |
| _ |