Skip to content

Commit 83293c0

Browse files
Jack Millertorvalds
Jack Miller
authored andcommitted
shm: allow exit_shm in parallel if only marking orphans
If shm_rmid_force (the default state) is not set then the shmids are only marked as orphaned and does not require any add, delete, or locking of the tree structure. Seperate the sysctl on and off case, and only obtain the read lock. The newly added list head can be deleted under the read lock because we are only called with current and will only change the semids allocated by this task and not manipulate the list. This commit assumes that up_read includes a sufficient memory barrier for the writes to be seen my others that later obtain a write lock. Signed-off-by: Milton Miller <[email protected]> Signed-off-by: Jack Miller <[email protected]> Cc: Davidlohr Bueso <[email protected]> Cc: Manfred Spraul <[email protected]> Cc: Anton Blanchard <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent ab602f7 commit 83293c0

File tree

1 file changed

+35
-32
lines changed

1 file changed

+35
-32
lines changed

ipc/shm.c

+35-32
Original file line numberDiff line numberDiff line change
@@ -268,32 +268,6 @@ static void shm_close(struct vm_area_struct *vma)
268268
up_write(&shm_ids(ns).rwsem);
269269
}
270270

271-
/* Called with ns->shm_ids(ns).rwsem locked */
272-
static void shm_mark_orphan(struct shmid_kernel *shp, struct ipc_namespace *ns)
273-
{
274-
if (WARN_ON(shp->shm_creator != current)) /* Remove me when it works */
275-
return;
276-
277-
/*
278-
* Mark it as orphaned to destroy the segment when
279-
* kernel.shm_rmid_forced is changed.
280-
* It is noop if the following shm_may_destroy() returns true.
281-
*/
282-
shp->shm_creator = NULL;
283-
284-
/*
285-
* Don't even try to destroy it. If shm_rmid_forced=0 and IPC_RMID
286-
* is not set, it shouldn't be deleted here.
287-
*/
288-
if (!ns->shm_rmid_forced)
289-
return;
290-
291-
if (shm_may_destroy(ns, shp)) {
292-
shm_lock_by_ptr(shp);
293-
shm_destroy(ns, shp);
294-
}
295-
}
296-
297271
/* Called with ns->shm_ids(ns).rwsem locked */
298272
static int shm_try_destroy_orphaned(int id, void *p, void *data)
299273
{
@@ -325,20 +299,49 @@ void shm_destroy_orphaned(struct ipc_namespace *ns)
325299
up_write(&shm_ids(ns).rwsem);
326300
}
327301

328-
302+
/* Locking assumes this will only be called with task == current */
329303
void exit_shm(struct task_struct *task)
330304
{
331305
struct ipc_namespace *ns = task->nsproxy->ipc_ns;
332306
struct shmid_kernel *shp, *n;
333307

334-
if (shm_ids(ns).in_use == 0)
308+
if (list_empty(&task->sysvshm.shm_clist))
309+
return;
310+
311+
/*
312+
* If kernel.shm_rmid_forced is not set then only keep track of
313+
* which shmids are orphaned, so that a later set of the sysctl
314+
* can clean them up.
315+
*/
316+
if (!ns->shm_rmid_forced) {
317+
down_read(&shm_ids(ns).rwsem);
318+
list_for_each_entry(shp, &task->sysvshm.shm_clist, shm_clist)
319+
shp->shm_creator = NULL;
320+
/*
321+
* Only under read lock but we are only called on current
322+
* so no entry on the list will be shared.
323+
*/
324+
list_del(&task->sysvshm.shm_clist);
325+
up_read(&shm_ids(ns).rwsem);
335326
return;
327+
}
336328

337-
/* Destroy all already created segments, but not mapped yet */
329+
/*
330+
* Destroy all already created segments, that were not yet mapped,
331+
* and mark any mapped as orphan to cover the sysctl toggling.
332+
* Destroy is skipped if shm_may_destroy() returns false.
333+
*/
338334
down_write(&shm_ids(ns).rwsem);
339-
list_for_each_entry_safe(shp, n, &task->sysvshm.shm_clist, shm_clist)
340-
shm_mark_orphan(shp, ns);
341-
/* remove the list head from any segments still attached */
335+
list_for_each_entry_safe(shp, n, &task->sysvshm.shm_clist, shm_clist) {
336+
shp->shm_creator = NULL;
337+
338+
if (shm_may_destroy(ns, shp)) {
339+
shm_lock_by_ptr(shp);
340+
shm_destroy(ns, shp);
341+
}
342+
}
343+
344+
/* Remove the list head from any segments still attached. */
342345
list_del(&task->sysvshm.shm_clist);
343346
up_write(&shm_ids(ns).rwsem);
344347
}

0 commit comments

Comments
 (0)