diff options
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r-- | sys/kern/kern_descrip.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index a27ab33b34da..2a833d2eafbe 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -665,20 +665,26 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) } while (atomic_cmpset_int(&fp->f_flag, flg, tmp) == 0); got_set = tmp & ~flg; got_cleared = flg & ~tmp; - tmp = fp->f_flag & FNONBLOCK; - error = fo_ioctl(fp, FIONBIO, &tmp, td->td_ucred, td); - if (error != 0) - goto revert_f_setfl; - tmp = fp->f_flag & FASYNC; - error = fo_ioctl(fp, FIOASYNC, &tmp, td->td_ucred, td); - if (error == 0) { - fdrop(fp, td); - break; + if (((got_set | got_cleared) & FNONBLOCK) != 0) { + tmp = fp->f_flag & FNONBLOCK; + error = fo_ioctl(fp, FIONBIO, &tmp, td->td_ucred, td); + if (error != 0) + goto revert_flags; + } + if (((got_set | got_cleared) & FASYNC) != 0) { + tmp = fp->f_flag & FASYNC; + error = fo_ioctl(fp, FIOASYNC, &tmp, td->td_ucred, td); + if (error != 0) + goto revert_nonblock; + } + fdrop(fp, td); + break; +revert_nonblock: + if (((got_set | got_cleared) & FNONBLOCK) != 0) { + tmp = ~fp->f_flag & FNONBLOCK; + (void)fo_ioctl(fp, FIONBIO, &tmp, td->td_ucred, td); } - atomic_clear_int(&fp->f_flag, FNONBLOCK); - tmp = 0; - (void)fo_ioctl(fp, FIONBIO, &tmp, td->td_ucred, td); -revert_f_setfl: +revert_flags: do { tmp = flg = fp->f_flag; tmp &= ~FCNTLFLAGS; @@ -5250,6 +5256,8 @@ file_type_to_name(short type) return ("eventfd"); case DTYPE_TIMERFD: return ("timerfd"); + case DTYPE_JAILDESC: + return ("jail"); default: return ("unkn"); } |