Changeset View
Standalone View
sys/kern/uipc_shm.c
Show First 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | |||||
static fo_ioctl_t shm_ioctl; | static fo_ioctl_t shm_ioctl; | ||||
static fo_stat_t shm_stat; | static fo_stat_t shm_stat; | ||||
static fo_close_t shm_close; | static fo_close_t shm_close; | ||||
static fo_chmod_t shm_chmod; | static fo_chmod_t shm_chmod; | ||||
static fo_chown_t shm_chown; | static fo_chown_t shm_chown; | ||||
static fo_seek_t shm_seek; | static fo_seek_t shm_seek; | ||||
static fo_fill_kinfo_t shm_fill_kinfo; | static fo_fill_kinfo_t shm_fill_kinfo; | ||||
static fo_mmap_t shm_mmap; | static fo_mmap_t shm_mmap; | ||||
static fo_get_seals_t shm_get_seals; | |||||
static fo_add_seals_t shm_add_seals; | |||||
/* File descriptor operations. */ | /* File descriptor operations. */ | ||||
struct fileops shm_ops = { | struct fileops shm_ops = { | ||||
.fo_read = shm_read, | .fo_read = shm_read, | ||||
.fo_write = shm_write, | .fo_write = shm_write, | ||||
.fo_truncate = shm_truncate, | .fo_truncate = shm_truncate, | ||||
.fo_ioctl = shm_ioctl, | .fo_ioctl = shm_ioctl, | ||||
.fo_poll = invfo_poll, | .fo_poll = invfo_poll, | ||||
.fo_kqfilter = invfo_kqfilter, | .fo_kqfilter = invfo_kqfilter, | ||||
.fo_stat = shm_stat, | .fo_stat = shm_stat, | ||||
.fo_close = shm_close, | .fo_close = shm_close, | ||||
.fo_chmod = shm_chmod, | .fo_chmod = shm_chmod, | ||||
.fo_chown = shm_chown, | .fo_chown = shm_chown, | ||||
.fo_sendfile = vn_sendfile, | .fo_sendfile = vn_sendfile, | ||||
.fo_seek = shm_seek, | .fo_seek = shm_seek, | ||||
.fo_fill_kinfo = shm_fill_kinfo, | .fo_fill_kinfo = shm_fill_kinfo, | ||||
.fo_mmap = shm_mmap, | .fo_mmap = shm_mmap, | ||||
.fo_get_seals = shm_get_seals, | |||||
.fo_add_seals = shm_add_seals, | |||||
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE | .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE | ||||
}; | }; | ||||
FEATURE(posix_shm, "POSIX shared memory"); | FEATURE(posix_shm, "POSIX shared memory"); | ||||
static int | static int | ||||
uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio) | uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 274 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
vm_object_t object; | vm_object_t object; | ||||
vm_page_t m; | vm_page_t m; | ||||
vm_pindex_t idx, nobjsize; | vm_pindex_t idx, nobjsize; | ||||
vm_ooffset_t delta; | vm_ooffset_t delta; | ||||
int base, rv; | int base, rv; | ||||
KASSERT(length >= 0, ("shm_dotruncate: length < 0")); | KASSERT(length >= 0, ("shm_dotruncate: length < 0")); | ||||
object = shmfd->shm_object; | object = shmfd->shm_object; | ||||
kib: I do not think this blank line is useful. | |||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
if (length == shmfd->shm_size) { | if (length == shmfd->shm_size) { | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
return (0); | return (0); | ||||
} | } | ||||
nobjsize = OFF_TO_IDX(length + PAGE_MASK); | nobjsize = OFF_TO_IDX(length + PAGE_MASK); | ||||
/* Are we shrinking? If so, trim the end. */ | /* Are we shrinking? If so, trim the end. */ | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | retry: | ||||
object->size = nobjsize; | object->size = nobjsize; | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* shmfd object management including creation and reference counting | * shmfd object management including creation and reference counting | ||||
* routines. | * routines. | ||||
*/ | */ | ||||
Done Inline ActionsTraditionally rv denotes Mach error. Please use error there. kib: Traditionally `rv` denotes Mach error. Please use `error` there. | |||||
struct shmfd * | struct shmfd * | ||||
shm_alloc(struct ucred *ucred, mode_t mode) | shm_alloc(struct ucred *ucred, mode_t mode) | ||||
Done Inline ActionsCan you move object locking there as well ? kib: Can you move object locking there as well ? | |||||
{ | { | ||||
struct shmfd *shmfd; | struct shmfd *shmfd; | ||||
shmfd = malloc(sizeof(*shmfd), M_SHMFD, M_WAITOK | M_ZERO); | shmfd = malloc(sizeof(*shmfd), M_SHMFD, M_WAITOK | M_ZERO); | ||||
shmfd->shm_size = 0; | shmfd->shm_size = 0; | ||||
shmfd->shm_uid = ucred->cr_uid; | shmfd->shm_uid = ucred->cr_uid; | ||||
shmfd->shm_gid = ucred->cr_gid; | shmfd->shm_gid = ucred->cr_gid; | ||||
shmfd->shm_mode = mode; | shmfd->shm_mode = mode; | ||||
▲ Show 20 Lines • Show All 583 Lines • ▼ Show 20 Lines | shm_fill_kinfo(struct file *fp, struct kinfo_file *kif, | ||||
struct filedesc *fdp __unused) | struct filedesc *fdp __unused) | ||||
{ | { | ||||
int res; | int res; | ||||
sx_slock(&shm_dict_lock); | sx_slock(&shm_dict_lock); | ||||
res = shm_fill_kinfo_locked(fp->f_data, kif, false); | res = shm_fill_kinfo_locked(fp->f_data, kif, false); | ||||
sx_sunlock(&shm_dict_lock); | sx_sunlock(&shm_dict_lock); | ||||
return (res); | return (res); | ||||
} | |||||
static int | |||||
shm_add_seals(struct file *fp, int seals) | |||||
{ | |||||
struct shmfd *shmfd; | |||||
shmfd = fp->f_data; | |||||
atomic_set_int(&shmfd->shm_seals, seals); | |||||
return (0); | |||||
} | |||||
static int | |||||
shm_get_seals(struct file *fp, int *seals) | |||||
{ | |||||
struct shmfd *shmfd; | |||||
shmfd = fp->f_data; | |||||
*seals = shmfd->shm_seals; | |||||
return (0); | |||||
} | } | ||||
static int | static int | ||||
Done Inline ActionsThis lock is only useful because reading of writemappings could be non-atomic on 32bit arches, right ? kib: This lock is only useful because reading of writemappings could be non-atomic on 32bit arches… | |||||
Done Inline ActionsThis was my theory at least, yeah. kevans: This was my theory at least, yeah. | |||||
sysctl_posix_shm_list(SYSCTL_HANDLER_ARGS) | sysctl_posix_shm_list(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
Done Inline ActionsI think you should note that we unmap i.e. decrement writemappings without taking a range lock, so the object lock there is to avoid torn reads on ILP32 arches. kib: I think you should note that we unmap i.e. decrement writemappings without taking a range lock… | |||||
struct shm_mapping *shmm; | struct shm_mapping *shmm; | ||||
struct sbuf sb; | struct sbuf sb; | ||||
struct kinfo_file kif; | struct kinfo_file kif; | ||||
u_long i; | u_long i; | ||||
ssize_t curlen; | ssize_t curlen; | ||||
int error, error2; | int error, error2; | ||||
sbuf_new_for_sysctl(&sb, NULL, sizeof(struct kinfo_file) * 5, req); | sbuf_new_for_sysctl(&sb, NULL, sizeof(struct kinfo_file) * 5, req); | ||||
Not Done Inline ActionsDid you mean to also check shm_kmappings here? They are not counted in the object. markj: Did you mean to also check shm_kmappings here? They are not counted in the object. | |||||
Done Inline Actionskib suggested elsewhere that we should ignore kernel mappings for sealing purposes, so I backed down on checking it. kevans: kib suggested elsewhere that we should ignore kernel mappings for sealing purposes, so I backed… | |||||
sbuf_clear_flags(&sb, SBUF_INCLUDENUL); | sbuf_clear_flags(&sb, SBUF_INCLUDENUL); | ||||
curlen = 0; | curlen = 0; | ||||
error = 0; | error = 0; | ||||
sx_slock(&shm_dict_lock); | sx_slock(&shm_dict_lock); | ||||
for (i = 0; i < shm_hash + 1; i++) { | for (i = 0; i < shm_hash + 1; i++) { | ||||
LIST_FOREACH(shmm, &shm_dictionary[i], sm_link) { | LIST_FOREACH(shmm, &shm_dictionary[i], sm_link) { | ||||
error = shm_fill_kinfo_locked(shmm->sm_shmfd, | error = shm_fill_kinfo_locked(shmm->sm_shmfd, | ||||
&kif, true); | &kif, true); | ||||
if (error == EPERM) | if (error == EPERM) | ||||
continue; | continue; | ||||
Done Inline ActionsI think there is no point is taking the lock there. kib: I think there is no point is taking the lock there. | |||||
Done Inline ActionsThis one I was attempting to guarantee that any pending F_ADD_SEALS had finished completion prior to fetching the current seal. This may have been a foolish prospect, though, as there could be at least a couple of problems with that. kevans: This one I was attempting to guarantee that any pending F_ADD_SEALS had finished completion… | |||||
if (error != 0) | if (error != 0) | ||||
break; | break; | ||||
pack_kinfo(&kif); | pack_kinfo(&kif); | ||||
if (req->oldptr != NULL && | if (req->oldptr != NULL && | ||||
kif.kf_structsize + curlen > req->oldlen) | kif.kf_structsize + curlen > req->oldlen) | ||||
break; | break; | ||||
error = sbuf_bcat(&sb, &kif, kif.kf_structsize) == 0 ? | error = sbuf_bcat(&sb, &kif, kif.kf_structsize) == 0 ? | ||||
0 : ENOMEM; | 0 : ENOMEM; | ||||
Show All 15 Lines |
I do not think this blank line is useful.