diff --git a/UPDATING b/UPDATING index 2a90933..53dede7 100644 --- a/UPDATING +++ b/UPDATING @@ -22,6 +22,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW: to maximize performance. (To disable malloc debugging, run ln -s aj /etc/malloc.conf.) +20090302: + The workaround is committed to allow to create System V shared + memory segment of size > 2 Gb on the 64-bit architectures. + Due to limitation of the existing ABI, the shm_segsz member + of the struct shmid_ds, returned by shmctl(IPC_STAT) call is + wrong for large segments. Note that limits shall be explicitely + raised to allow such segments to be created. + 20090301: The layout of struct ifnet has changed, requiring a rebuild of all network device driver modules. diff --git a/lib/libc/sys/shmctl.2 b/lib/libc/sys/shmctl.2 index 90c61c9..3e19666 100644 --- a/lib/libc/sys/shmctl.2 +++ b/lib/libc/sys/shmctl.2 @@ -133,6 +133,15 @@ the shared memory segment's owner or creator. Permission denied due to mismatch between operation and mode of shared memory segment. .El +.Sh "BUGS" +The shm_segsz member of the +.Vt shmid_ds +structure has int type, that is too short to represent full range +of the values for segment size, which is allowed to be size_t. +If shared memory limits are raised to allow segments with size > 2 Gb +to be created, be aware that IPC_STAT call may return truncated value +for shm_segsz. +.El .Sh "SEE ALSO" .Xr shmat 2 , .Xr shmdt 2 , diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 4e9854d..a945523 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -121,7 +121,8 @@ static sy_call_t *shmcalls[] = { #define SHMSEG_ALLOCATED 0x0800 #define SHMSEG_WANTED 0x1000 -static int shm_last_free, shm_nused, shm_committed, shmalloced; +static int shm_last_free, shm_nused, shmalloced; +size_t shm_committed; static struct shmid_kernel *shmsegs; struct shmmap_state { @@ -250,7 +251,7 @@ shm_deallocate_segment(shmseg) vm_object_deallocate(shmseg->u.shm_internal); shmseg->u.shm_internal = NULL; - size = round_page(shmseg->u.shm_segsz); + size = round_page(shmseg->shm_bsegsz); shm_committed -= btoc(size); shm_nused--; shmseg->u.shm_perm.mode = SHMSEG_FREE; @@ -270,7 +271,7 @@ shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s) segnum = IPCID_TO_IX(shmmap_s->shmid); shmseg = &shmsegs[segnum]; - size = round_page(shmseg->u.shm_segsz); + size = round_page(shmseg->shm_bsegsz); result = vm_map_remove(&vm->vm_map, shmmap_s->va, shmmap_s->va + size); if (result != KERN_SUCCESS) return (EINVAL); @@ -390,7 +391,7 @@ kern_shmat(td, shmid, shmaddr, shmflg) error = EMFILE; goto done2; } - size = round_page(shmseg->u.shm_segsz); + size = round_page(shmseg->shm_bsegsz); #ifdef VM_PROT_READ_IS_EXEC prot = VM_PROT_READ | VM_PROT_EXECUTE; #else @@ -422,7 +423,8 @@ kern_shmat(td, shmid, shmaddr, shmflg) vm_object_reference(shmseg->u.shm_internal); rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->u.shm_internal, - 0, &attach_va, size, (flags & MAP_FIXED)?0:1, prot, prot, 0); + 0, &attach_va, size, (flags & MAP_FIXED) ? VMFS_NO_SPACE : + VMFS_ANY_SPACE, prot, prot, 0); if (rv != KERN_SUCCESS) { vm_object_deallocate(shmseg->u.shm_internal); error = ENOMEM; @@ -720,7 +722,7 @@ shmget_existing(td, uap, mode, segnum) if (error != 0) return (error); #endif - if (uap->size && uap->size > shmseg->u.shm_segsz) + if (uap->size && uap->size > shmseg->shm_bsegsz) return (EINVAL); td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm); return (0); @@ -732,7 +734,8 @@ shmget_allocate_segment(td, uap, mode) struct shmget_args *uap; int mode; { - int i, segnum, shmid, size; + int i, segnum, shmid; + size_t size; struct ucred *cred = td->td_ucred; struct shmid_kernel *shmseg; vm_object_t shm_object; @@ -790,6 +793,7 @@ shmget_allocate_segment(td, uap, mode) shmseg->u.shm_perm.mode = (shmseg->u.shm_perm.mode & SHMSEG_WANTED) | (mode & ACCESSPERMS) | SHMSEG_ALLOCATED; shmseg->u.shm_segsz = uap->size; + shmseg->shm_bsegsz = uap->size; shmseg->u.shm_cpid = td->td_proc->p_pid; shmseg->u.shm_lpid = shmseg->u.shm_nattch = 0; shmseg->u.shm_atime = shmseg->u.shm_dtime = 0; diff --git a/sys/sys/shm.h b/sys/sys/shm.h index 33ed7b0..c4b1369 100644 --- a/sys/sys/shm.h +++ b/sys/sys/shm.h @@ -108,6 +108,7 @@ struct shminfo { struct shmid_kernel { struct shmid_ds u; struct label *label; /* MAC label */ + size_t shm_bsegsz; }; extern struct shminfo shminfo; diff --git a/usr.bin/ipcs/ipcs.c b/usr.bin/ipcs/ipcs.c index 67364d5..1fd943a 100644 --- a/usr.bin/ipcs/ipcs.c +++ b/usr.bin/ipcs/ipcs.c @@ -452,8 +452,8 @@ print_kshmptr(int i, int option, struct shmid_kernel *kshmptr) kshmptr->u.shm_nattch); if (option & BIGGEST) - printf(" %12d", - kshmptr->u.shm_segsz); + printf(" %12zu", + kshmptr->shm_bsegsz); if (option & PID) printf(" %12d %12d",