Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/uipc_shm.c
Show First 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio) | ||||
* pageout daemon does not need to acquire the tmpfs vnode | * pageout daemon does not need to acquire the tmpfs vnode | ||||
* lock to page out tobj's pages because tobj is a OBJT_SWAP | * lock to page out tobj's pages because tobj is a OBJT_SWAP | ||||
* type object. | * type object. | ||||
*/ | */ | ||||
rv = vm_page_grab_valid(&m, obj, idx, | rv = vm_page_grab_valid(&m, obj, idx, | ||||
VM_ALLOC_NORMAL | VM_ALLOC_SBUSY | VM_ALLOC_IGN_SBUSY); | VM_ALLOC_NORMAL | VM_ALLOC_SBUSY | VM_ALLOC_IGN_SBUSY); | ||||
if (rv != VM_PAGER_OK) { | if (rv != VM_PAGER_OK) { | ||||
VM_OBJECT_WUNLOCK(obj); | VM_OBJECT_WUNLOCK(obj); | ||||
printf("uiomove_object: vm_obj %p idx %jd pager error %d\n", | if (bootverbose) { | ||||
obj, idx, rv); | printf("uiomove_object: vm_obj %p idx %jd " | ||||
return (EIO); | "pager error %d\n", obj, idx, rv); | ||||
} | } | ||||
return (rv == VM_PAGER_AGAIN ? ENOSPC : EIO); | |||||
} | |||||
VM_OBJECT_WUNLOCK(obj); | VM_OBJECT_WUNLOCK(obj); | ||||
found: | found: | ||||
error = uiomove_fromphys(&m, offset, tlen, uio); | error = uiomove_fromphys(&m, offset, tlen, uio); | ||||
if (uio->uio_rw == UIO_WRITE && error == 0) | if (uio->uio_rw == UIO_WRITE && error == 0) | ||||
vm_page_set_dirty(m); | vm_page_set_dirty(m); | ||||
vm_page_activate(m); | vm_page_activate(m); | ||||
vm_page_sunbusy(m); | vm_page_sunbusy(m); | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
bool | bool | ||||
shm_largepage(struct shmfd *shmfd) | shm_largepage(struct shmfd *shmfd) | ||||
{ | { | ||||
return (shmfd->shm_object->type == OBJT_PHYS); | return (shmfd->shm_object->type == OBJT_PHYS); | ||||
} | } | ||||
static void | |||||
shm_pager_freespace(vm_object_t obj, vm_pindex_t start, vm_size_t size) | |||||
{ | |||||
struct shmfd *shm; | |||||
vm_size_t c; | |||||
swap_pager_freespace(obj, start, size, &c); | |||||
if (c == 0) | |||||
return; | |||||
shm = obj->un_pager.swp.swp_priv; | |||||
if (shm == NULL) | |||||
return; | |||||
KASSERT(shm->shm_pages >= c, | |||||
("shm %p pages %jd free %jd", shm, | |||||
(uintmax_t)shm->shm_pages, (uintmax_t)c)); | |||||
shm->shm_pages -= c; | |||||
} | |||||
static void | |||||
shm_page_inserted(vm_object_t obj, vm_page_t m) | |||||
{ | |||||
struct shmfd *shm; | |||||
shm = obj->un_pager.swp.swp_priv; | |||||
if (shm == NULL) | |||||
return; | |||||
shm->shm_pages += 1; | |||||
} | |||||
static void | |||||
shm_page_removed(vm_object_t obj, vm_page_t m) | |||||
{ | |||||
struct shmfd *shm; | |||||
shm = obj->un_pager.swp.swp_priv; | |||||
if (shm == NULL) | |||||
return; | |||||
KASSERT(shm->shm_pages >= 1, | |||||
("shm %p pages %jd free 1", shm, | |||||
(uintmax_t)shm->shm_pages)); | |||||
shm->shm_pages += 1; | |||||
} | |||||
static struct pagerops shm_swap_pager_ops = { | |||||
.pgo_kvme_type = KVME_TYPE_SWAP, | |||||
.pgo_freespace = shm_pager_freespace, | |||||
.pgo_page_inserted = shm_page_inserted, | |||||
.pgo_page_removed = shm_page_removed, | |||||
}; | |||||
static int shmfd_pager_type = -1; | |||||
static int | static int | ||||
shm_seek(struct file *fp, off_t offset, int whence, struct thread *td) | shm_seek(struct file *fp, off_t offset, int whence, struct thread *td) | ||||
{ | { | ||||
struct shmfd *shmfd; | struct shmfd *shmfd; | ||||
off_t foffset; | off_t foffset; | ||||
int error; | int error; | ||||
shmfd = fp->f_data; | shmfd = fp->f_data; | ||||
▲ Show 20 Lines • Show All 200 Lines • ▼ Show 20 Lines | #endif | ||||
/* | /* | ||||
* Attempt to return sanish values for fstat() on a memory file | * Attempt to return sanish values for fstat() on a memory file | ||||
* descriptor. | * descriptor. | ||||
*/ | */ | ||||
bzero(sb, sizeof(*sb)); | bzero(sb, sizeof(*sb)); | ||||
sb->st_blksize = PAGE_SIZE; | sb->st_blksize = PAGE_SIZE; | ||||
sb->st_size = shmfd->shm_size; | sb->st_size = shmfd->shm_size; | ||||
sb->st_blocks = howmany(sb->st_size, sb->st_blksize); | |||||
mtx_lock(&shm_timestamp_lock); | mtx_lock(&shm_timestamp_lock); | ||||
sb->st_atim = shmfd->shm_atime; | sb->st_atim = shmfd->shm_atime; | ||||
sb->st_ctim = shmfd->shm_ctime; | sb->st_ctim = shmfd->shm_ctime; | ||||
sb->st_mtim = shmfd->shm_mtime; | sb->st_mtim = shmfd->shm_mtime; | ||||
sb->st_birthtim = shmfd->shm_birthtime; | sb->st_birthtim = shmfd->shm_birthtime; | ||||
sb->st_mode = S_IFREG | shmfd->shm_mode; /* XXX */ | sb->st_mode = S_IFREG | shmfd->shm_mode; /* XXX */ | ||||
sb->st_uid = shmfd->shm_uid; | sb->st_uid = shmfd->shm_uid; | ||||
sb->st_gid = shmfd->shm_gid; | sb->st_gid = shmfd->shm_gid; | ||||
mtx_unlock(&shm_timestamp_lock); | mtx_unlock(&shm_timestamp_lock); | ||||
sb->st_dev = shm_dev_ino; | sb->st_dev = shm_dev_ino; | ||||
sb->st_ino = shmfd->shm_ino; | sb->st_ino = shmfd->shm_ino; | ||||
sb->st_nlink = shmfd->shm_object->ref_count; | sb->st_nlink = shmfd->shm_object->ref_count; | ||||
if (shm_largepage(shmfd)) { | |||||
sb->st_blocks = shmfd->shm_object->size / | sb->st_blocks = shmfd->shm_object->size / | ||||
(pagesizes[shmfd->shm_lp_psind] >> PAGE_SHIFT); | (pagesizes[shmfd->shm_lp_psind] >> PAGE_SHIFT); | ||||
} else { | |||||
sb->st_blocks = shmfd->shm_pages; | |||||
} | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
shm_close(struct file *fp, struct thread *td) | shm_close(struct file *fp, struct thread *td) | ||||
{ | { | ||||
struct shmfd *shmfd; | struct shmfd *shmfd; | ||||
▲ Show 20 Lines • Show All 294 Lines • ▼ Show 20 Lines | shm_alloc(struct ucred *ucred, mode_t mode, bool largepage) | ||||
shmfd->shm_gid = ucred->cr_gid; | shmfd->shm_gid = ucred->cr_gid; | ||||
shmfd->shm_mode = mode; | shmfd->shm_mode = mode; | ||||
if (largepage) { | if (largepage) { | ||||
shmfd->shm_object = phys_pager_allocate(NULL, | shmfd->shm_object = phys_pager_allocate(NULL, | ||||
&shm_largepage_phys_ops, NULL, shmfd->shm_size, | &shm_largepage_phys_ops, NULL, shmfd->shm_size, | ||||
VM_PROT_DEFAULT, 0, ucred); | VM_PROT_DEFAULT, 0, ucred); | ||||
shmfd->shm_lp_alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT; | shmfd->shm_lp_alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT; | ||||
} else { | } else { | ||||
shmfd->shm_object = vm_pager_allocate(OBJT_SWAP, NULL, | shmfd->shm_object = vm_pager_allocate(shmfd_pager_type, NULL, | ||||
shmfd->shm_size, VM_PROT_DEFAULT, 0, ucred); | shmfd->shm_size, VM_PROT_DEFAULT, 0, ucred); | ||||
} | } | ||||
KASSERT(shmfd->shm_object != NULL, ("shm_create: vm_pager_allocate")); | KASSERT(shmfd->shm_object != NULL, ("shm_create: vm_pager_allocate")); | ||||
vfs_timestamp(&shmfd->shm_birthtime); | vfs_timestamp(&shmfd->shm_birthtime); | ||||
shmfd->shm_atime = shmfd->shm_mtime = shmfd->shm_ctime = | shmfd->shm_atime = shmfd->shm_mtime = shmfd->shm_ctime = | ||||
shmfd->shm_birthtime; | shmfd->shm_birthtime; | ||||
shmfd->shm_ino = alloc_unr64(&shm_ino_unr); | shmfd->shm_ino = alloc_unr64(&shm_ino_unr); | ||||
refcount_init(&shmfd->shm_refs, 1); | refcount_init(&shmfd->shm_refs, 1); | ||||
Show All 13 Lines | shm_hold(struct shmfd *shmfd) | ||||
refcount_acquire(&shmfd->shm_refs); | refcount_acquire(&shmfd->shm_refs); | ||||
return (shmfd); | return (shmfd); | ||||
} | } | ||||
void | void | ||||
shm_drop(struct shmfd *shmfd) | shm_drop(struct shmfd *shmfd) | ||||
{ | { | ||||
vm_object_t obj; | |||||
if (refcount_release(&shmfd->shm_refs)) { | if (refcount_release(&shmfd->shm_refs)) { | ||||
#ifdef MAC | #ifdef MAC | ||||
mac_posixshm_destroy(shmfd); | mac_posixshm_destroy(shmfd); | ||||
#endif | #endif | ||||
rangelock_destroy(&shmfd->shm_rl); | rangelock_destroy(&shmfd->shm_rl); | ||||
mtx_destroy(&shmfd->shm_mtx); | mtx_destroy(&shmfd->shm_mtx); | ||||
vm_object_deallocate(shmfd->shm_object); | obj = shmfd->shm_object; | ||||
if (!shm_largepage(shmfd)) { | |||||
VM_OBJECT_WLOCK(obj); | |||||
obj->un_pager.swp.swp_priv = NULL; | |||||
VM_OBJECT_WUNLOCK(obj); | |||||
} | |||||
vm_object_deallocate(obj); | |||||
free(shmfd, M_SHMFD); | free(shmfd, M_SHMFD); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Determine if the credentials have sufficient permissions for a | * Determine if the credentials have sufficient permissions for a | ||||
* specified combination of FREAD and FWRITE. | * specified combination of FREAD and FWRITE. | ||||
*/ | */ | ||||
Show All 22 Lines | shm_init(void *arg) | ||||
int i; | int i; | ||||
mtx_init(&shm_timestamp_lock, "shm timestamps", NULL, MTX_DEF); | mtx_init(&shm_timestamp_lock, "shm timestamps", NULL, MTX_DEF); | ||||
sx_init(&shm_dict_lock, "shm dictionary"); | sx_init(&shm_dict_lock, "shm dictionary"); | ||||
shm_dictionary = hashinit(1024, M_SHMFD, &shm_hash); | shm_dictionary = hashinit(1024, M_SHMFD, &shm_hash); | ||||
new_unrhdr64(&shm_ino_unr, 1); | new_unrhdr64(&shm_ino_unr, 1); | ||||
shm_dev_ino = devfs_alloc_cdp_inode(); | shm_dev_ino = devfs_alloc_cdp_inode(); | ||||
KASSERT(shm_dev_ino > 0, ("shm dev inode not initialized")); | KASSERT(shm_dev_ino > 0, ("shm dev inode not initialized")); | ||||
shmfd_pager_type = vm_pager_alloc_dyn_type(&shm_swap_pager_ops, | |||||
OBJT_SWAP); | |||||
MPASS(shmfd_pager_type != -1); | |||||
for (i = 1; i < MAXPAGESIZES; i++) { | for (i = 1; i < MAXPAGESIZES; i++) { | ||||
if (pagesizes[i] == 0) | if (pagesizes[i] == 0) | ||||
break; | break; | ||||
#define M (1024 * 1024) | #define M (1024 * 1024) | ||||
#define G (1024 * M) | #define G (1024 * M) | ||||
if (pagesizes[i] >= G) | if (pagesizes[i] >= G) | ||||
snprintf(name, sizeof(name), "%luG", pagesizes[i] / G); | snprintf(name, sizeof(name), "%luG", pagesizes[i] / G); | ||||
▲ Show 20 Lines • Show All 1,149 Lines • Show Last 20 Lines |