summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormr <mr@FreeBSD.org>2001-10-28 09:29:10 +0000
committermr <mr@FreeBSD.org>2001-10-28 09:29:10 +0000
commitf757fda60d8e586e6ba39ba525f615b8cb3fe0ce (patch)
tree13b4e909deffbd1c8f2a34c63dcc244b37e32d6b
parent315406dcf8c8a2619b51a673f41f5e666863fcdd (diff)
downloadFreeBSD-src-f757fda60d8e586e6ba39ba525f615b8cb3fe0ce.zip
FreeBSD-src-f757fda60d8e586e6ba39ba525f615b8cb3fe0ce.tar.gz
Introduce [IPC|SHM]_[INFO|STAT] to shmctl to make
`/compat/linux/usr/bin/ipcs -m` happy.
-rw-r--r--sys/compat/linux/linux_ipc.c55
-rw-r--r--sys/kern/sysv_shm.c45
-rw-r--r--sys/sys/ipc.h1
-rw-r--r--sys/sys/shm.h16
4 files changed, 113 insertions, 4 deletions
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c
index aa4deef..aa45505 100644
--- a/sys/compat/linux/linux_ipc.c
+++ b/sys/compat/linux/linux_ipc.c
@@ -70,6 +70,27 @@ struct l_shm_info {
l_ulong swap_successes;
};
+static void
+bsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo *lpp)
+{
+ lpp->shmmax = bpp->shmmax;
+ lpp->shmmin = bpp->shmmin;
+ lpp->shmmni = bpp->shmmni;
+ lpp->shmseg = bpp->shmseg;
+ lpp->shmall = bpp->shmall;
+}
+
+static void
+bsd_to_linux_shm_info( struct shm_info *bpp, struct l_shm_info *lpp)
+{
+ lpp->used_ids = bpp->used_ids ;
+ lpp->shm_tot = bpp->shm_tot ;
+ lpp->shm_rss = bpp->shm_rss ;
+ lpp->shm_swp = bpp->shm_swp ;
+ lpp->swap_attempts = bpp->swap_attempts ;
+ lpp->swap_successes = bpp->swap_successes ;
+}
+
struct l_ipc_perm {
l_key_t key;
l_uid16_t uid;
@@ -425,6 +446,8 @@ int
linux_shmctl(struct thread *td, struct linux_shmctl_args *args)
{
struct l_shmid_ds linux_shmid;
+ struct l_shminfo linux_shminfo;
+ struct l_shm_info linux_shm_info;
struct shmctl_args /* {
int shmid;
int cmd;
@@ -434,6 +457,25 @@ linux_shmctl(struct thread *td, struct linux_shmctl_args *args)
caddr_t sg = stackgap_init();
switch (args->cmd) {
+
+ case LINUX_IPC_INFO:
+ bsd_args.shmid = args->shmid;
+ bsd_args.cmd = IPC_INFO;
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shminfo));
+ if ((error = shmctl(td, &bsd_args)))
+ return error;
+ bsd_to_linux_shminfo( (struct shminfo *)bsd_args.buf, &linux_shminfo );
+ return copyout(&linux_shminfo, (caddr_t)args->buf, sizeof(shminfo));
+
+ case LINUX_SHM_INFO:
+ bsd_args.shmid = args->shmid;
+ bsd_args.cmd = SHM_INFO;
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shm_info));
+ if ((error = shmctl(td, &bsd_args)))
+ return error;
+ bsd_to_linux_shm_info( (struct shm_info *)bsd_args.buf, &linux_shm_info );
+ return copyout(&linux_shm_info, (caddr_t)args->buf, sizeof(struct shm_info));
+
case LINUX_IPC_STAT:
bsd_args.shmid = args->shmid;
bsd_args.cmd = IPC_STAT;
@@ -443,6 +485,16 @@ linux_shmctl(struct thread *td, struct linux_shmctl_args *args)
bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid);
return copyout(&linux_shmid, (caddr_t)args->buf, sizeof(linux_shmid));
+ case LINUX_SHM_STAT:
+ bsd_args.shmid = args->shmid;
+ bsd_args.cmd = SHM_STAT;
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
+ if ((error = shmctl(td, &bsd_args))) {
+ return error;
+ }
+ bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid);
+ return copyout(&linux_shmid, (caddr_t)args->buf, sizeof(linux_shmid));
+
case LINUX_IPC_SET:
if ((error = copyin((caddr_t)args->buf, &linux_shmid,
sizeof(linux_shmid))))
@@ -467,9 +519,6 @@ linux_shmctl(struct thread *td, struct linux_shmctl_args *args)
}
return shmctl(td, &bsd_args);
- case LINUX_IPC_INFO:
- case LINUX_SHM_STAT:
- case LINUX_SHM_INFO:
case LINUX_SHM_LOCK:
case LINUX_SHM_UNLOCK:
default:
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index 74743e5..dc4fa3b 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -96,6 +96,7 @@ struct shmmap_state {
static void shm_deallocate_segment __P((struct shmid_ds *));
static int shm_find_segment_by_key __P((key_t));
static struct shmid_ds *shm_find_segment_by_shmid __P((int));
+static struct shmid_ds *shm_find_segment_by_shmidx __P((int));
static int shm_delete_mapping __P((struct proc *p, struct shmmap_state *));
static void shmrealloc __P((void));
static void shminit __P((void));
@@ -179,6 +180,20 @@ shm_find_segment_by_shmid(shmid)
return shmseg;
}
+static struct shmid_ds *
+shm_find_segment_by_shmidx(int segnum)
+{
+ struct shmid_ds *shmseg;
+
+ if (segnum < 0 || segnum >= shmalloced)
+ return NULL;
+ shmseg = &shmsegs[segnum];
+ if ((shmseg->shm_perm.mode & (SHMSEG_ALLOCATED | SHMSEG_REMOVED))
+ != SHMSEG_ALLOCATED )
+ return NULL;
+ return shmseg;
+}
+
static void
shm_deallocate_segment(shmseg)
struct shmid_ds *shmseg;
@@ -476,12 +491,38 @@ shmctl(td, uap)
error = ENOSYS;
goto done2;
}
- shmseg = shm_find_segment_by_shmid(uap->shmid);
+ switch (uap->cmd) {
+ case IPC_INFO:
+ error = copyout( (caddr_t)&shminfo, uap->buf, sizeof( shminfo ) );
+ if (error)
+ goto done2;
+ td->td_retval[0] = shmalloced;
+ goto done2;
+ case SHM_INFO: {
+ struct shm_info shm_info;
+ shm_info.used_ids = shm_nused;
+ shm_info.shm_rss = 0; /*XXX where to get from ? */
+ shm_info.shm_tot = 0; /*XXX where to get from ? */
+ shm_info.shm_swp = 0; /*XXX where to get from ? */
+ shm_info.swap_attempts = 0; /*XXX where to get from ? */
+ shm_info.swap_successes = 0; /*XXX where to get from ? */
+ error = copyout( (caddr_t)&shm_info, uap->buf, sizeof( shm_info ) );
+ if (error)
+ goto done2;
+ td->td_retval[0] = shmalloced;
+ goto done2;
+ }
+ }
+ if( (uap->cmd) == SHM_STAT )
+ shmseg = shm_find_segment_by_shmidx(uap->shmid);
+ else
+ shmseg = shm_find_segment_by_shmid(uap->shmid);
if (shmseg == NULL) {
error = EINVAL;
goto done2;
}
switch (uap->cmd) {
+ case SHM_STAT:
case IPC_STAT:
error = ipcperm(td, &shmseg->shm_perm, IPC_R);
if (error)
@@ -489,6 +530,8 @@ shmctl(td, uap)
error = copyout((caddr_t)shmseg, uap->buf, sizeof(inbuf));
if (error)
goto done2;
+ else if( (uap->cmd) == SHM_STAT )
+ td->td_retval[0] = IXSEQ_TO_IPCID( uap->shmid, shmseg->shm_perm );
break;
case IPC_SET:
error = ipcperm(td, &shmseg->shm_perm, IPC_M);
diff --git a/sys/sys/ipc.h b/sys/sys/ipc.h
index 463a541..7ca8b9d 100644
--- a/sys/sys/ipc.h
+++ b/sys/sys/ipc.h
@@ -75,6 +75,7 @@ struct ipc_perm {
#define IPC_RMID 0 /* remove identifier */
#define IPC_SET 1 /* set options */
#define IPC_STAT 2 /* get options */
+#define IPC_INFO 3 /* get info */
#ifdef _KERNEL
/* Macros to convert between ipc ids and array indices or sequence ids */
diff --git a/sys/sys/shm.h b/sys/sys/shm.h
index 48aa303..024c0e5 100644
--- a/sys/sys/shm.h
+++ b/sys/sys/shm.h
@@ -50,6 +50,13 @@
#define SHM_R (IPC_R)
#define SHM_W (IPC_W)
+/* predefine tbd *LOCK shmctl commands */
+#define SHM_LOCK 11
+#define SHM_UNLOCK 12
+
+/* ipcs shmctl commands */
+#define SHM_STAT 13
+#define SHM_INFO 14
struct shmid_ds {
struct ipc_perm shm_perm; /* operation permission structure */
@@ -79,6 +86,15 @@ struct shminfo {
extern struct shminfo shminfo;
extern struct shmid_ds *shmsegs;
+struct shm_info {
+ int used_ids;
+ unsigned long shm_tot;
+ unsigned long shm_rss;
+ unsigned long shm_swp;
+ unsigned long swap_attempts;
+ unsigned long swap_successes;
+};
+
struct thread;
struct proc;
OpenPOWER on IntegriCloud