From: Solofo Ramangalahy The msgmnb and msgmni values are coupled for deactivation and reactivation of value computation. The uncoupling of msgmn{b,i} for deactivation/reactivation of recomputation adds flexibility and testability. . Flexibility was discussed during the msgmni series development and ended up with reactivation by negative value on /proc. . Testability allows to experiment with the automatic computation of msgmn{b,i} values. For example, if current algorithm does not fit application needs. As msgmni value is based in msgmnb and msgmnb*msgmni should not be bigger than 1/32 of low memory, reenabling msgmnb triggers one shot recomputation of msgmni. Signed-off-by: Solofo Ramangalahy --- Documentation/sysctl/kernel.txt | 1 include/linux/ipc_namespace.h | 3 +- ipc/ipc_sysctl.c | 53 ++++++++++++++++++++++++++++++---------- ipc/ipcns_notifier.c | 9 ------ ipc/msg.c | 6 ++++ 5 files changed, 49 insertions(+), 23 deletions(-) Index: b/include/linux/ipc_namespace.h =================================================================== --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h @@ -34,7 +34,9 @@ struct ipc_namespace { int msg_ctlmax; int msg_ctlmnb; + bool msg_ctlmnb_activated; /* recompute_msgmnb activation */ int msg_ctlmni; + bool msg_ctlmni_activated; /* recompute_msgmni activation */ atomic_t msg_bytes; atomic_t msg_hdrs; @@ -53,7 +55,6 @@ extern atomic_t nr_ipc_ns; #define INIT_IPC_NS(ns) .ns = &init_ipc_ns, extern int register_ipcns_notifier(struct ipc_namespace *); -extern int cond_register_ipcns_notifier(struct ipc_namespace *); extern int unregister_ipcns_notifier(struct ipc_namespace *); extern int ipcns_notify(unsigned long); Index: b/ipc/msg.c =================================================================== --- a/ipc/msg.c +++ b/ipc/msg.c @@ -91,6 +91,8 @@ void recompute_msgmni(struct ipc_namespa unsigned long allowed; int nb_ns; + if (!ns->msg_ctlmni_activated) + return; si_meminfo(&i); allowed = (((i.totalram - i.totalhigh) / MSG_MEM_SCALE) * i.mem_unit) / ns->msg_ctlmnb; @@ -114,6 +116,8 @@ void recompute_msgmni(struct ipc_namespa */ void recompute_msgmnb(struct ipc_namespace *ns) { + if (!ns->msg_ctlmnb_activated) + return; ns->msg_ctlmnb = min(MSGMNB * num_online_cpus(), MSGMNB * MSG_CPU_SCALE); } @@ -121,6 +125,8 @@ void recompute_msgmnb(struct ipc_namespa void msg_init_ns(struct ipc_namespace *ns) { ns->msg_ctlmax = MSGMAX; + ns->msg_ctlmnb_activated = true; + ns->msg_ctlmni_activated = true; recompute_msgmnb(ns); recompute_msgmni(ns); Index: b/ipc/ipc_sysctl.c =================================================================== --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -33,18 +33,46 @@ static void *get_ipc(ctl_table *table) * add/remove or ipc namespace creation/removal. * They can come back to a recomputable state by being set to a <0 value. */ -static void tunable_set_callback(int val) +static void tunable_set_callback(int val, ctl_table *table) { - if (val >= 0) - unregister_ipcns_notifier(current->nsproxy->ipc_ns); - else { + int tunable = table->ctl_name; + + if (val >= 0) { + switch (tunable) { + case KERN_MSGMNB: + current->nsproxy->ipc_ns->msg_ctlmnb_activated = false; + break; + case KERN_MSGMNI: + current->nsproxy->ipc_ns->msg_ctlmni_activated = false; + break; + default: + printk(KERN_ERR "ipc: unexpected value %s\n", + table->procname); + break; + } + } else { /* * Re-enable automatic recomputing only if not already * enabled. */ - recompute_msgmnb(current->nsproxy->ipc_ns); - recompute_msgmni(current->nsproxy->ipc_ns); - cond_register_ipcns_notifier(current->nsproxy->ipc_ns); + switch (tunable) { + case KERN_MSGMNB: + current->nsproxy->ipc_ns->msg_ctlmnb_activated = true; + recompute_msgmnb(current->nsproxy->ipc_ns); + /* + * msgmni adjustment is needed not to overflow + * 1/MSG_MEM_SCALE limit. + */ + recompute_msgmni(current->nsproxy->ipc_ns); + case KERN_MSGMNI: + current->nsproxy->ipc_ns->msg_ctlmni_activated = true; + recompute_msgmni(current->nsproxy->ipc_ns); + break; + default: + printk(KERN_ERR "ipc: unexpected value %s\n", + table->procname); + break; + } } } @@ -71,9 +99,10 @@ static int proc_ipc_callback_dointvec(ct rc = proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos); - if (write && !rc && lenp_bef == *lenp) - tunable_set_callback(*((int *)(ipc_table.data))); - + if (write && !rc && lenp_bef == *lenp) { + BUG_ON(table == NULL); + tunable_set_callback(*((int *)(ipc_table.data)), table); + } return rc; } @@ -148,8 +177,8 @@ static int sysctl_ipc_registered_data(ct * Tunable has successfully been changed from userland */ int *data = get_ipc(table); - - tunable_set_callback(*data); + BUG_ON(table == NULL); + tunable_set_callback(*data, table); } return rc; Index: b/ipc/ipcns_notifier.c =================================================================== --- a/ipc/ipcns_notifier.c +++ b/ipc/ipcns_notifier.c @@ -65,15 +65,6 @@ int register_ipcns_notifier(struct ipc_n return blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb); } -int cond_register_ipcns_notifier(struct ipc_namespace *ns) -{ - memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb)); - ns->ipcns_nb.notifier_call = ipcns_callback; - ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI; - return blocking_notifier_chain_cond_register(&ipcns_chain, - &ns->ipcns_nb); -} - int unregister_ipcns_notifier(struct ipc_namespace *ns) { return blocking_notifier_chain_unregister(&ipcns_chain, Index: b/Documentation/sysctl/kernel.txt =================================================================== --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -203,7 +203,6 @@ The exact value is automatically (re)com # echo -1 > /proc/sys/kernel/msgmnb See recompute_msgmnb() function in ipc/ directory for details. -The value of msgmnb is coupled with the value of msgmni. ============================================================== -- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/