ipc,shm: introduce shmctl_nolock
Similar to semctl and msgctl, when calling msgctl, the *_INFO and *_STAT commands can be performed without acquiring the ipc object. Add a shmctl_nolock() function and move the logic of *_INFO and *_STAT out of msgctl(). Since we are just moving functionality, this change still takes the lock and it will be properly lockless in the next patch. Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com> Tested-by: Sedat Dilek <sedat.dilek@gmail.com> Cc: Rik van Riel <riel@redhat.com> Cc: Manfred Spraul <manfred@colorfullife.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
3b1c4ad377
commit
68eccc1dc3
61
ipc/shm.c
61
ipc/shm.c
@ -820,28 +820,23 @@ out_up:
|
||||
return err;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
|
||||
static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
|
||||
int cmd, int version, void __user *buf)
|
||||
{
|
||||
int err;
|
||||
struct shmid_kernel *shp;
|
||||
int err, version;
|
||||
struct ipc_namespace *ns;
|
||||
|
||||
if (cmd < 0 || shmid < 0) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
version = ipc_parse_version(&cmd);
|
||||
ns = current->nsproxy->ipc_ns;
|
||||
|
||||
switch (cmd) { /* replace with proc interface ? */
|
||||
case IPC_INFO:
|
||||
{
|
||||
struct shminfo64 shminfo;
|
||||
|
||||
/* preliminary security checks for *_INFO */
|
||||
if (cmd == IPC_INFO || cmd == SHM_INFO) {
|
||||
err = security_shm_shmctl(NULL, cmd);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case IPC_INFO:
|
||||
{
|
||||
struct shminfo64 shminfo;
|
||||
|
||||
memset(&shminfo, 0, sizeof(shminfo));
|
||||
shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
|
||||
@ -864,10 +859,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
|
||||
{
|
||||
struct shm_info shm_info;
|
||||
|
||||
err = security_shm_shmctl(NULL, cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memset(&shm_info, 0, sizeof(shm_info));
|
||||
down_read(&shm_ids(ns).rw_mutex);
|
||||
shm_info.used_ids = shm_ids(ns).in_use;
|
||||
@ -928,6 +919,36 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
|
||||
err = result;
|
||||
goto out;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
shm_unlock(shp);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
|
||||
{
|
||||
struct shmid_kernel *shp;
|
||||
int err, version;
|
||||
struct ipc_namespace *ns;
|
||||
|
||||
if (cmd < 0 || shmid < 0) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
version = ipc_parse_version(&cmd);
|
||||
ns = current->nsproxy->ipc_ns;
|
||||
|
||||
switch (cmd) {
|
||||
case IPC_INFO:
|
||||
case SHM_INFO:
|
||||
case SHM_STAT:
|
||||
case IPC_STAT:
|
||||
return shmctl_nolock(ns, shmid, cmd, version, buf);
|
||||
case SHM_LOCK:
|
||||
case SHM_UNLOCK:
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user