Changeset View
Standalone View
sys/dev/random/randomdev.c
Show First 20 Lines • Show All 334 Lines • ▼ Show 20 Lines | randomdev_write(struct cdev *dev __unused, struct uio *uio, int flags __unused) | ||||
random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK); | random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK); | ||||
nbytes = uio->uio_resid; | nbytes = uio->uio_resid; | ||||
while (uio->uio_resid > 0 && error == 0) { | while (uio->uio_resid > 0 && error == 0) { | ||||
c = MIN(uio->uio_resid, PAGE_SIZE); | c = MIN(uio->uio_resid, PAGE_SIZE); | ||||
error = uiomove(random_buf, c, uio); | error = uiomove(random_buf, c, uio); | ||||
if (error) | if (error) | ||||
break; | break; | ||||
randomdev_accumulate(random_buf, c); | randomdev_accumulate(random_buf, c); | ||||
tsleep(p_random_alg_context, 0, "randwr", hz/10); | |||||
} | } | ||||
if (nbytes != uio->uio_resid && (error == ERESTART || error == EINTR)) | if (nbytes != uio->uio_resid && (error == ERESTART || error == EINTR)) | ||||
/* Partial write, not error. */ | /* Partial write, not error. */ | ||||
error = 0; | error = 0; | ||||
cem: Is this condition even possible anymore? The only way I can see the accumulation loop exiting… | |||||
cpercivaAuthorUnsubmitted Done Inline ActionsMaybe possible if there's a page fault and a signal arrives while the data is being faulted in? I agree that it's unlikely though. cperciva: Maybe possible if there's a page fault and a signal arrives while the data is being faulted in? | |||||
cemUnsubmitted Not Done Inline ActionsIf that case does happen, should we squash actually error, rather than returning EINTR? I thought we were supposed to bubble that up to the syscall entry layer, generally. Anyway, orthogonal to your improvement here. Thanks! cem: If that case does happen, should we squash actually error, rather than returning EINTR? I… | |||||
cpercivaAuthorUnsubmitted Done Inline ActionsNo, this code is correct -- we return EINTR from the syscall if the write was interrupted before writing anything (i.e. if uio_resid is still equal to nbytes), but if at least one byte was written then write(2) returns success with a short write length. cperciva: No, this code is correct -- we return EINTR from the syscall if the write was interrupted… | |||||
cemUnsubmitted Not Done Inline ActionsDoesn’t dofilewrite already do that? cem: Doesn’t dofilewrite already do that?
http://fxr.watson.org/fxr/source/kern/sys_generic.c#L568 | |||||
cpercivaAuthorUnsubmitted Done Inline ActionsHmm yes, indeed it seems that way. I suspect this isn't the only place this sort of duplication is present in the tree, either. cperciva: Hmm yes, indeed it seems that way. I suspect this isn't the only place this sort of… | |||||
free(random_buf, M_ENTROPY); | free(random_buf, M_ENTROPY); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static int | static int | ||||
randomdev_poll(struct cdev *dev __unused, int events, struct thread *td __unused) | randomdev_poll(struct cdev *dev __unused, int events, struct thread *td __unused) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 78 Lines • Show Last 20 Lines |
Is this condition even possible anymore? The only way I can see the accumulation loop exiting early is if we hit trap on an invalid userspace buffer, producing EFAULT. randomdev_accumulate() is incapable of failure.