diff options
| author | Alexey Dobriyan <adobriyan@gmail.com> | 2016-12-12 19:45:22 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-12 21:55:09 -0500 |
| commit | 492b2da6056e7051917516368e75e062422c3557 (patch) | |
| tree | 808bc51279edffc50b3513a215771668919770d1 /fs | |
| parent | 39a10ac23cfdb6469550e1641a2bc2ed80663ceb (diff) | |
proc: tweak comments about 2 stage open and everything
Some comments were obsoleted since commit 05c0ae21c034 ("try a saner
locking for pde_opener...").
Some new comments added.
Some confusing comments replaced with equally confusing ones.
Link: http://lkml.kernel.org/r/20161029160231.GD1246@avx2
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/proc/inode.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 57f548e2eb59..783bc19644d1 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
| @@ -138,6 +138,16 @@ static void unuse_pde(struct proc_dir_entry *pde) | |||
| 138 | /* pde is locked */ | 138 | /* pde is locked */ |
| 139 | static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo) | 139 | static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo) |
| 140 | { | 140 | { |
| 141 | /* | ||
| 142 | * close() (proc_reg_release()) can't delete an entry and proceed: | ||
| 143 | * ->release hook needs to be available at the right moment. | ||
| 144 | * | ||
| 145 | * rmmod (remove_proc_entry() et al) can't delete an entry and proceed: | ||
| 146 | * "struct file" needs to be available at the right moment. | ||
| 147 | * | ||
| 148 | * Therefore, first process to enter this function does ->release() and | ||
| 149 | * signals its completion to the other process which does nothing. | ||
| 150 | */ | ||
| 141 | if (pdeo->closing) { | 151 | if (pdeo->closing) { |
| 142 | /* somebody else is doing that, just wait */ | 152 | /* somebody else is doing that, just wait */ |
| 143 | DECLARE_COMPLETION_ONSTACK(c); | 153 | DECLARE_COMPLETION_ONSTACK(c); |
| @@ -152,6 +162,7 @@ static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo) | |||
| 152 | file = pdeo->file; | 162 | file = pdeo->file; |
| 153 | pde->proc_fops->release(file_inode(file), file); | 163 | pde->proc_fops->release(file_inode(file), file); |
| 154 | spin_lock(&pde->pde_unload_lock); | 164 | spin_lock(&pde->pde_unload_lock); |
| 165 | /* After ->release. */ | ||
| 155 | list_del(&pdeo->lh); | 166 | list_del(&pdeo->lh); |
| 156 | if (pdeo->c) | 167 | if (pdeo->c) |
| 157 | complete(pdeo->c); | 168 | complete(pdeo->c); |
| @@ -167,6 +178,8 @@ void proc_entry_rundown(struct proc_dir_entry *de) | |||
| 167 | if (atomic_add_return(BIAS, &de->in_use) != BIAS) | 178 | if (atomic_add_return(BIAS, &de->in_use) != BIAS) |
| 168 | wait_for_completion(&c); | 179 | wait_for_completion(&c); |
| 169 | 180 | ||
| 181 | /* ->pde_openers list can't grow from now on. */ | ||
| 182 | |||
| 170 | spin_lock(&de->pde_unload_lock); | 183 | spin_lock(&de->pde_unload_lock); |
| 171 | while (!list_empty(&de->pde_openers)) { | 184 | while (!list_empty(&de->pde_openers)) { |
| 172 | struct pde_opener *pdeo; | 185 | struct pde_opener *pdeo; |
| @@ -312,14 +325,15 @@ static int proc_reg_open(struct inode *inode, struct file *file) | |||
| 312 | struct pde_opener *pdeo; | 325 | struct pde_opener *pdeo; |
| 313 | 326 | ||
| 314 | /* | 327 | /* |
| 315 | * What for, you ask? Well, we can have open, rmmod, remove_proc_entry | 328 | * Ensure that |
| 316 | * sequence. ->release won't be called because ->proc_fops will be | 329 | * 1) PDE's ->release hook will be called no matter what |
| 317 | * cleared. Depending on complexity of ->release, consequences vary. | 330 | * either normally by close()/->release, or forcefully by |
| 331 | * rmmod/remove_proc_entry. | ||
| 332 | * | ||
| 333 | * 2) rmmod isn't blocked by opening file in /proc and sitting on | ||
| 334 | * the descriptor (including "rmmod foo </proc/foo" scenario). | ||
| 318 | * | 335 | * |
| 319 | * We can't wait for mercy when close will be done for real, it's | 336 | * Save every "struct file" with custom ->release hook. |
| 320 | * deadlockable: rmmod foo </proc/foo . So, we're going to do ->release | ||
| 321 | * by hand in remove_proc_entry(). For this, save opener's credentials | ||
| 322 | * for later. | ||
| 323 | */ | 337 | */ |
| 324 | pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL); | 338 | pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL); |
| 325 | if (!pdeo) | 339 | if (!pdeo) |
| @@ -340,7 +354,6 @@ static int proc_reg_open(struct inode *inode, struct file *file) | |||
| 340 | pdeo->file = file; | 354 | pdeo->file = file; |
| 341 | pdeo->closing = false; | 355 | pdeo->closing = false; |
| 342 | pdeo->c = NULL; | 356 | pdeo->c = NULL; |
| 343 | /* Strictly for "too late" ->release in proc_reg_release(). */ | ||
| 344 | spin_lock(&pde->pde_unload_lock); | 357 | spin_lock(&pde->pde_unload_lock); |
| 345 | list_add(&pdeo->lh, &pde->pde_openers); | 358 | list_add(&pdeo->lh, &pde->pde_openers); |
| 346 | spin_unlock(&pde->pde_unload_lock); | 359 | spin_unlock(&pde->pde_unload_lock); |
