The patch titled Subject: ipc: allow boot time extension of IPCMNI from 32k to 16M has been added to the -mm tree. Its filename is ipc-allow-boot-time-extension-of-ipcmni-from-32k-to-16m.patch This patch should soon appear at http://ozlabs.org/~akpm/mmots/broken-out/ipc-allow-boot-time-extension-of-ipcmni-from-32k-to-16m.patch and later at http://ozlabs.org/~akpm/mmotm/broken-out/ipc-allow-boot-time-extension-of-ipcmni-from-32k-to-16m.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next and is updated there every 3-4 working days ------------------------------------------------------ From: Waiman Long <longman@xxxxxxxxxx> Subject: ipc: allow boot time extension of IPCMNI from 32k to 16M Patch series "ipc: Increase IPCMNI limit", v12. There are users out there requesting increase in the IPCMNI value to more than 32k. This patchset does that by using a boot kernel parameter "ipcmni_extend" to increase the IPCMNI limit from 32k to 16M when that boot command line option is specified. Patch 1 adds a "ipcmni_extend" boot command line parameter to extend the IPCMNI limit from 32k to 16M. Patch 2 changes how the sequence number within an id is being generated by incrementing it only when the generated id is not greater than the previous one. That reduces the chance of id reuse whether "ipcmni_extend" is set or not. Patch 3 makes identifier allocation go cyclical through the entire 24-bit id space with "ipcmni_extend" only to further reduce the chance of id reuse, but probably with a slight memory and performance overhead. The cyclical id allocation isn't done for non-ipcmni_extend mode as the potential memory and performance overhead may be problematic on system with slow CPU and little memory. Systems that run applications which need more than 32k IPC identifiers can certainly afford the extra overhead. This patch (of 3): The maximum number of unique System V IPC identifiers was limited to 32k. That limit should be big enough for most use cases. However, there are some users out there requesting for more, especially those that are migrating from Solaris which uses 24 bits for unique identifiers. To satisfy the need of those users, a new boot time kernel option "ipcmni_extend" is added to extend the IPCMNI value to 16M. This is a 512X increase which should be big enough for users out there that need a large number of unique IPC identifier. The use of this new option will change the pattern of the IPC identifiers returned by functions like shmget(2). An application that depends on such pattern may not work properly. So it should only be used if the users really need more than 32k of unique IPC numbers. This new option does have the side effect of reducing the maximum number of unique sequence numbers from 64k down to 128. So it is a trade-off. The computation of a new IPC id is not done in the performance critical path. So a little bit of additional overhead shouldn't have any real performance impact. Link: http://lkml.kernel.org/r/1551379645-819-2-git-send-email-longman@xxxxxxxxxx Signed-off-by: Waiman Long <longman@xxxxxxxxxx> Acked-by: Manfred Spraul <manfred@xxxxxxxxxxxxxxxx> Cc: "Luis R. Rodriguez" <mcgrof@xxxxxxxxxx> Cc: Kees Cook <keescook@xxxxxxxxxxxx> Cc: Jonathan Corbet <corbet@xxxxxxx> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx> Cc: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> Cc: Takashi Iwai <tiwai@xxxxxxx> Cc: Davidlohr Bueso <dbueso@xxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- Documentation/admin-guide/kernel-parameters.txt | 3 ipc/ipc_sysctl.c | 12 +++ ipc/util.c | 10 +-- ipc/util.h | 44 +++++++++++--- 4 files changed, 54 insertions(+), 15 deletions(-) --- a/Documentation/admin-guide/kernel-parameters.txt~ipc-allow-boot-time-extension-of-ipcmni-from-32k-to-16m +++ a/Documentation/admin-guide/kernel-parameters.txt @@ -1812,6 +1812,9 @@ ip= [IP_PNP] See Documentation/filesystems/nfs/nfsroot.txt. + ipcmni_extend [KNL] Extend the maximum number of unique System V + IPC identifiers from 32,768 to 16,777,216. + irqaffinity= [SMP] Set the default irq affinity mask The argument is a cpu list, as described above. --- a/ipc/ipc_sysctl.c~ipc-allow-boot-time-extension-of-ipcmni-from-32k-to-16m +++ a/ipc/ipc_sysctl.c @@ -120,7 +120,8 @@ static int proc_ipc_sem_dointvec(struct static int zero; static int one = 1; static int int_max = INT_MAX; -static int ipc_mni = IPCMNI; +int ipc_mni = IPCMNI; +int ipc_mni_shift = IPCMNI_SHIFT; static struct ctl_table ipc_kern_table[] = { { @@ -246,3 +247,12 @@ static int __init ipc_sysctl_init(void) } device_initcall(ipc_sysctl_init); + +static int __init ipc_mni_extend(char *str) +{ + ipc_mni = IPCMNI_EXTEND; + ipc_mni_shift = IPCMNI_EXTEND_SHIFT; + pr_info("IPCMNI extended to %d.\n", ipc_mni); + return 0; +} +early_param("ipcmni_extend", ipc_mni_extend); --- a/ipc/util.c~ipc-allow-boot-time-extension-of-ipcmni-from-32k-to-16m +++ a/ipc/util.c @@ -110,7 +110,7 @@ static const struct rhashtable_params ip * @ids: ipc identifier set * * Set up the sequence range to use for the ipc identifier range (limited - * below IPCMNI) then initialise the keys hashtable and ids idr. + * below ipc_mni) then initialise the keys hashtable and ids idr. */ void ipc_init_ids(struct ipc_ids *ids) { @@ -226,7 +226,7 @@ static inline int ipc_idr_alloc(struct i 0, GFP_NOWAIT); } if (idx >= 0) - new->id = SEQ_MULTIPLIER * new->seq + idx; + new->id = (new->seq << IPCMNI_SEQ_SHIFT) + idx; return idx; } @@ -254,8 +254,8 @@ int ipc_addid(struct ipc_ids *ids, struc /* 1) Initialize the refcount so that ipc_rcu_putref works */ refcount_set(&new->refcount, 1); - if (limit > IPCMNI) - limit = IPCMNI; + if (limit > ipc_mni) + limit = ipc_mni; if (ids->in_use >= limit) return -ENOSPC; @@ -738,7 +738,7 @@ static struct kern_ipc_perm *sysvipc_fin if (total >= ids->in_use) return NULL; - for (; pos < IPCMNI; pos++) { + for (; pos < ipc_mni; pos++) { ipc = idr_find(&ids->ipcs_idr, pos); if (ipc != NULL) { *new_pos = pos + 1; --- a/ipc/util.h~ipc-allow-boot-time-extension-of-ipcmni-from-32k-to-16m +++ a/ipc/util.h @@ -15,8 +15,34 @@ #include <linux/err.h> #include <linux/ipc_namespace.h> -#define IPCMNI 32768 /* <= MAX_INT limit for ipc arrays (including sysctl changes) */ -#define SEQ_MULTIPLIER (IPCMNI) +/* + * The IPC ID contains 2 separate numbers - index and sequence number. + * By default, + * bits 0-14: index (32k, 15 bits) + * bits 15-30: sequence number (64k, 16 bits) + * + * When IPCMNI extension mode is turned on, the composition changes: + * bits 0-23: index (16M, 24 bits) + * bits 24-30: sequence number (128, 7 bits) + */ +#define IPCMNI_SHIFT 15 +#define IPCMNI_EXTEND_SHIFT 24 +#define IPCMNI (1 << IPCMNI_SHIFT) +#define IPCMNI_EXTEND (1 << IPCMNI_EXTEND_SHIFT) + +#ifdef CONFIG_SYSVIPC_SYSCTL +extern int ipc_mni; +extern int ipc_mni_shift; + +#define IPCMNI_SEQ_SHIFT ipc_mni_shift +#define IPCMNI_IDX_MASK ((1 << ipc_mni_shift) - 1) + +#else /* CONFIG_SYSVIPC_SYSCTL */ + +#define ipc_mni IPCMNI +#define IPCMNI_SEQ_SHIFT IPCMNI_SHIFT +#define IPCMNI_IDX_MASK ((1 << IPCMNI_SHIFT) - 1) +#endif /* CONFIG_SYSVIPC_SYSCTL */ void sem_init(void); void msg_init(void); @@ -96,9 +122,9 @@ struct pid_namespace *ipc_seq_pid_ns(str #define IPC_MSG_IDS 1 #define IPC_SHM_IDS 2 -#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER) -#define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER) -#define IPCID_SEQ_MAX min_t(int, INT_MAX/SEQ_MULTIPLIER, USHRT_MAX) +#define ipcid_to_idx(id) ((id) & IPCMNI_IDX_MASK) +#define ipcid_to_seqx(id) ((id) >> IPCMNI_SEQ_SHIFT) +#define IPCID_SEQ_MAX (INT_MAX >> IPCMNI_SEQ_SHIFT) /* must be called with ids->rwsem acquired for writing */ int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); @@ -123,8 +149,8 @@ static inline int ipc_get_maxidx(struct if (ids->in_use == 0) return -1; - if (ids->in_use == IPCMNI) - return IPCMNI - 1; + if (ids->in_use == ipc_mni) + return ipc_mni - 1; return ids->max_idx; } @@ -219,10 +245,10 @@ void free_ipcs(struct ipc_namespace *ns, static inline int sem_check_semmni(struct ipc_namespace *ns) { /* - * Check semmni range [0, IPCMNI] + * Check semmni range [0, ipc_mni] * semmni is the last element of sem_ctls[4] array */ - return ((ns->sem_ctls[3] < 0) || (ns->sem_ctls[3] > IPCMNI)) + return ((ns->sem_ctls[3] < 0) || (ns->sem_ctls[3] > ipc_mni)) ? -ERANGE : 0; } _ Patches currently in -mm which might be from longman@xxxxxxxxxx are debugobjects-move-printk-out-of-db-lock-critical-sections.patch include-linux-nodemaskh-use-nr_node_ids-not-max_numnodes-in-__nodemask_pr_numnodes.patch ipc-allow-boot-time-extension-of-ipcmni-from-32k-to-16m.patch ipc-conserve-sequence-numbers-in-ipcmni_extend-mode.patch ipc-do-cyclic-id-allocation-with-ipcmni_extend-mode.patch