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/proc/inode.c | |
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/proc/inode.c')
-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); |