[RFC PATCH] ipc: add shm_locked for IPC shm



From: Hiroshi Shimamoto <h-shimamoto@xxxxxxxxxxxxx>

Shared memory users probably don't think the shared memory is
swapped out. But actually shared memory could be swapped out under
memory pressure.
Linux has SHM_LOCK feature for prevent shared memory swapping,
and it can be used by shmctl() after create the shared memory.
There are some needs that SHM_LOCK is default behavior.

This patch adds shm_locked sysctl to turn SHM_LOCK on when creating.
kernel.shm_locked = 0, is default and the behavior is not changed.
kernel.shm_locked = 1, means shared memory will be locked when
it's created.

Signed-off-by: Hiroshi Shimamoto <h-shimamoto@xxxxxxxxxxxxx>
---
include/linux/ipc_namespace.h | 1 +
include/linux/sysctl.h | 1 +
ipc/ipc_sysctl.c | 9 +++++
ipc/shm.c | 70 ++++++++++++++++++++++++----------------
kernel/sysctl_check.c | 2 +
5 files changed, 55 insertions(+), 28 deletions(-)

diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index e4451d1..1323985 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -29,6 +29,7 @@ struct ipc_namespace {
size_t shm_ctlmax;
size_t shm_ctlall;
int shm_ctlmni;
+ int shm_ctllocked;
int shm_tot;
};

diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 571f01d..434c207 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -163,6 +163,7 @@ enum
KERN_MAX_LOCK_DEPTH=74,
KERN_NMI_WATCHDOG=75, /* int: enable/disable nmi watchdog */
KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
+ KERN_SHMLOCKED=77, /* int: make shared memory locked */
};


diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 7f4235b..00d43b2 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -123,6 +123,15 @@ static struct ctl_table ipc_kern_table[] = {
.strategy = sysctl_ipc_data,
},
{
+ .ctl_name = KERN_SHMLOCKED,
+ .procname = "shm_locked",
+ .data = &init_ipc_ns.shm_ctllocked,
+ .maxlen = sizeof (init_ipc_ns.shm_ctllocked),
+ .mode = 0644,
+ .proc_handler = proc_ipc_dointvec,
+ .strategy = sysctl_ipc_data,
+ },
+ {
.ctl_name = KERN_MSGMAX,
.procname = "msgmax",
.data = &init_ipc_ns.msg_ctlmax,
diff --git a/ipc/shm.c b/ipc/shm.c
index cc63fae..6078477 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -66,6 +66,7 @@ static int newseg(struct ipc_namespace *, struct ipc_params *);
static void shm_open(struct vm_area_struct *vma);
static void shm_close(struct vm_area_struct *vma);
static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
+static int do_shmlock(struct shmid_kernel *shp, int cmd);
#ifdef CONFIG_PROC_FS
static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
#endif
@@ -75,6 +76,7 @@ void shm_init_ns(struct ipc_namespace *ns)
ns->shm_ctlmax = SHMMAX;
ns->shm_ctlall = SHMALL;
ns->shm_ctlmni = SHMMNI;
+ ns->shm_ctllocked = 0;
ns->shm_tot = 0;
ipc_init_ids(&ns->ids[IPC_SHM_IDS]);
}
@@ -438,6 +440,9 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
*/
file->f_dentry->d_inode->i_ino = shp->shm_perm.id;

+ if (ns->shm_ctllocked)
+ do_shmlock(shp, SHM_LOCK);
+
ns->shm_tot += numpages;
error = shp->shm_perm.id;
shm_unlock(shp);
@@ -626,6 +631,42 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
}
}

