]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
ipcs: determine ipc limits from /proc
authorSami Kerola <kerolasa@iki.fi>
Sun, 21 Oct 2012 16:40:28 +0000 (17:40 +0100)
committerKarel Zak <kzak@redhat.com>
Fri, 23 Nov 2012 13:58:21 +0000 (14:58 +0100)
Some of the limit values are not dynamic.  Like in kernel these values
are #defined.

[kzak@redhat.com: - use better names for functions,
                  - add ipcutils.{c,h}
                  - read also shmmax from /proc]

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Karel Zak <kzak@redhat.com>
include/pathnames.h
sys-utils/Makemodule.am
sys-utils/ipcs.c
sys-utils/ipcutils.c [new file with mode: 0644]
sys-utils/ipcutils.h [new file with mode: 0644]

index cc60baf96dd1aff861a1d1eebbb07c3443567afc..0f9f30c0462191b44d34c2178187b210f39f7133 100644 (file)
 #define _PATH_PROC_IPC_MSGMNI  "/proc/sys/kernel/msgmni"
 #define _PATH_PROC_IPC_SEM     "/proc/sys/kernel/sem"
 #define _PATH_PROC_IPC_SHMALL  "/proc/sys/kernel/shmall"
+#define _PATH_PROC_IPC_SHMMAX  "/proc/sys/kernel/shmmax"
 #define _PATH_PROC_IPC_SHMMNI  "/proc/sys/kernel/shmmni"
 
 /* kernel command line */
index a6e3c0768946d2542e1b77ed5006178e088b10df..c7b1eb361492fc003f8dd5089499e87d159fa024 100644 (file)
@@ -16,7 +16,11 @@ ipcrm_LDADD = $(LDADD) libcommon.la
 
 usrbin_exec_PROGRAMS += ipcs
 dist_man_MANS += sys-utils/ipcs.1
-ipcs_SOURCES = sys-utils/ipcs.c
+ipcs_SOURCES = sys-utils/ipcs.c \
+               sys-utils/ipcutils.c \
+               sys-utils/ipcutils.h
+ipcs_LDADD = $(LDADD) libcommon.la
+
 
 usrbin_exec_PROGRAMS += renice
 dist_man_MANS += sys-utils/renice.1
index 2fbca0888fb94f050cc675736e871c66c611b8d4..b904bb326bc2633571f986654689791e98cc17c1 100644 (file)
 #include <errno.h>
 #include <features.h>
 #include <getopt.h>
-#include <grp.h>
-#include <pwd.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/sem.h>
-#include <sys/shm.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
 
 #include "c.h"
 #include "nls.h"
 #include "closestream.h"
 
-/*
- * SHM_DEST and SHM_LOCKED are defined in kernel headers, but inside
- * #ifdef __KERNEL__ ... #endif
- */
-#ifndef SHM_DEST
-  /* shm_mode upper byte flags */
-# define SHM_DEST      01000   /* segment will be destroyed on last detach */
-# define SHM_LOCKED    02000   /* segment will not be swapped */
-#endif
-
-/* For older kernels the same holds for the defines below */
-#ifndef MSG_STAT
-# define MSG_STAT      11
-# define MSG_INFO      12
-#endif
-
-#ifndef SHM_STAT
-# define SHM_STAT      13
-# define SHM_INFO      14
-struct shm_info {
-       int used_ids;
-       ulong shm_tot;          /* total allocated shm */
-       ulong shm_rss;          /* total resident shm */
-       ulong shm_swp;          /* total swapped shm */
-       ulong swap_attempts;
-       ulong swap_successes;
-};
-#endif
-
-#ifndef SEM_STAT
-# define SEM_STAT      18
-# define SEM_INFO      19
-#endif
-
-/* Some versions of libc only define IPC_INFO when __USE_GNU is defined. */
-#ifndef IPC_INFO
-# define IPC_INFO      3
-#endif
+#include "ipcutils.h"
 
