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;
|
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;
|
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);
|
err = security_shm_shmctl(NULL, cmd);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case IPC_INFO:
|
||||||
|
{
|
||||||
|
struct shminfo64 shminfo;
|
||||||
|
|
||||||
memset(&shminfo, 0, sizeof(shminfo));
|
memset(&shminfo, 0, sizeof(shminfo));
|
||||||
shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
|
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;
|
struct shm_info shm_info;
|
||||||
|
|
||||||
err = security_shm_shmctl(NULL, cmd);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
memset(&shm_info, 0, sizeof(shm_info));
|
memset(&shm_info, 0, sizeof(shm_info));
|
||||||
down_read(&shm_ids(ns).rw_mutex);
|
down_read(&shm_ids(ns).rw_mutex);
|
||||||
shm_info.used_ids = shm_ids(ns).in_use;
|
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;
|
err = result;
|
||||||
goto out;
|
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_LOCK:
|
||||||
case SHM_UNLOCK:
|
case SHM_UNLOCK:
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user