+static int do_shmlock(struct shmid_kernel *shp, int cmd)
+{
+ int err;
+
+ if (!capable(CAP_IPC_LOCK)) {
+ err = -EPERM;
+ if (current->euid != shp->shm_perm.uid &&
+ current->euid != shp->shm_perm.cuid)
+ goto out;
+ if (cmd == SHM_LOCK &&
+ !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
+ goto out;
+ }
+
+ err = security_shm_shmctl(shp, cmd);
+ if (err)
+ goto out;
+
+ if (cmd == SHM_LOCK) {
+ struct user_struct * user = current->user;
+ if (!is_file_hugepages(shp->shm_file)) {
+ err = shmem_lock(shp->shm_file, 1, user);
+ if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){
+ shp->shm_perm.mode |= SHM_LOCKED;
+ shp->mlock_user = user;
+ }
+ }
+ } else if (!is_file_hugepages(shp->shm_file)) {
+ shmem_lock(shp->shm_file, 0, shp->mlock_user);
+ shp->shm_perm.mode &= ~SHM_LOCKED;
+ shp->mlock_user = NULL;
+ }
+out:
+ return err;
+}
+
asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
{
struct shm_setbuf setbuf;
@@ -753,34 +794,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
if (err)
goto out_unlock;

- if (!capable(CAP_IPC_LOCK)) {
- err = -EPERM;
- if (current->euid != shp->shm_perm.uid &&
- current->euid != shp->shm_perm.cuid)
- goto out_unlock;
- if (cmd == SHM_LOCK &&
- !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
- goto out_unlock;
- }
-
- err = security_shm_shmctl(shp, cmd);
- if (err)
- goto out_unlock;
-
- if(cmd==SHM_LOCK) {
- struct user_struct * user = current->user;
- if (!is_file_hugepages(shp->shm_file)) {
- err = shmem_lock(shp->shm_file, 1, user);
- if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){
- shp->shm_perm.mode |= SHM_LOCKED;
- shp->mlock_user = user;
- }
- }
- } else if (!is_file_hugepages(shp->shm_file)) {
- shmem_lock(shp->shm_file, 0, shp->mlock_user);
- shp->shm_perm.mode &= ~SHM_LOCKED;
- shp->mlock_user = NULL;
- }
+ err = do_shmlock(shp, cmd);
shm_unlock(shp);
goto out;
}
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index c09350d..3d13649 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -104,6 +104,8 @@ static const struct trans_ctl_table trans_kern_table[] = {
{ KERN_MAX_LOCK_DEPTH, "max_lock_depth" },
{ KERN_NMI_WATCHDOG, "nmi_watchdog" },
{ KERN_PANIC_ON_NMI, "panic_on_unrecovered_nmi" },
+
+ { KERN_SHMLOCKED, "shm_locked" },
{}
};

--
1.5.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



Relevant Pages

  • POSIX shm and mmap on Solaris problem -- a bug?
    ... works fine on Linux. ... we need to attach two POSIX shared memory ... In order to find the suitable addresses for the second segment, ... if (ftruncate(sfd, shmsize)) { ...
    (comp.unix.solaris)
  • POSIX shm and mmap on Solaris problem -- a bug?
    ... works fine on Linux. ... we need to attach two POSIX shared memory ... In order to find the suitable addresses for the second segment, ... if (ftruncate(sfd, shmsize)) { ...
    (comp.unix.programmer)
  • Re: Quad AMD opteron system and Linux
    ... linux doesn't like processes bigger than 1.5G. ... I'd like to be able to have 8GB of shared memory, for DB cache, and ... 16GB of memory being used for filesystem cache. ... I blew up a box this time last week with dual-Xeon/4GB RAM when it had ...
    (comp.os.linux.hardware)
  • [Info-ingres] (Fwd) Linux shared memory
    ... I'd like to configure some shared cache servers on a Linux box. ... How do I configure scads of shared memory on Linux? ... Random Duckman Quote #108: ... Giving Duckman an aphrodysiac is like giving Michael ...
    (comp.databases.ingres)
  • PTHREAD_PROCESS_SHARED on GNU/Linux
    ... a stock Linux kernel won't release the lock on behalf of the ... mutex, so you'd probably have to stop everything and re-initialize the ... shared memory if any process dies unexpectedly. ...
    (comp.programming.threads)