From 776dab0a25508fe424132ac1aaafc11a9b257d38 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Tue, 22 Nov 2022 11:31:29 -0500 Subject: [PATCH 15/52] shm: Make it possible for drivers to create shm files With this change it becomes easier to create largepage POSIX shm objects from within the kernel, and also to associate such objects with a file handle. --- sys/kern/uipc_shm.c | 79 ++++++++++++++++++++++++++++++--------------- sys/sys/mman.h | 6 ++++ 2 files changed, 59 insertions(+), 26 deletions(-) diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index 1bb3714d6713..5aa793372a17 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -493,13 +493,56 @@ shm_truncate(struct file *fp, off_t length, struct ucred *active_cred, return (shm_dotruncate(shmfd, length)); } +int +shm_largepage_getconf(struct shmfd *shmfd, struct shm_largepage_conf *conf) +{ + void *rl_cookie; + + KASSERT(shm_largepage(shmfd), + ("%s: requires a largepage object", __func__)); + + rl_cookie = rangelock_rlock(&shmfd->shm_rl, 0, OFF_MAX, + &shmfd->shm_mtx); + conf->psind = shmfd->shm_lp_psind; + conf->alloc_policy = shmfd->shm_lp_alloc_policy; + rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); + return (0); +} + +int +shm_largepage_setconf(struct shmfd *shmfd, struct shm_largepage_conf *conf) +{ + void *rl_cookie; + + KASSERT(shm_largepage(shmfd), + ("%s: requires a largepage object", __func__)); + + if (shmfd->shm_lp_psind != 0 && conf->psind != shmfd->shm_lp_psind) + return (EINVAL); + if (conf->psind <= 0 || conf->psind >= MAXPAGESIZES || + pagesizes[conf->psind] == 0) + return (EINVAL); + if (conf->alloc_policy != SHM_LARGEPAGE_ALLOC_DEFAULT && + conf->alloc_policy != SHM_LARGEPAGE_ALLOC_NOWAIT && + conf->alloc_policy != SHM_LARGEPAGE_ALLOC_HARD) + return (EINVAL); + + rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX, + &shmfd->shm_mtx); + shmfd->shm_lp_psind = conf->psind; + shmfd->shm_lp_alloc_policy = conf->alloc_policy; + shmfd->shm_object->un_pager.phys.data_val = conf->psind; + rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); + + return (0); +} + int shm_ioctl(struct file *fp, u_long com, void *data, struct ucred *active_cred, struct thread *td) { struct shmfd *shmfd; struct shm_largepage_conf *conf; - void *rl_cookie; shmfd = fp->f_data; switch (com) { @@ -514,34 +557,12 @@ shm_ioctl(struct file *fp, u_long com, void *data, struct ucred *active_cred, if (!shm_largepage(shmfd)) return (ENOTTY); conf = data; - if (shmfd->shm_lp_psind != 0 && - conf->psind != shmfd->shm_lp_psind) - return (EINVAL); - if (conf->psind <= 0 || conf->psind >= MAXPAGESIZES || - pagesizes[conf->psind] == 0) - return (EINVAL); - if (conf->alloc_policy != SHM_LARGEPAGE_ALLOC_DEFAULT && - conf->alloc_policy != SHM_LARGEPAGE_ALLOC_NOWAIT && - conf->alloc_policy != SHM_LARGEPAGE_ALLOC_HARD) - return (EINVAL); - - rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX, - &shmfd->shm_mtx); - shmfd->shm_lp_psind = conf->psind; - shmfd->shm_lp_alloc_policy = conf->alloc_policy; - shmfd->shm_object->un_pager.phys.data_val = conf->psind; - rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); - return (0); + return (shm_largepage_setconf(shmfd, conf)); case FIOGSHMLPGCNF: if (!shm_largepage(shmfd)) return (ENOTTY); conf = data; - rl_cookie = rangelock_rlock(&shmfd->shm_rl, 0, OFF_MAX, - &shmfd->shm_mtx); - conf->psind = shmfd->shm_lp_psind; - conf->alloc_policy = shmfd->shm_lp_alloc_policy; - rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); - return (0); + return (shm_largepage_getconf(shmfd, conf)); default: return (ENOTTY); } @@ -1015,6 +1036,12 @@ shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred) return (ENOENT); } +void +shm_finit(struct shmfd *shmfd, int flags, struct file *fp) +{ + finit(fp, flags, DTYPE_SHM, shmfd, &shm_ops); +} + int kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode, int shmflags, struct filecaps *fcaps, const char *name __unused) @@ -1228,7 +1255,7 @@ kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode, } shmfd->shm_flags = shmflags; - finit(fp, FFLAGS(flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops); + shm_finit(shmfd, FFLAGS(flags & O_ACCMODE), fp); td->td_retval[0] = fd; fdrop(fp, td); diff --git a/sys/sys/mman.h b/sys/sys/mman.h index 3c9931df4cbf..6843e4aa29d0 100644 --- a/sys/sys/mman.h +++ b/sys/sys/mman.h @@ -292,10 +292,16 @@ int shm_unmap(struct file *fp, void *mem, size_t size); int shm_access(struct shmfd *shmfd, struct ucred *ucred, int flags); struct shmfd *shm_alloc(struct ucred *ucred, mode_t mode, bool largepage); +void shm_finit(struct shmfd *shmfd, int flags, struct file *fp); struct shmfd *shm_hold(struct shmfd *shmfd); void shm_drop(struct shmfd *shmfd); int shm_dotruncate(struct shmfd *shmfd, off_t length); + bool shm_largepage(struct shmfd *shmfd); +int shm_largepage_getconf(struct shmfd *shmfd, + struct shm_largepage_conf *conf); +int shm_largepage_setconf(struct shmfd *shmfd, + struct shm_largepage_conf *conf); extern struct fileops shm_ops; -- 2.41.0