diff options
author | mr <mr@FreeBSD.org> | 2001-10-28 09:29:10 +0000 |
---|---|---|
committer | mr <mr@FreeBSD.org> | 2001-10-28 09:29:10 +0000 |
commit | f757fda60d8e586e6ba39ba525f615b8cb3fe0ce (patch) | |
tree | 13b4e909deffbd1c8f2a34c63dcc244b37e32d6b | |
parent | 315406dcf8c8a2619b51a673f41f5e666863fcdd (diff) | |
download | FreeBSD-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.c | 55 | ||||
-rw-r--r-- | sys/kern/sysv_shm.c | 45 | ||||
-rw-r--r-- | sys/sys/ipc.h | 1 | ||||
-rw-r--r-- | sys/sys/shm.h | 16 |
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; |