Implement shmat(2) flag SHM_REMAP.
Based on the description in Linux man page. Reviewed by: markj, ngie (previous version) Sponsored by: Mellanox Technologies MFC after: 1 week Differential revision: https://reviews.freebsd.org/D18837
This commit is contained in:
parent
b1df0520f7
commit
f34dbcf7d0
@ -47,6 +47,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/msg.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/sem.h>
|
||||
@ -772,17 +773,25 @@ ATF_TC_BODY(shm, tc)
|
||||
atf_tc_fail("sender: received unexpected signal");
|
||||
}
|
||||
|
||||
ATF_TC_CLEANUP(shm, tc)
|
||||
static void
|
||||
shmid_cleanup(const char *name)
|
||||
{
|
||||
int sender_shmid;
|
||||
int shmid;
|
||||
|
||||
/*
|
||||
* Remove the shared memory area if it exists.
|
||||
*/
|
||||
sender_shmid = read_int("sender_shmid");
|
||||
if (sender_shmid != -1)
|
||||
if (shmctl(sender_shmid, IPC_RMID, NULL) == -1)
|
||||
shmid = read_int(name);
|
||||
if (shmid != -1) {
|
||||
if (shmctl(shmid, IPC_RMID, NULL) == -1)
|
||||
err(1, "shmctl IPC_RMID");
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC_CLEANUP(shm, tc)
|
||||
{
|
||||
|
||||
shmid_cleanup("sender_shmid");
|
||||
}
|
||||
|
||||
void
|
||||
@ -837,12 +846,53 @@ sharer(void)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef SHM_REMAP
|
||||
ATF_TC_WITH_CLEANUP(shm_remap);
|
||||
ATF_TC_HEAD(shm_remap, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Checks SHM_REMAP");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(shm_remap, tc)
|
||||
{
|
||||
char *shm_buf;
|
||||
int shmid_remap;
|
||||
|
||||
pgsize = sysconf(_SC_PAGESIZE);
|
||||
|
||||
shmkey = get_ftok(4160);
|
||||
ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed");
|
||||
|
||||
ATF_REQUIRE_MSG((shmid_remap = shmget(shmkey, pgsize,
|
||||
IPC_CREAT | 0640)) != -1, "shmget: %d", errno);
|
||||
write_int("shmid_remap", shmid_remap);
|
||||
|
||||
ATF_REQUIRE_MSG((shm_buf = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_PRIVATE, -1, 0)) != MAP_FAILED, "mmap: %d", errno);
|
||||
|
||||
ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, 0) == (void *)-1,
|
||||
"shmat without MAP_REMAP succeeded");
|
||||
ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, SHM_REMAP) == shm_buf,
|
||||
"shmat(SHM_REMAP): %d", errno);
|
||||
}
|
||||
|
||||
ATF_TC_CLEANUP(shm_remap, tc)
|
||||
{
|
||||
|
||||
shmid_cleanup("shmid_remap");
|
||||
}
|
||||
#endif /* SHM_REMAP */
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, msg);
|
||||
ATF_TP_ADD_TC(tp, sem);
|
||||
ATF_TP_ADD_TC(tp, shm);
|
||||
#ifdef SHM_REMAP
|
||||
ATF_TP_ADD_TC(tp, shm_remap);
|
||||
#endif
|
||||
|
||||
return atf_no_error();
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 25, 2018
|
||||
.Dd January 14, 2019
|
||||
.Dt SHMAT 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -64,17 +64,38 @@ kernel.
|
||||
.It
|
||||
If
|
||||
.Fa addr
|
||||
is nonzero and SHM_RND is not specified in
|
||||
is nonzero and
|
||||
.Va SHM_RND
|
||||
is not specified in
|
||||
.Fa flag ,
|
||||
the segment is attached the specified address.
|
||||
.It
|
||||
If
|
||||
.Fa addr
|
||||
is specified and SHM_RND is specified,
|
||||
is specified and
|
||||
.Va SHM_RND
|
||||
is specified,
|
||||
.Fa addr
|
||||
is rounded down to the nearest multiple of SHMLBA.
|
||||
.El
|
||||
.Pp
|
||||
If the
|
||||
.Va SHM_REMAP
|
||||
flag is specified and the passed
|
||||
.Fa addr
|
||||
is not
|
||||
.Dv NULL ,
|
||||
any existing mappings in the virtual addresses range are
|
||||
cleared before the segment is attached.
|
||||
If the flag is not specified,
|
||||
.Fa addr
|
||||
is not
|
||||
.Dv NULL ,
|
||||
and the virtual address range contains
|
||||
some pre-existing mappings, the
|
||||
.Fn shmat
|
||||
call fails.
|
||||
.Pp
|
||||
The
|
||||
.Fn shmdt
|
||||
system call
|
||||
@ -104,6 +125,14 @@ The
|
||||
.Fa addr
|
||||
argument
|
||||
was not an acceptable address.
|
||||
.It Bq Er ENOMEM
|
||||
The specified
|
||||
.Fa addr
|
||||
cannot be used for mapping, for instance due to the amount of available
|
||||
space being smaller than the segment size,
|
||||
or because pre-existing mappings are in the range and no
|
||||
.Va SHM_REMAP
|
||||
flag was provided.
|
||||
.It Bq Er EMFILE
|
||||
Failed to attach the shared memory segment because the per-process
|
||||
.Va kern.ipc.shmseg
|
||||
|
@ -388,7 +388,7 @@ kern_shmat_locked(struct thread *td, int shmid, const void *shmaddr,
|
||||
vm_offset_t attach_va;
|
||||
vm_prot_t prot;
|
||||
vm_size_t size;
|
||||
int error, i, rv;
|
||||
int cow, error, find_space, i, rv;
|
||||
|
||||
AUDIT_ARG_SVIPC_ID(shmid);
|
||||
AUDIT_ARG_VALUE(shmflg);
|
||||
@ -427,6 +427,7 @@ kern_shmat_locked(struct thread *td, int shmid, const void *shmaddr,
|
||||
return (EMFILE);
|
||||
size = round_page(shmseg->u.shm_segsz);
|
||||
prot = VM_PROT_READ;
|
||||
cow = MAP_INHERIT_SHARE | MAP_PREFAULT_PARTIAL;
|
||||
if ((shmflg & SHM_RDONLY) == 0)
|
||||
prot |= VM_PROT_WRITE;
|
||||
if (shmaddr != NULL) {
|
||||
@ -436,6 +437,9 @@ kern_shmat_locked(struct thread *td, int shmid, const void *shmaddr,
|
||||
attach_va = (vm_offset_t)shmaddr;
|
||||
else
|
||||
return (EINVAL);
|
||||
if ((shmflg & SHM_REMAP) != 0)
|
||||
cow |= MAP_REMAP;
|
||||
find_space = VMFS_NO_SPACE;
|
||||
} else {
|
||||
/*
|
||||
* This is just a hint to vm_map_find() about where to
|
||||
@ -443,12 +447,12 @@ kern_shmat_locked(struct thread *td, int shmid, const void *shmaddr,
|
||||
*/
|
||||
attach_va = round_page((vm_offset_t)p->p_vmspace->vm_daddr +
|
||||
lim_max(td, RLIMIT_DATA));
|
||||
find_space = VMFS_OPTIMAL_SPACE;
|
||||
}
|
||||
|
||||
vm_object_reference(shmseg->object);
|
||||
rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->object, 0, &attach_va,
|
||||
size, 0, shmaddr != NULL ? VMFS_NO_SPACE : VMFS_OPTIMAL_SPACE,
|
||||
prot, prot, MAP_INHERIT_SHARE | MAP_PREFAULT_PARTIAL);
|
||||
size, 0, find_space, prot, prot, cow);
|
||||
if (rv != KERN_SUCCESS) {
|
||||
vm_object_deallocate(shmseg->object);
|
||||
return (ENOMEM);
|
||||
|
@ -52,6 +52,7 @@
|
||||
|
||||
#define SHM_RDONLY 010000 /* Attach read-only (else read-write) */
|
||||
#define SHM_RND 020000 /* Round attach address to SHMLBA */
|
||||
#define SHM_REMAP 030000 /* Unmap before mapping */
|
||||
#define SHMLBA PAGE_SIZE /* Segment low boundary address multiple */
|
||||
|
||||
/* "official" access mode definitions; somewhat braindead since you have
|
||||
|
@ -1565,6 +1565,8 @@ vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
|
||||
KASSERT((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) == 0 ||
|
||||
object == NULL,
|
||||
("vm_map_find: non-NULL backing object for stack"));
|
||||
MPASS((cow & MAP_REMAP) == 0 || (find_space == VMFS_NO_SPACE &&
|
||||
(cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) == 0));
|
||||
if (find_space == VMFS_OPTIMAL_SPACE && (object == NULL ||
|
||||
(object->flags & OBJ_COLORED) == 0))
|
||||
find_space = VMFS_ANY_SPACE;
|
||||
@ -1595,6 +1597,14 @@ again:
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
} else if ((cow & MAP_REMAP) != 0) {
|
||||
if (*addr < vm_map_min(map) ||
|
||||
*addr + length > vm_map_max(map) ||
|
||||
*addr + length <= length) {
|
||||
rv = KERN_INVALID_ADDRESS;
|
||||
goto done;
|
||||
}
|
||||
vm_map_delete(map, *addr, *addr + length);
|
||||
}
|
||||
if ((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) != 0) {
|
||||
rv = vm_map_stack_locked(map, *addr, length, sgrowsiz, prot,
|
||||
|
@ -342,6 +342,7 @@ long vmspace_resident_count(struct vmspace *vmspace);
|
||||
#define MAP_DISABLE_COREDUMP 0x0100
|
||||
#define MAP_PREFAULT_MADVISE 0x0200 /* from (user) madvise request */
|
||||
#define MAP_VN_WRITECOUNT 0x0400
|
||||
#define MAP_REMAP 0x0800
|
||||
#define MAP_STACK_GROWS_DOWN 0x1000
|
||||
#define MAP_STACK_GROWS_UP 0x2000
|
||||
#define MAP_ACC_CHARGED 0x4000
|
||||
|
Loading…
x
Reference in New Issue
Block a user