shmfd: account for the actually allocated pages

Return the value as stat(2) st_blocks.

Suggested and reviewed by:	markj (previous version)
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D37097
This commit is contained in:
Konstantin Belousov 2022-11-23 23:26:38 +02:00
parent 37aea2649f
commit 0919f29d91
2 changed files with 79 additions and 5 deletions

View File

@ -347,6 +347,61 @@ shm_largepage(struct shmfd *shmfd)
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;
if (!vm_pager_has_page(obj, m->pindex, NULL, NULL))
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;
if (!vm_pager_has_page(obj, m->pindex, NULL, NULL)) {
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
shm_seek(struct file *fp, off_t offset, int whence, struct thread *td)
{
@ -563,7 +618,6 @@ shm_stat(struct file *fp, struct stat *sb, struct ucred *active_cred)
bzero(sb, sizeof(*sb));
sb->st_blksize = PAGE_SIZE;
sb->st_size = shmfd->shm_size;
sb->st_blocks = howmany(sb->st_size, sb->st_blksize);
mtx_lock(&shm_timestamp_lock);
sb->st_atim = shmfd->shm_atime;
sb->st_ctim = shmfd->shm_ctime;
@ -576,8 +630,12 @@ shm_stat(struct file *fp, struct stat *sb, struct ucred *active_cred)
sb->st_dev = shm_dev_ino;
sb->st_ino = shmfd->shm_ino;
sb->st_nlink = shmfd->shm_object->ref_count;
sb->st_blocks = shmfd->shm_object->size /
(pagesizes[shmfd->shm_lp_psind] >> PAGE_SHIFT);
if (shm_largepage(shmfd)) {
sb->st_blocks = shmfd->shm_object->size /
(pagesizes[shmfd->shm_lp_psind] >> PAGE_SHIFT);
} else {
sb->st_blocks = shmfd->shm_pages;
}
return (0);
}
@ -876,6 +934,7 @@ struct shmfd *
shm_alloc(struct ucred *ucred, mode_t mode, bool largepage)
{
struct shmfd *shmfd;
vm_object_t obj;
shmfd = malloc(sizeof(*shmfd), M_SHMFD, M_WAITOK | M_ZERO);
shmfd->shm_size = 0;
@ -888,8 +947,12 @@ shm_alloc(struct ucred *ucred, mode_t mode, bool largepage)
VM_PROT_DEFAULT, 0, ucred);
shmfd->shm_lp_alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT;
} else {
shmfd->shm_object = vm_pager_allocate(OBJT_SWAP, NULL,
obj = vm_pager_allocate(shmfd_pager_type, NULL,
shmfd->shm_size, VM_PROT_DEFAULT, 0, ucred);
VM_OBJECT_WLOCK(obj);
obj->un_pager.swp.swp_priv = shmfd;
VM_OBJECT_WUNLOCK(obj);
shmfd->shm_object = obj;
}
KASSERT(shmfd->shm_object != NULL, ("shm_create: vm_pager_allocate"));
vfs_timestamp(&shmfd->shm_birthtime);
@ -918,6 +981,7 @@ shm_hold(struct shmfd *shmfd)
void
shm_drop(struct shmfd *shmfd)
{
vm_object_t obj;
if (refcount_release(&shmfd->shm_refs)) {
#ifdef MAC
@ -925,7 +989,13 @@ shm_drop(struct shmfd *shmfd)
#endif
rangelock_destroy(&shmfd->shm_rl);
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);
}
}
@ -964,6 +1034,9 @@ shm_init(void *arg)
new_unrhdr64(&shm_ino_unr, 1);
shm_dev_ino = devfs_alloc_cdp_inode();
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++) {
if (pagesizes[i] == 0)

View File

@ -268,6 +268,7 @@ struct file;
struct shmfd {
vm_ooffset_t shm_size;
vm_object_t shm_object;
vm_pindex_t shm_pages; /* allocated pages */
int shm_refs;
uid_t shm_uid;
gid_t shm_gid;