svn commit: r189283 - in head: . lib/libc/sys sys/kern sys/sys usr.bin/ipcs

Konstantin Belousov kib at FreeBSD.org
Mon Mar 2 10:53:33 PST 2009


Author: kib
Date: Mon Mar  2 18:53:30 2009
New Revision: 189283
URL: http://svn.freebsd.org/changeset/base/189283

Log:
  Correct types of variables used to track amount of allocated SysV shared
  memory from int to size_t. Implement a workaround for current ABI not
  allowing to properly save size for and report more then 2Gb sized segment
  of shared memory.
  
  This makes it possible to use > 2 Gb shared memory segments on 64bit
  architectures. Please note the new BUGS section in shmctl(2) and
  UPDATING note for limitations of this temporal solution.
  
  Reviewed by:	csjp
  Tested by:	Nikolay Dzham <i levsha org ua>
  MFC after:	2 weeks

Modified:
  head/UPDATING
  head/lib/libc/sys/shmctl.2
  head/sys/kern/sysv_shm.c
  head/sys/sys/shm.h
  head/usr.bin/ipcs/ipcs.c

Modified: head/UPDATING
==============================================================================
--- head/UPDATING	Mon Mar  2 18:43:50 2009	(r189282)
+++ head/UPDATING	Mon Mar  2 18:53:30 2009	(r189283)
@@ -22,6 +22,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.
 	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.

Modified: head/lib/libc/sys/shmctl.2
==============================================================================
--- head/lib/libc/sys/shmctl.2	Mon Mar  2 18:43:50 2009	(r189282)
+++ head/lib/libc/sys/shmctl.2	Mon Mar  2 18:53:30 2009	(r189283)
@@ -133,6 +133,15 @@ the shared memory segment's owner or cre
 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 ,

Modified: head/sys/kern/sysv_shm.c
==============================================================================
--- head/sys/kern/sysv_shm.c	Mon Mar  2 18:43:50 2009	(r189282)
+++ head/sys/kern/sysv_shm.c	Mon Mar  2 18:53:30 2009	(r189283)
@@ -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, 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;

Modified: head/sys/sys/shm.h
==============================================================================
--- head/sys/sys/shm.h	Mon Mar  2 18:43:50 2009	(r189282)
+++ head/sys/sys/shm.h	Mon Mar  2 18:53:30 2009	(r189283)
@@ -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;

Modified: head/usr.bin/ipcs/ipcs.c
==============================================================================
--- head/usr.bin/ipcs/ipcs.c	Mon Mar  2 18:43:50 2009	(r189282)
+++ head/usr.bin/ipcs/ipcs.c	Mon Mar  2 18:53:30 2009	(r189283)
@@ -452,8 +452,8 @@ print_kshmptr(int i, int option, struct 
 		    kshmptr->u.shm_nattch);
 
 	if (option & BIGGEST)
-		printf(" %12d",
-		    kshmptr->u.shm_segsz);
+		printf(" %12zu",
+		    kshmptr->shm_bsegsz);
 
 	if (option & PID)
 		printf(" %12d %12d",


More information about the svn-src-all mailing list