1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-17 15:27:36 +00:00

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
This commit is contained in:
Konstantin Belousov 2009-03-02 18:53:30 +00:00
parent 2883703e00
commit 65067cc8b0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=189283
5 changed files with 31 additions and 9 deletions

View File

@ -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.

View File

@ -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 ,

View File

@ -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;

View File

@ -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;

View File

@ -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",