-/*
- * The last arg of semctl is a union semun, but where is it defined? X/OPEN
- * tells us to define it ourselves, but until recently Linux include files
- * would also define it.
- */
-#ifndef HAVE_UNION_SEMUN
-/* according to X/OPEN we have to define it ourselves */
-union semun {
-       int val;
-       struct semid_ds *buf;
-       unsigned short int *array;
-       struct seminfo *__buf;
-};
-#endif
-
-/*
- * X/OPEN (Jan 1987) does not define fields key, seq in struct ipc_perm;
- *     glibc-1.09 has no support for sysv ipc.
- *     glibc 2 uses __key, __seq
- */
-#if defined (__GLIBC__) && __GLIBC__ >= 2
-# define KEY __key
-#else
-# define KEY key
-#endif
 
 #define LIMITS 1
 #define STATUS 2
@@ -269,9 +195,9 @@ void do_shm (char format)
        int maxid, shmid, id;
        struct shmid_ds shmseg;
        struct shm_info shm_info;
-       struct shminfo shminfo;
        struct ipc_perm *ipcp = &shmseg.shm_perm;
        struct passwd *pw;
+       struct ipc_limits lim;
 
        maxid = shmctl (0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
        if (maxid < 0) {
@@ -282,20 +208,13 @@ void do_shm (char format)
        switch (format) {
        case LIMITS:
                printf (_("------ Shared Memory Limits --------\n"));
-               if ((shmctl (0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0 )
+               if (ipc_shm_get_limits(&lim))
                        return;
-               /*
-                * glibc 2.1.3 and all earlier libc's have ints as fields of
-                * struct shminfo; glibc 2.1.91 has unsigned long; ach
-                */
-               printf (_("max number of segments = %lu\n"),
-                       (unsigned long) shminfo.shmmni);
-               printf (_("max seg size (kbytes) = %lu\n"),
-                       (unsigned long) (shminfo.shmmax >> 10));
-               printf (_("max total shared memory (kbytes) = %llu\n"),
-                       getpagesize() / 1024 * (unsigned long long) shminfo.shmall);
-               printf (_("min seg size (bytes) = %lu\n"),
-                       (unsigned long) shminfo.shmmin);
+               printf (_("max number of segments = %ju\n"), lim.shmmni);
+               printf (_("max seg size (kbytes) = %ju\n"), lim.shmmax / 1024);
+               printf (_("max total shared memory (kbytes) = %ju\n"),
+                                       (lim.shmall / 1024) * getpagesize());
+               printf (_("min seg size (bytes) = %ju\n"), lim.shmmin);
                return;
 
        case STATUS:
@@ -415,6 +334,7 @@ void do_sem (char format)
        struct ipc_perm *ipcp = &semary.sem_perm;
        struct passwd *pw;
        union semun arg;
+       struct ipc_limits lim;
 
        arg.array = (ushort *)  (void *) &seminfo;
        maxid = semctl (0, 0, SEM_INFO, arg);
@@ -426,14 +346,13 @@ void do_sem (char format)
        switch (format) {
        case LIMITS:
                printf (_("------ Semaphore Limits --------\n"));
-               arg.array = (ushort *) (void *) &seminfo; /* damn union */
-               if ((semctl (0, 0, IPC_INFO, arg)) < 0 )
+               if (ipc_sem_get_limits(&lim))
                        return;
-               printf (_("max number of arrays = %d\n"), seminfo.semmni);
-               printf (_("max semaphores per array = %d\n"), seminfo.semmsl);
-               printf (_("max semaphores system wide = %d\n"), seminfo.semmns);
-               printf (_("max ops per semop call = %d\n"), seminfo.semopm);
-               printf (_("semaphore max value = %d\n"), seminfo.semvmx);
+               printf (_("max number of arrays = %d\n"), lim.semmni);
+               printf (_("max semaphores per array = %d\n"), lim.semmsl);
+               printf (_("max semaphores system wide = %d\n"), lim.semmns);
+               printf (_("max ops per semop call = %d\n"), lim.semopm);
+               printf (_("semaphore max value = %d\n"), lim.semvmx);
                return;
 
        case STATUS:
@@ -515,6 +434,7 @@ void do_msg (char format)
        struct msginfo msginfo;
        struct ipc_perm *ipcp = &msgque.msg_perm;
        struct passwd *pw;
+       struct ipc_limits lim;
 
        maxid = msgctl (0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo);
        if (maxid < 0) {
@@ -524,12 +444,12 @@ void do_msg (char format)
 
        switch (format) {
        case LIMITS:
-               if ((msgctl (0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0 )
+               if (ipc_msg_get_limits(&lim))
                        return;
                printf (_("------ Messages Limits --------\n"));
-               printf (_("max queues system wide = %d\n"), msginfo.msgmni);
-               printf (_("max size of message (bytes) = %d\n"), msginfo.msgmax);
-               printf (_("default max size of queue (bytes) = %d\n"), msginfo.msgmnb);
+               printf (_("max queues system wide = %d\n"), lim.msgmni);
+               printf (_("max size of message (bytes) = %zu\n"), lim.msgmax);
+               printf (_("default max size of queue (bytes) = %d\n"), lim.msgmnb);
                return;
 
        case STATUS:
diff --git a/sys-utils/ipcutils.c b/sys-utils/ipcutils.c
new file mode 100644 (file)
index 0000000..041f350
--- /dev/null
@@ -0,0 +1,89 @@
+
+#include "c.h"
+#include "path.h"
+#include "pathnames.h"
+#include "ipcutils.h"
+
+#ifndef SEMVMX
+# define SEMVMX  32767 /* <= 32767 semaphore maximum value */
+#endif
+#ifndef SHMMIN
+# define SHMMIN 1      /* min shared segment size in bytes */
+#endif
+
+
+int ipc_msg_get_limits(struct ipc_limits *lim)
+{
+       if (path_exist(_PATH_PROC_IPC_MSGMNI) &&
+           path_exist(_PATH_PROC_IPC_MSGMNB) &&
+           path_exist(_PATH_PROC_IPC_MSGMAX)) {
+
+               lim->msgmni = path_read_s32(_PATH_PROC_IPC_MSGMNI);
+               lim->msgmnb = path_read_s32(_PATH_PROC_IPC_MSGMNB);
+               lim->msgmax = path_read_s32(_PATH_PROC_IPC_MSGMAX);
+       } else {
+               struct msginfo msginfo;
+
+               if (msgctl(0, IPC_INFO, (struct msqid_ds *) &msginfo) < 0)
+                       return 1;
+               lim->msgmni = msginfo.msgmni;
+               lim->msgmnb = msginfo.msgmnb;
+               lim->msgmax = msginfo.msgmax;
+       }
+
+       return 0;
+}
+
+int ipc_sem_get_limits(struct ipc_limits *lim)
+{
+       FILE *f;
+       int rc = 0;
+
+       lim->semvmx = SEMVMX;
+
+       f = path_fopen("r", 0, _PATH_PROC_IPC_SEM);
+       if (f) {
+               rc = fscanf(f, "%d\t%d\t%d\t%d",
+                      &lim->semmsl, &lim->semmns, &lim->semopm, &lim->semmni);
+               fclose(f);
+
+       }
+
+       if (rc == 4) {
+               struct seminfo seminfo;
+               union semun arg = { .array = (ushort *) &seminfo };
+
+               if (semctl(0, 0, IPC_INFO, arg) < 0)
+                       return 1;
+               lim->semmni = seminfo.semmni;
+               lim->semmsl = seminfo.semmsl;
+               lim->semmns = seminfo.semmns;
+               lim->semopm = seminfo.semopm;
+       }
+
+       return 0;
+}
+
+int ipc_shm_get_limits(struct ipc_limits *lim)
+{
+       lim->shmmin = SHMMIN;
+
+       if (path_exist(_PATH_PROC_IPC_SHMALL) &&
+           path_exist(_PATH_PROC_IPC_SHMMAX) &&
+           path_exist(_PATH_PROC_IPC_SHMMNI)) {
+
+               lim->shmall = path_read_u64(_PATH_PROC_IPC_SHMALL);
+               lim->shmmax = path_read_u64(_PATH_PROC_IPC_SHMMAX);
+               lim->shmmni = path_read_u64(_PATH_PROC_IPC_SHMMNI);
+
+       } else {
+               struct shminfo shminfo;
+
+               if (shmctl(0, IPC_INFO, (struct shmid_ds *) &shminfo) < 0)
+                       return 1;
+               lim->shmmni = shminfo.shmmni;
+               lim->shmall = shminfo.shmall;
+       }
+
+       return 0;
+}
diff --git a/sys-utils/ipcutils.h b/sys-utils/ipcutils.h
new file mode 100644 (file)
index 0000000..ef539ee
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef UTIL_LINUX_IPCUTILS_H
+#define UTIL_LINUX_IPCUTILS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include <grp.h>
+#include <pwd.h>
+
+/*
+ * SHM_DEST and SHM_LOCKED are defined in kernel headers, but inside
+ * #ifdef __KERNEL__ ... #endif
+ */
+#ifndef SHM_DEST
+  /* shm_mode upper byte flags */
+# define SHM_DEST      01000   /* segment will be destroyed on last detach */
+# define SHM_LOCKED    02000   /* segment will not be swapped */
+#endif
+
+/* For older kernels the same holds for the defines below */
+#ifndef MSG_STAT
+# define MSG_STAT      11
+# define MSG_INFO      12
+#endif
+
+#ifndef SHM_STAT
+# define SHM_STAT      13
+# define SHM_INFO      14
+struct shm_info {
+       int used_ids;
+       ulong shm_tot;          /* total allocated shm */
+       ulong shm_rss;          /* total resident shm */
+       ulong shm_swp;          /* total swapped shm */
+       ulong swap_attempts;
+       ulong swap_successes;
+};
+#endif
+
+#ifndef SEM_STAT
+# define SEM_STAT      18
+# define SEM_INFO      19
+#endif
+
+/* Some versions of libc only define IPC_INFO when __USE_GNU is defined. */
+#ifndef IPC_INFO
+# define IPC_INFO      3
+#endif
+
+/*
+ *  * The last arg of semctl is a union semun, but where is it defined? X/OPEN
+ *   * tells us to define it ourselves, but until recently Linux include files
+ *    * would also define it.
+ *     */
+#ifndef HAVE_UNION_SEMUN
+/* according to X/OPEN we have to define it ourselves */
+union semun {
+       int val;
+       struct semid_ds *buf;
+       unsigned short int *array;
+       struct seminfo *__buf;
+};
+#endif
+
+/*
+ * X/OPEN (Jan 1987) does not define fields key, seq in struct ipc_perm;
+ *     glibc-1.09 has no support for sysv ipc.
+ *     glibc 2 uses __key, __seq
+ */
+#if defined (__GLIBC__) && __GLIBC__ >= 2
+# define KEY __key
+#else
+# define KEY key
+#endif
+
+struct ipc_limits {
+       uint64_t        shmmni;         /* max number of segments */
+       uint64_t        shmmax;         /* max segment size */
+       uint64_t        shmall;         /* max total shared memory */
+       uint64_t        shmmin;         /* min segment size */
+
+       int             semmni;         /* max number of arrays */
+       int             semmsl;         /* max semaphores per array */
+       int             semmns;         /* max semaphores system wide */
+       int             semopm;         /* max ops per semop call */
+       unsigned int    semvmx;         /* semaphore max value (constant) */
+
+       int             msgmni;         /* max queues system wide */
+       size_t          msgmax;         /* max size of message */
+       int             msgmnb;         /* default max size of queue */
+};
+
+extern int ipc_msg_get_limits(struct ipc_limits *lim);
+extern int ipc_sem_get_limits(struct ipc_limits *lim);
+extern int ipc_shm_get_limits(struct ipc_limits *lim);
+
+#endif /* UTIL_LINUX_IPCUTILS_H */