Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/uipc_shm.c
Show First 20 Lines • Show All 444 Lines • ▼ Show 20 Lines | rl_cookie = rangelock_wlock(&shmfd->shm_rl, uio->uio_offset, | ||||
size, &shmfd->shm_mtx); | size, &shmfd->shm_mtx); | ||||
} | } | ||||
if ((shmfd->shm_seals & F_SEAL_WRITE) != 0) { | if ((shmfd->shm_seals & F_SEAL_WRITE) != 0) { | ||||
error = EPERM; | error = EPERM; | ||||
} else { | } else { | ||||
error = 0; | error = 0; | ||||
if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0 && | if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0 && | ||||
size > shmfd->shm_size) { | size > shmfd->shm_size) { | ||||
VM_OBJECT_WLOCK(shmfd->shm_object); | error = shm_dotruncate_cookie(shmfd, size, rl_cookie); | ||||
error = shm_dotruncate_locked(shmfd, size, rl_cookie); | |||||
VM_OBJECT_WUNLOCK(shmfd->shm_object); | |||||
} | } | ||||
if (error == 0) | if (error == 0) | ||||
error = uiomove_object(shmfd->shm_object, | error = uiomove_object(shmfd->shm_object, | ||||
shmfd->shm_size, uio); | shmfd->shm_size, uio); | ||||
} | } | ||||
rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | ||||
foffset_unlock_uio(fp, uio, flags); | foffset_unlock_uio(fp, uio, flags); | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 298 Lines • ▼ Show 20 Lines | |||||
#if 0 | #if 0 | ||||
vm_object_page_remove(object, newobjsz, oldobjsz, 0); | vm_object_page_remove(object, newobjsz, oldobjsz, 0); | ||||
object->size = newobjsz; | object->size = newobjsz; | ||||
shmfd->shm_size = length; | shmfd->shm_size = length; | ||||
return (0); | return (0); | ||||
#endif | #endif | ||||
} | } | ||||
if ((shmfd->shm_seals & F_SEAL_GROW) != 0) | |||||
return (EPERM); | |||||
aflags = VM_ALLOC_NORMAL | VM_ALLOC_ZERO; | aflags = VM_ALLOC_NORMAL | VM_ALLOC_ZERO; | ||||
if (shmfd->shm_lp_alloc_policy == SHM_LARGEPAGE_ALLOC_NOWAIT) | if (shmfd->shm_lp_alloc_policy == SHM_LARGEPAGE_ALLOC_NOWAIT) | ||||
aflags |= VM_ALLOC_WAITFAIL; | aflags |= VM_ALLOC_WAITFAIL; | ||||
try = 0; | try = 0; | ||||
/* | /* | ||||
* Extend shmfd and object, keeping all already fully | * Extend shmfd and object, keeping all already fully | ||||
* allocated large pages intact even on error, because dropped | * allocated large pages intact even on error, because dropped | ||||
▲ Show 20 Lines • Show All 633 Lines • ▼ Show 20 Lines | out: | ||||
free(path_from, M_SHMFD); | free(path_from, M_SHMFD); | ||||
free(path_to, M_SHMFD); | free(path_to, M_SHMFD); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
shm_mmap_large(struct shmfd *shmfd, vm_map_t map, vm_offset_t *addr, | shm_mmap_large(struct shmfd *shmfd, vm_map_t map, vm_offset_t *addr, | ||||
vm_size_t size, vm_prot_t prot, vm_prot_t max_prot, int flags, | vm_size_t size, vm_prot_t prot, vm_prot_t max_prot, int flags, | ||||
vm_ooffset_t foff, bool writecounted, struct thread *td) | vm_ooffset_t foff, struct thread *td) | ||||
{ | { | ||||
struct vmspace *vms; | struct vmspace *vms; | ||||
vm_map_entry_t next_entry, prev_entry; | vm_map_entry_t next_entry, prev_entry; | ||||
vm_offset_t align, mask, maxaddr; | vm_offset_t align, mask, maxaddr; | ||||
int docow, error, rv, try; | int docow, error, rv, try; | ||||
bool curmap; | bool curmap; | ||||
if (shmfd->shm_lp_psind == 0) | if (shmfd->shm_lp_psind == 0) | ||||
Show All 15 Lines | if (curmap) { | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
} | } | ||||
docow = shmfd->shm_lp_psind << MAP_SPLIT_BOUNDARY_SHIFT; | docow = shmfd->shm_lp_psind << MAP_SPLIT_BOUNDARY_SHIFT; | ||||
docow |= MAP_INHERIT_SHARE; | docow |= MAP_INHERIT_SHARE; | ||||
if ((flags & MAP_NOCORE) != 0) | if ((flags & MAP_NOCORE) != 0) | ||||
docow |= MAP_DISABLE_COREDUMP; | docow |= MAP_DISABLE_COREDUMP; | ||||
if (writecounted) | |||||
docow |= MAP_WRITECOUNT; | |||||
mask = pagesizes[shmfd->shm_lp_psind] - 1; | mask = pagesizes[shmfd->shm_lp_psind] - 1; | ||||
if ((foff & mask) != 0) | if ((foff & mask) != 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
maxaddr = vm_map_max(map); | maxaddr = vm_map_max(map); | ||||
#ifdef MAP_32BIT | #ifdef MAP_32BIT | ||||
if ((flags & MAP_32BIT) != 0 && maxaddr > MAP_32BIT_MAX_ADDR) | if ((flags & MAP_32BIT) != 0 && maxaddr > MAP_32BIT_MAX_ADDR) | ||||
maxaddr = MAP_32BIT_MAX_ADDR; | maxaddr = MAP_32BIT_MAX_ADDR; | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | if (error != 0) | ||||
goto out; | goto out; | ||||
#endif | #endif | ||||
mtx_lock(&shm_timestamp_lock); | mtx_lock(&shm_timestamp_lock); | ||||
vfs_timestamp(&shmfd->shm_atime); | vfs_timestamp(&shmfd->shm_atime); | ||||
mtx_unlock(&shm_timestamp_lock); | mtx_unlock(&shm_timestamp_lock); | ||||
vm_object_reference(shmfd->shm_object); | vm_object_reference(shmfd->shm_object); | ||||
if (writecnt) | |||||
vm_pager_update_writecount(shmfd->shm_object, 0, objsize); | |||||
if (shm_largepage(shmfd)) { | if (shm_largepage(shmfd)) { | ||||
writecnt = false; | |||||
error = shm_mmap_large(shmfd, map, addr, objsize, prot, | error = shm_mmap_large(shmfd, map, addr, objsize, prot, | ||||
maxprot, flags, foff, writecnt, td); | maxprot, flags, foff, td); | ||||
} else { | } else { | ||||
if (writecnt) { | |||||
vm_pager_update_writecount(shmfd->shm_object, 0, | |||||
objsize); | |||||
} | |||||
error = vm_mmap_object(map, addr, objsize, prot, maxprot, flags, | error = vm_mmap_object(map, addr, objsize, prot, maxprot, flags, | ||||
shmfd->shm_object, foff, writecnt, td); | shmfd->shm_object, foff, writecnt, td); | ||||
} | } | ||||
if (error != 0) { | if (error != 0) { | ||||
if (writecnt) | if (writecnt) | ||||
vm_pager_release_writecount(shmfd->shm_object, 0, | vm_pager_release_writecount(shmfd->shm_object, 0, | ||||
markj: Doesn't this need to move too? | |||||
Done Inline ActionsI think a better fix is to reset writecount to false for largepage. And not pass writecnt to shm_mmap_large at all, there is no reason to set MAP_ENTRY_WRITECNT although it is safe as nop for now. kib: I think a better fix is to reset writecount to false for largepage. And not pass writecnt to… | |||||
objsize); | objsize); | ||||
vm_object_deallocate(shmfd->shm_object); | vm_object_deallocate(shmfd->shm_object); | ||||
} | } | ||||
out: | out: | ||||
rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 216 Lines • ▼ Show 20 Lines | shm_add_seals(struct file *fp, int seals) | ||||
/* Even already-set seals should result in EPERM. */ | /* Even already-set seals should result in EPERM. */ | ||||
if ((shmfd->shm_seals & F_SEAL_SEAL) != 0) { | if ((shmfd->shm_seals & F_SEAL_SEAL) != 0) { | ||||
error = EPERM; | error = EPERM; | ||||
goto out; | goto out; | ||||
} | } | ||||
nseals = seals & ~shmfd->shm_seals; | nseals = seals & ~shmfd->shm_seals; | ||||
if ((nseals & F_SEAL_WRITE) != 0) { | if ((nseals & F_SEAL_WRITE) != 0) { | ||||
if (shm_largepage(shmfd)) { | |||||
error = ENOTSUP; | |||||
goto out; | |||||
} | |||||
/* | /* | ||||
* The rangelock above prevents writable mappings from being | * The rangelock above prevents writable mappings from being | ||||
* added after we've started applying seals. The RLOCK here | * added after we've started applying seals. The RLOCK here | ||||
* is to avoid torn reads on ILP32 arches as unmapping/reducing | * is to avoid torn reads on ILP32 arches as unmapping/reducing | ||||
* writemappings will be done without a rangelock. | * writemappings will be done without a rangelock. | ||||
*/ | */ | ||||
VM_OBJECT_RLOCK(shmfd->shm_object); | VM_OBJECT_RLOCK(shmfd->shm_object); | ||||
writemappings = shmfd->shm_object->un_pager.swp.writemappings; | writemappings = shmfd->shm_object->un_pager.swp.writemappings; | ||||
▲ Show 20 Lines • Show All 126 Lines • Show Last 20 Lines |
Doesn't this need to move too?