Hello!
A few weeks ago, I ran into problem, which related to SystemV IPC.
More than 20 processes attached to a segment shared queue. Process-initiator for
create segment was killed, as process which was accessed to segment
last. Segment didn't free memory, but tagged it as SHMSEG_REMOVED as
the result. This is a reason of memory overflow (memory assotiated as
shm). Moreover, processes, which was attached to this segment did't
get a new data. I have one resolve. I need to restarted all process,
which still attached to segment. But this reason have a problem. We
haven't list of this processes at system. Moreover, struct shmid_ds,
which described segment, haven't this info too.
This patch is a resolve of problem. It:
- added a linked list of structures shmid_pi in struct shmid_ds. PID
(and last access time) recorded to this struct consistently. Memory
allocates with ident 'shminfo' for this list of struct shmid_pi.
- added syscall shminf for get all elements from list shmid_ds.
- added option [-P] in ipcs(1) for system call shminf.
Thanks.
--
Respectfully,
Stanislav Putrya
System administrator
FotoStrana.Ru Ltd.
ICQ IM: 328585847
Jabber-GoogleTalk: root.vagner
mob.phone SPB: +79215788755
mob.phone RND: +79525600664
email: [email protected]
email: [email protected]
email: [email protected]
site: bsdway.ru
site: fotostrana.ru
----------------------------------------
( ) ASCII ribbon campaign
X - against HTML, vCards and
/ \ - proprietary attachments in e-mail
Index: usr.bin/ipcs/ipcs.c
===================================================================
--- usr.bin/ipcs/ipcs.c (revision 249257)
+++ usr.bin/ipcs/ipcs.c (working copy)
@@ -30,6 +30,7 @@
#include <sys/param.h>
#include <sys/proc.h>
+#include <sys/queue.h>
#define _KERNEL
#include <sys/sem.h>
#include <sys/shm.h>
@@ -37,6 +38,7 @@
#undef _KERNEL
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <kvm.h>
@@ -47,6 +49,9 @@
#include <string.h>
#include <unistd.h>
+#include <sys/module.h>
+#include <sys/syscall.h>
+
#include "ipc.h"
char *fmt_perm(u_short);
@@ -58,12 +63,15 @@
void print_kmsqheader(int option);
void print_kmsqptr(int i, int option, struct msqid_kernel *kmsqptr);
void print_kshmtotal(struct shminfo shminfo);
+void print_kshminfoptr(int i, int option, struct shmid_kernel *kshmptr);
void print_kshmheader(int option);
void print_kshmptr(int i, int option, struct shmid_kernel *kshmptr);
void print_ksemtotal(struct seminfo seminfo);
void print_ksemheader(int option);
void print_ksemptr(int i, int option, struct semid_kernel *ksemaptr);
+int shminf(int, struct shmid_pi *);
+
char *
fmt_perm(u_short mode)
{
@@ -103,6 +111,7 @@
#define OUTSTANDING 4
#define PID 8
#define TIME 16
+#define PIDLIST 32
int
main(int argc, char *argv[])
@@ -114,7 +123,7 @@
int i;
uid_t uid = 0;
- while ((i = getopt(argc, argv, "MmQqSsabC:cN:optTu:y")) != -1)
+ while ((i = getopt(argc, argv, "MmQqSsabPC:cN:optTu:y")) != -1)
switch (i) {
case 'a':
option |= BIGGEST | CREATOR | OUTSTANDING | PID | TIME;
@@ -165,6 +174,9 @@
user = optarg;
uid = user2uid(user);
break;
+ case 'P':
+ option |= PIDLIST;
+ break;
case 'y':
use_sysctl = 0;
break;
@@ -409,20 +421,28 @@
void
print_kshmheader(int option)
{
-
- printf("Shared Memory:\n");
- printf("T %12s %12s %-11s %-8s %-8s",
- "ID", "KEY", "MODE", "OWNER", "GROUP");
- if (option & CREATOR)
- printf(" %-8s %-8s", "CREATOR", "CGROUP");
- if (option & OUTSTANDING)
- printf(" %12s", "NATTCH");
- if (option & BIGGEST)
- printf(" %12s", "SEGSZ");
- if (option & PID)
- printf(" %12s %12s", "CPID", "LPID");
- if (option & TIME)
- printf(" %-8s %-8s %-8s", "ATIME", "DTIME", "CTIME");
+ if (option & PIDLIST)
+ {
+ printf("Shared Memory pids info:\n");
+ printf("T %12s %12s %-11s %-8s %-8s",
+ "ID", "KEY", "NATTCH", "PID", "ATIME");
+ }
+ else
+ {
+ printf("Shared Memory:\n");
+ printf("T %12s %12s %-11s %-8s %-8s",
+ "ID", "KEY", "MODE", "OWNER", "GROUP");
+ if (option & CREATOR)
+ printf(" %-8s %-8s", "CREATOR", "CGROUP");
+ if (option & OUTSTANDING)
+ printf(" %12s", "NATTCH");
+ if (option & BIGGEST)
+ printf(" %12s", "SEGSZ");
+ if (option & PID)
+ printf(" %12s %12s", "CPID", "LPID");
+ if (option & TIME)
+ printf(" %-8s %-8s %-8s", "ATIME", "DTIME", "CTIME");
+ }
printf("\n");
}
@@ -430,18 +450,44 @@
print_kshmptr(int i, int option, struct shmid_kernel *kshmptr)
{
char atime_buf[100], dtime_buf[100], ctime_buf[100];
+ int sysc_num, pid, error, cnt;
cvt_time(kshmptr->u.shm_atime, atime_buf);
cvt_time(kshmptr->u.shm_dtime, dtime_buf);
cvt_time(kshmptr->u.shm_ctime, ctime_buf);
- printf("m %12d %12d %s %-8s %-8s",
- IXSEQ_TO_IPCID(i, kshmptr->u.shm_perm),
- (int)kshmptr->u.shm_perm.key,
- fmt_perm(kshmptr->u.shm_perm.mode),
- user_from_uid(kshmptr->u.shm_perm.uid, 0),
- group_from_gid(kshmptr->u.shm_perm.gid, 0));
+ if (option & PIDLIST)
+ {
+ struct shmid_pi shmid_pi_entry[kshmptr->u.shm_nattch];
+ bzero(shmid_pi_entry, sizeof(struct shmid_pi)*(kshmptr->u.shm_nattch));
+ error = shminf(IXSEQ_TO_IPCID(i, kshmptr->u.shm_perm), shmid_pi_entry);
+ if (error)
+ printf("ERROR:%d,%s ", error, strerror(errno));
+
+ for (cnt=0; cnt<(kshmptr->u.shm_nattch) && shmid_pi_entry[cnt].shm_pid; cnt++)
+ {
+ bzero(atime_buf, sizeof(atime_buf));
+ cvt_time(shmid_pi_entry[cnt].shm_atime, atime_buf);
+ printf("m %12d %12d %6d",
+ IXSEQ_TO_IPCID(i, kshmptr->u.shm_perm),
+ (int)kshmptr->u.shm_perm.key,
+ kshmptr->u.shm_nattch);
+ printf("%9d %10s\n", shmid_pi_entry[cnt].shm_pid, atime_buf);
+ };
+ return;
+ }
+ else
+ {
+ printf("m %12d %12d %s %-8s %-8s",
+ IXSEQ_TO_IPCID(i, kshmptr->u.shm_perm),
+ (int)kshmptr->u.shm_perm.key,
+ fmt_perm(kshmptr->u.shm_perm.mode),
+ user_from_uid(kshmptr->u.shm_perm.uid, 0),
+ group_from_gid(kshmptr->u.shm_perm.gid, 0));
+ };
+ kd=NULL;
+
if (option & CREATOR)
printf(" %-8s %-8s",
user_from_uid(kshmptr->u.shm_perm.cuid, 0),
@@ -456,9 +502,11 @@
kshmptr->u.shm_segsz);
if (option & PID)
+ {
printf(" %12d %12d",
kshmptr->u.shm_cpid,
kshmptr->u.shm_lpid);
+ }
if (option & TIME)
printf(" %s %s %s",
@@ -466,7 +514,8 @@
dtime_buf,
ctime_buf);
- printf("\n");
+ if (!(option & PIDLIST))
+ printf("\n");
}
void
Index: lib/libc/sys/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map (revision 249257)
+++ lib/libc/sys/Symbol.map (working copy)
@@ -268,6 +268,7 @@
shmat;
shmdt;
shmget;
+ shminf;
shmsys;
shutdown;
sigaction;
@@ -921,6 +922,8 @@
__sys_shmdt;
_shmget;
__sys_shmget;
+ _shminf;
+ __sys_shminf;
_shmsys;
__sys_shmsys;
_shutdown;
Index: sys/fs/procfs/procfs_map.c
===================================================================
--- sys/fs/procfs/procfs_map.c (revision 249257)
+++ sys/fs/procfs/procfs_map.c (working copy)
@@ -241,6 +241,6 @@
}
}
vm_map_unlock_read(map);
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
return (error);
}
Index: sys/bsm/audit_kevents.h
===================================================================
--- sys/bsm/audit_kevents.h (revision 249257)
+++ sys/bsm/audit_kevents.h (working copy)
@@ -383,6 +383,7 @@
#define AUE_DARWIN_PIDFORTASK 359 /* Darwin-specific. */
#define AUE_DARWIN_SYSCTL_NONADMIN 360
#define AUE_DARWIN_COPYFILE 361 /* Darwin-specific. */
+#define AUE_SHMINF 362
/*
* Audit event identifiers added as part of OpenBSM, generally corresponding
Index: sys/vm/vm_pageout.c
===================================================================
--- sys/vm/vm_pageout.c (revision 249257)
+++ sys/vm/vm_pageout.c (working copy)
@@ -1364,7 +1364,7 @@
continue;
}
if (!vm_map_trylock_read(&vm->vm_map)) {
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
PROC_UNLOCK(p);
continue;
}
@@ -1372,7 +1372,7 @@
vm_map_unlock_read(&vm->vm_map);
if (shortage == VM_OOM_MEM)
size += vmspace_resident_count(vm);
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
/*
* if the this process is bigger than the biggest one
* remember it.
@@ -1788,7 +1788,7 @@
tryagain = 1;
}
#endif
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
}
sx_sunlock(&allproc_lock);
if (tryagain != 0 && attempts <= 10)
Index: sys/vm/vm_map.c
===================================================================
--- sys/vm/vm_map.c (revision 249257)
+++ sys/vm/vm_map.c (working copy)
@@ -331,7 +331,7 @@
}
static inline void
-vmspace_dofree(struct vmspace *vm)
+vmspace_dofree(struct vmspace *vm, int *pid)
{
CTR1(KTR_VM, "vmspace_free: %p", vm);
@@ -340,7 +340,7 @@
* Make sure any SysV shm is freed, it might not have been in
* exit1().
*/
- shmexit(vm);
+ shmexit(vm, pid);
/*
* Lock the map, to wait out all other references to it.
@@ -356,14 +356,14 @@
}
void
-vmspace_free(struct vmspace *vm)
+vmspace_free(struct vmspace *vm, int *pid)
{
if (vm->vm_refcnt == 0)
panic("vmspace_free: attempt to free already freed vmspace");
if (atomic_fetchadd_int(&vm->vm_refcnt, -1) == 1)
- vmspace_dofree(vm);
+ vmspace_dofree(vm, pid);
}
void
@@ -376,7 +376,7 @@
p->p_vmspace = NULL;
PROC_VMSPACE_UNLOCK(p);
KASSERT(vm == &vmspace0, ("vmspace_exitfree: wrong vmspace"));
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
}
void
@@ -425,7 +425,7 @@
p->p_vmspace = &vmspace0;
PROC_VMSPACE_UNLOCK(p);
pmap_activate(td);
- vmspace_dofree(vm);
+ vmspace_dofree(vm, &p->p_pid);
}
vmspace_container_reset(p);
}
@@ -453,7 +453,7 @@
} while (!atomic_cmpset_int(&vm->vm_refcnt, refcnt, refcnt + 1));
if (vm != p->p_vmspace) {
PROC_VMSPACE_UNLOCK(p);
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
return (NULL);
}
PROC_VMSPACE_UNLOCK(p);
@@ -3657,6 +3657,7 @@
vmspace_exec(struct proc *p, vm_offset_t minuser, vm_offset_t maxuser)
{
struct vmspace *oldvmspace = p->p_vmspace;
+ int *oldpid = &p->p_pid;
struct vmspace *newvmspace;
newvmspace = vmspace_alloc(minuser, maxuser);
@@ -3675,7 +3676,7 @@
PROC_VMSPACE_UNLOCK(p);
if (p == curthread->td_proc)
pmap_activate(curthread);
- vmspace_free(oldvmspace);
+ vmspace_free(oldvmspace, oldpid);
return (0);
}
@@ -3687,9 +3688,11 @@
vmspace_unshare(struct proc *p)
{
struct vmspace *oldvmspace = p->p_vmspace;
+ int *oldpid;
struct vmspace *newvmspace;
vm_ooffset_t fork_charge;
+ oldpid = &p->p_pid;
if (oldvmspace->vm_refcnt == 1)
return (0);
fork_charge = 0;
@@ -3697,7 +3700,7 @@
if (newvmspace == NULL)
return (ENOMEM);
if (!swap_reserve_by_cred(fork_charge, p->p_ucred)) {
- vmspace_free(newvmspace);
+ vmspace_free(newvmspace, NULL);
return (ENOMEM);
}
PROC_VMSPACE_LOCK(p);
@@ -3705,7 +3708,7 @@
PROC_VMSPACE_UNLOCK(p);
if (p == curthread->td_proc)
pmap_activate(curthread);
- vmspace_free(oldvmspace);
+ vmspace_free(oldvmspace, oldpid);
return (0);
}
Index: sys/vm/vm_meter.c
===================================================================
--- sys/vm/vm_meter.c (revision 249257)
+++ sys/vm/vm_meter.c (working copy)
@@ -184,7 +184,7 @@
VM_OBJECT_UNLOCK(object);
}
vm_map_unlock_read(map);
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
if (paging)
total.t_pw++;
}
Index: sys/vm/vm_glue.c
===================================================================
--- sys/vm/vm_glue.c (revision 249257)
+++ sys/vm/vm_glue.c (working copy)
@@ -945,7 +945,7 @@
didswap++;
PROC_UNLOCK(p);
vm_map_unlock(&vm->vm_map);
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
sx_sunlock(&allproc_lock);
goto retry;
}
@@ -954,7 +954,7 @@
PROC_UNLOCK(p);
vm_map_unlock(&vm->vm_map);
nextproc1:
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
continue;
}
sx_sunlock(&allproc_lock);
Index: sys/vm/vm_extern.h
===================================================================
--- sys/vm/vm_extern.h (revision 249257)
+++ sys/vm/vm_extern.h (working copy)
@@ -81,7 +81,7 @@
int vmspace_unshare(struct proc *);
void vmspace_exit(struct thread *);
struct vmspace *vmspace_acquire_ref(struct proc *);
-void vmspace_free(struct vmspace *);
+void vmspace_free(struct vmspace *, int *);
void vmspace_exitfree(struct proc *);
void vnode_pager_setsize(struct vnode *, vm_ooffset_t);
int vslock(void *, size_t);
Index: sys/security/audit/audit_bsm.c
===================================================================
--- sys/security/audit/audit_bsm.c (revision 249257)
+++ sys/security/audit/audit_bsm.c (working copy)
@@ -1403,7 +1403,7 @@
}
break;
- /* AUE_SHMAT, AUE_SHMCTL, AUE_SHMDT and AUE_SHMGET are SysV IPC */
+ /* AUE_SHMAT, AUE_SHMCTL, AUE_SHMDT, AUE_SHMINF and AUE_SHMGET are SysV IPC */
case AUE_SHMAT:
if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
tok = au_to_arg32(1, "shmid", ar->ar_arg_svipc_id);
@@ -1458,6 +1458,15 @@
}
break;
+ case AUE_SHMINF:
+ if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
+ tok = au_to_arg32(1, "shmid", ar->ar_arg_svipc_id);
+ kau_write(rec, tok);
+ /* XXXAUDIT: Does having the ipc token make sense? */
+ tok = au_to_ipc(AT_IPC_SHM, ar->ar_arg_svipc_id);
+ kau_write(rec, tok);
+ }
+
case AUE_SHMGET:
/* This is unusual; the return value is in an argument token */
if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
Index: sys/sys/syscall.mk
===================================================================
--- sys/sys/syscall.mk (revision 249257)
+++ sys/sys/syscall.mk (working copy)
@@ -396,4 +396,5 @@
rctl_remove_rule.o \
posix_fallocate.o \
posix_fadvise.o \
- wait6.o
+ wait6.o \
+ shminf.o
Index: sys/sys/syscall.h
===================================================================
--- sys/sys/syscall.h (revision 249257)
+++ sys/sys/syscall.h (working copy)
@@ -448,4 +448,5 @@
#define SYS_posix_fallocate 530
#define SYS_posix_fadvise 531
#define SYS_wait6 532
-#define SYS_MAXSYSCALL 533
+#define SYS_shminf 533
+#define SYS_MAXSYSCALL 534
Index: sys/sys/ipc.h
===================================================================
--- sys/sys/ipc.h (revision 249257)
+++ sys/sys/ipc.h (working copy)
@@ -135,7 +135,7 @@
int ipcperm(struct thread *, struct ipc_perm *, int);
extern void (*shmfork_hook)(struct proc *, struct proc *);
-extern void (*shmexit_hook)(struct vmspace *);
+extern void (*shmexit_hook)(struct vmspace *, int *);
#else /* ! _KERNEL */
Index: sys/sys/sysproto.h
===================================================================
--- sys/sys/sysproto.h (revision 249257)
+++ sys/sys/sysproto.h (working copy)
@@ -1747,6 +1747,10 @@
char wrusage_l_[PADL_(struct __wrusage *)]; struct __wrusage * wrusage; char wrusage_r_[PADR_(struct __wrusage *)];
char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)];
};
+struct shminf_args {
+ char shmid_l_[PADL_(int)]; int shmid; char shmid_r_[PADR_(int)];
+ char buf_l_[PADL_(struct shmid_pi *)]; struct shmid_pi * buf; char buf_r_[PADR_(struct shmid_pi *)];
+};
int nosys(struct thread *, struct nosys_args *);
void sys_sys_exit(struct thread *, struct sys_exit_args *);
int sys_fork(struct thread *, struct fork_args *);
@@ -2125,6 +2129,7 @@
int sys_posix_fallocate(struct thread *, struct posix_fallocate_args *);
int sys_posix_fadvise(struct thread *, struct posix_fadvise_args *);
int sys_wait6(struct thread *, struct wait6_args *);
+int sys_shminf(struct thread *, struct shminf_args *);
#ifdef COMPAT_43
@@ -2817,6 +2822,7 @@
#define SYS_AUE_posix_fallocate AUE_NULL
#define SYS_AUE_posix_fadvise AUE_NULL
#define SYS_AUE_wait6 AUE_WAIT6
+#define SYS_AUE_shminf AUE_SHMINF
#undef PAD_
#undef PADL_
Index: sys/sys/shm.h
===================================================================
--- sys/sys/shm.h (revision 249257)
+++ sys/sys/shm.h (working copy)
@@ -42,6 +42,7 @@
#include <sys/cdefs.h>
#include <sys/ipc.h>
#include <sys/_types.h>
+#include <sys/queue.h>
#define SHM_RDONLY 010000 /* Attach read-only (else read-write) */
#define SHM_RND 020000 /* Round attach address to SHMLBA */
@@ -90,6 +91,15 @@
};
#endif
+
+
+struct shmid_pi {
+ pid_t shm_pid;
+ time_t shm_atime;
+ LIST_ENTRY(shmid_pi) shm_pi_list;
+};
+
+
struct shmid_ds {
struct ipc_perm shm_perm; /* operation permission structure */
size_t shm_segsz; /* size of segment in bytes */
@@ -99,8 +109,11 @@
time_t shm_atime; /* time of last shmat() */
time_t shm_dtime; /* time of last shmdt() */
time_t shm_ctime; /* time of last change by shmctl() */
+ LIST_HEAD(shmid_pi_head, shmid_pi) shm_pi; /* processes info who is attached. !EDIT this in /usr/include/sys/shm.h */
+
};
+
#ifdef _KERNEL
#include <vm/vm.h>
@@ -142,7 +155,7 @@
struct proc;
struct vmspace;
-void shmexit(struct vmspace *);
+void shmexit(struct vmspace *, int *);
void shmfork(struct proc *, struct proc *);
#else /* !_KERNEL */
@@ -159,6 +172,7 @@
#endif
void *shmat(int, const void *, int);
int shmget(key_t, size_t, int);
+int shminf(int, struct shmid_pi *);
int shmctl(int, int, struct shmid_ds *);
int shmdt(const void *);
__END_DECLS
Index: sys/kern/kern_proc.c
===================================================================
--- sys/kern/kern_proc.c (revision 249257)
+++ sys/kern/kern_proc.c (working copy)
@@ -2114,7 +2114,7 @@
}
}
vm_map_unlock_read(map);
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
PRELE(p);
free(kve, M_TEMP);
return (error);
@@ -2302,7 +2302,7 @@
}
}
vm_map_unlock_read(map);
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
PRELE(p);
free(kve, M_TEMP);
return (error);
Index: sys/kern/sysv_shm.c
===================================================================
--- sys/kern/sysv_shm.c (revision 249257)
+++ sys/kern/sysv_shm.c (working copy)
@@ -99,7 +99,9 @@
FEATURE(sysv_shm, "System V shared memory segments support");
static MALLOC_DEFINE(M_SHM, "shm", "SVID compatible shared memory segments");
+static MALLOC_DEFINE(M_SHMINF, "shminfo", "Struct for pids info in shared memory segments");
+
static int shmget_allocate_segment(struct thread *td,
struct shmget_args *uap, int mode);
static int shmget_existing(struct thread *td, struct shmget_args *uap,
@@ -123,12 +125,12 @@
static int shm_find_segment_by_key(key_t);
static struct shmid_kernel *shm_find_segment_by_shmid(int);
static struct shmid_kernel *shm_find_segment_by_shmidx(int);
-static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *);
+static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *, int *);
static void shmrealloc(void);
static int shminit(void);
static int sysvshm_modload(struct module *, int, void *);
static int shmunload(void);
-static void shmexit_myhook(struct vmspace *vm);
+static void shmexit_myhook(struct vmspace *vm, int *pid);
static void shmfork_myhook(struct proc *p1, struct proc *p2);
static int sysctl_shmsegs(SYSCTL_HANDLER_ARGS);
@@ -247,6 +249,7 @@
#ifdef MAC
mac_sysvshm_cleanup(shmseg);
#endif
+
racct_sub_cred(shmseg->cred, RACCT_NSHM, 1);
racct_sub_cred(shmseg->cred, RACCT_SHMSIZE, size);
crfree(shmseg->cred);
@@ -254,16 +257,19 @@
}
static int
-shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s)
+shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s, int *pid)
{
struct shmid_kernel *shmseg;
+ struct shmid_pi *shm_pi_entry;
int segnum, result;
vm_size_t size;
GIANT_REQUIRED;
segnum = IPCID_TO_IX(shmmap_s->shmid);
+
shmseg = &shmsegs[segnum];
+
size = round_page(shmseg->u.shm_segsz);
result = vm_map_remove(&vm->vm_map, shmmap_s->va, shmmap_s->va + size);
if (result != KERN_SUCCESS)
@@ -272,8 +278,26 @@
shmseg->u.shm_dtime = time_second;
if ((--shmseg->u.shm_nattch <= 0) &&
(shmseg->u.shm_perm.mode & SHMSEG_REMOVED)) {
+ LIST_FOREACH(shm_pi_entry, &shmseg->u.shm_pi, shm_pi_list)
+ {
+ LIST_REMOVE(shm_pi_entry, shm_pi_list);
+ free(shm_pi_entry, M_SHMINF);
+ break;
+ };
+
shm_deallocate_segment(shmseg);
shm_last_free = segnum;
+ } else if (pid)
+ {
+ LIST_FOREACH(shm_pi_entry, &shmseg->u.shm_pi, shm_pi_list)
+ {
+ if (shm_pi_entry->shm_pid == (*pid))
+ {
+ LIST_REMOVE(shm_pi_entry, shm_pi_list);
+ free(shm_pi_entry, M_SHMINF);
+ break;
+ }
+ };
}
return (0);
}
@@ -290,6 +314,7 @@
{
struct proc *p = td->td_proc;
struct shmmap_state *shmmap_s;
+
#ifdef MAC
struct shmid_kernel *shmsegptr;
#endif
@@ -320,7 +345,9 @@
if (error != 0)
goto done2;
#endif
- error = shm_delete_mapping(p->p_vmspace, shmmap_s);
+
+ error = shm_delete_mapping(p->p_vmspace, shmmap_s, &p->p_pid);
+
done2:
mtx_unlock(&Giant);
return (error);
@@ -344,6 +371,7 @@
int i, flags;
struct shmid_kernel *shmseg;
struct shmmap_state *shmmap_s = NULL;
+ struct shmid_pi *shmseg_pi;
vm_offset_t attach_va;
vm_prot_t prot;
vm_size_t size;
@@ -420,6 +448,15 @@
goto done2;
}
+ if (!shmseg->u.shm_nattch)
+ LIST_INIT(&shmseg->u.shm_pi);
+
+ shmseg_pi = malloc(sizeof(struct shmid_pi),
+ M_SHMINF, M_WAITOK);
+ shmseg_pi->shm_pid = p->p_pid;
+ shmseg_pi->shm_atime = time_second;
+ LIST_INSERT_HEAD(&shmseg->u.shm_pi, shmseg_pi, shm_pi_list);
+
shmmap_s->va = attach_va;
shmmap_s->shmid = shmid;
shmseg->u.shm_lpid = p->p_pid;
@@ -439,7 +476,34 @@
return kern_shmat(td, uap->shmid, uap->shmaddr, uap->shmflg);
}
+#ifndef _SYS_SYSPROTO_H_
+struct shminf_args {
+ int shmid;
+ shmid_pi *buf;
+};
+#endif
+
int
+sys_shminf(struct thread *td, struct shminf_args *uap)
+{
+ struct shmid_kernel *shmseg;
+ struct shmid_pi *buffer, *userbuf;
+ int error = 0;
+
+ userbuf = uap->buf;
+ shmseg = shm_find_segment_by_shmid(uap->shmid);
+ if (shmseg == NULL)
+ return(EINVAL);
+ LIST_FOREACH(buffer, &shmseg->u.shm_pi, shm_pi_list)
+ {
+ copyout(&buffer->shm_pid, uap->buf, sizeof(struct shmid_pi));
+ uap->buf++;
+ }
+ uap->buf = userbuf;
+ return(error);
+}
+
+int
kern_shmctl(td, shmid, cmd, buf, bufsz)
struct thread *td;
int shmid;
@@ -525,7 +589,7 @@
shmseg->u.shm_ctime = time_second;
break;
}
- case IPC_RMID:
+ case IPC_RMID: {
error = ipcperm(td, &shmseg->u.shm_perm, IPC_M);
if (error)
goto done2;
@@ -536,6 +600,7 @@
shm_last_free = IPCID_TO_IX(shmid);
}
break;
+ }
#if 0
case SHM_LOCK:
case SHM_UNLOCK:
@@ -799,7 +864,7 @@
}
static void
-shmexit_myhook(struct vmspace *vm)
+shmexit_myhook(struct vmspace *vm, int *pid)
{
struct shmmap_state *base, *shm;
int i;
@@ -809,7 +874,7 @@
mtx_lock(&Giant);
for (i = 0, shm = base; i < shminfo.shmseg; i++, shm++) {
if (shm->shmid != -1)
- shm_delete_mapping(vm, shm);
+ shm_delete_mapping(vm, shm, pid);
}
mtx_unlock(&Giant);
free(base, M_SHM);
@@ -847,6 +912,7 @@
SYSCALL_INIT_HELPER(shmctl),
SYSCALL_INIT_HELPER(shmdt),
SYSCALL_INIT_HELPER(shmget),
+ SYSCALL_INIT_HELPER(shminf),
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
SYSCALL_INIT_HELPER_COMPAT(freebsd7_shmctl),
@@ -1040,7 +1106,7 @@
static sy_call_t *shmcalls[] = {
(sy_call_t *)sys_shmat, (sy_call_t *)oshmctl,
(sy_call_t *)sys_shmdt, (sy_call_t *)sys_shmget,
- (sy_call_t *)freebsd7_shmctl
+ (sy_call_t *)freebsd7_shmctl, (sy_call_t *)sys_shminf
};
int
Index: sys/kern/init_sysent.c
===================================================================
--- sys/kern/init_sysent.c (revision 249257)
+++ sys/kern/init_sysent.c (working copy)
@@ -567,4 +567,5 @@
{ AS(posix_fallocate_args), (sy_call_t *)sys_posix_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 530 = posix_fallocate */
{ AS(posix_fadvise_args), (sy_call_t *)sys_posix_fadvise, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 531 = posix_fadvise */
{ AS(wait6_args), (sy_call_t *)sys_wait6, AUE_WAIT6, NULL, 0, 0, 0, SY_THR_STATIC }, /* 532 = wait6 */
+ { AS(shminf_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 533 = shminf */
};
Index: sys/kern/kern_exec.c
===================================================================
--- sys/kern/kern_exec.c (revision 249257)
+++ sys/kern/kern_exec.c (working copy)
@@ -1052,7 +1052,7 @@
sv_minuser = MAX(sv->sv_minuser, PAGE_SIZE);
if (vmspace->vm_refcnt == 1 && vm_map_min(map) == sv_minuser &&
vm_map_max(map) == sv->sv_maxuser) {
- shmexit(vmspace);
+ shmexit(vmspace, &p->p_pid);
pmap_remove_pages(vmspace_pmap(vmspace));
vm_map_remove(map, vm_map_min(map), vm_map_max(map));
} else {
Index: sys/kern/syscalls.c
===================================================================
--- sys/kern/syscalls.c (revision 249257)
+++ sys/kern/syscalls.c (working copy)
@@ -540,4 +540,5 @@
"posix_fallocate", /* 530 = posix_fallocate */
"posix_fadvise", /* 531 = posix_fadvise */
"wait6", /* 532 = wait6 */
+ "shminf", /* 533 = shminf */
};
Index: sys/kern/systrace_args.c
===================================================================
--- sys/kern/systrace_args.c (revision 249257)
+++ sys/kern/systrace_args.c (working copy)
@@ -3256,6 +3256,14 @@
*n_args = 6;
break;
}
+ /* shminf */
+ case 533: {
+ struct shminf_args *p = params;
+ iarg[0] = p->shmid; /* int */
+ uarg[1] = (intptr_t) p->buf; /* struct shmid_pi * */
+ *n_args = 2;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -8669,6 +8677,19 @@
break;
};
break;
+ /* shminf */
+ case 533:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct shmid_pi *";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
Index: sys/kern/kern_fork.c
===================================================================
--- sys/kern/kern_fork.c (revision 249257)
+++ sys/kern/kern_fork.c (working copy)
@@ -938,7 +938,7 @@
racct_proc_exit(newproc);
fail1:
if (vm2 != NULL)
- vmspace_free(vm2);
+ vmspace_free(vm2, NULL);
uma_zfree(proc_zone, newproc);
#ifdef PROCDESC
if (((flags & RFPROCDESC) != 0) && (fp_procdesc != NULL))
Index: sys/kern/vfs_aio.c
===================================================================
--- sys/kern/vfs_aio.c (revision 249257)
+++ sys/kern/vfs_aio.c (working copy)
@@ -1115,7 +1115,7 @@
* that it was acting on behalf of.
*/
if (tmpvm != myvm) {
- vmspace_free(tmpvm);
+ vmspace_free(tmpvm, &mycp->p_pid);
}
curcp = userp;
}
@@ -1160,7 +1160,7 @@
}
#endif
/* Remove our vmspace reference. */
- vmspace_free(tmpvm);
+ vmspace_free(tmpvm, &mycp->p_pid);
curcp = mycp;
Index: sys/kern/sys_process.c
===================================================================
--- sys/kern/sys_process.c (revision 249257)
+++ sys/kern/sys_process.c (working copy)
@@ -386,7 +386,7 @@
} while (0);
vm_map_unlock_read(map);
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
pve->pve_fsid = VNOVAL;
pve->pve_fileid = VNOVAL;
Index: sys/kern/sysv_ipc.c
===================================================================
--- sys/kern/sysv_ipc.c (revision 249257)
+++ sys/kern/sysv_ipc.c (working copy)
@@ -49,7 +49,7 @@
#include <sys/ucred.h>
void (*shmfork_hook)(struct proc *, struct proc *) = NULL;
-void (*shmexit_hook)(struct vmspace *) = NULL;
+void (*shmexit_hook)(struct vmspace *, int *) = NULL;
/* called from kern_fork.c */
void
@@ -64,11 +64,11 @@
/* called from kern_exit.c */
void
-shmexit(struct vmspace *vm)
+shmexit(struct vmspace *vm, int *pid)
{
if (shmexit_hook != NULL)
- shmexit_hook(vm);
+ shmexit_hook(vm, pid);
return;
}
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master (revision 249257)
+++ sys/kern/syscalls.master (working copy)
@@ -952,5 +952,6 @@
int *status, int options, \
struct __wrusage *wrusage, \
siginfo_t *info); }
+533 AUE_SHMINF NOSTD { int shminf(int shmid, struct shmid_pi *buf); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/dev/hwpmc/hwpmc_mod.c
===================================================================
--- sys/dev/hwpmc/hwpmc_mod.c (revision 249257)
+++ sys/dev/hwpmc/hwpmc_mod.c (working copy)
@@ -1780,7 +1780,7 @@
}
vm_map_unlock_read(map);
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
return;
}
Index: sys/compat/freebsd32/freebsd32_systrace_args.c
===================================================================
--- sys/compat/freebsd32/freebsd32_systrace_args.c (revision 249257)
+++ sys/compat/freebsd32/freebsd32_systrace_args.c (working copy)
@@ -3058,6 +3058,14 @@
*n_args = 6;
break;
}
+ /* shminf */
+ case 533: {
+ struct shminf_args *p = params;
+ iarg[0] = p->shmid; /* int */
+ uarg[1] = (intptr_t) p->buf; /* struct shmid_pi * */
+ *n_args = 2;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -8167,6 +8175,19 @@
break;
};
break;
+ /* shminf */
+ case 533:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct shmid_pi *";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
Index: sys/compat/freebsd32/freebsd32_syscalls.c
===================================================================
--- sys/compat/freebsd32/freebsd32_syscalls.c (revision 249257)
+++ sys/compat/freebsd32/freebsd32_syscalls.c (working copy)
@@ -556,4 +556,5 @@
"freebsd32_posix_fallocate", /* 530 = freebsd32_posix_fallocate */
"freebsd32_posix_fadvise", /* 531 = freebsd32_posix_fadvise */
"freebsd32_wait6", /* 532 = freebsd32_wait6 */
+ "shminf", /* 533 = shminf */
};
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master (revision 249257)
+++ sys/compat/freebsd32/syscalls.master (working copy)
@@ -1001,4 +1001,5 @@
int *status, int options, \
struct wrusage32 *wrusage, \
siginfo_t *info); }
+533 AUE_SHMINF NOSTD|NOPROTO { int shminf(int shmid, struct shmid_pi *buf); }
Index: sys/compat/freebsd32/freebsd32_syscall.h
===================================================================
--- sys/compat/freebsd32/freebsd32_syscall.h (revision 249257)
+++ sys/compat/freebsd32/freebsd32_syscall.h (working copy)
@@ -426,4 +426,5 @@
#define FREEBSD32_SYS_freebsd32_posix_fallocate 530
#define FREEBSD32_SYS_freebsd32_posix_fadvise 531
#define FREEBSD32_SYS_freebsd32_wait6 532
-#define FREEBSD32_SYS_MAXSYSCALL 533
+#define FREEBSD32_SYS_shminf 533
+#define FREEBSD32_SYS_MAXSYSCALL 534
Index: sys/compat/freebsd32/freebsd32_sysent.c
===================================================================
--- sys/compat/freebsd32/freebsd32_sysent.c (revision 249257)
+++ sys/compat/freebsd32/freebsd32_sysent.c (working copy)
@@ -593,4 +593,5 @@
{ AS(freebsd32_posix_fallocate_args), (sy_call_t *)freebsd32_posix_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 530 = freebsd32_posix_fallocate */
{ AS(freebsd32_posix_fadvise_args), (sy_call_t *)freebsd32_posix_fadvise, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 531 = freebsd32_posix_fadvise */
{ AS(freebsd32_wait6_args), (sy_call_t *)freebsd32_wait6, AUE_WAIT6, NULL, 0, 0, 0, SY_THR_STATIC }, /* 532 = freebsd32_wait6 */
+ { AS(shminf_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 533 = shminf */
};
Index: sys/compat/linprocfs/linprocfs.c
===================================================================
--- sys/compat/linprocfs/linprocfs.c (revision 249257)
+++ sys/compat/linprocfs/linprocfs.c (working copy)
@@ -1114,7 +1114,7 @@
}
}
vm_map_unlock_read(map);
- vmspace_free(vm);
+ vmspace_free(vm, &p->p_pid);
return (error);
}
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[email protected]"