diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -770,6 +770,8 @@ flagsp = &fp->f_vnread_flags; if (atomic_cmpset_acq_16(flagsp, 0, FOFFSET_LOCKED)) return (atomic_load_long(&fp->f_offset)); + if ((flags & FOF_NONBLOCK) != 0) + return (-1); sleepq_lock(&fp->f_vnread_flags); state = atomic_load_16(flagsp); @@ -804,6 +806,7 @@ short state; KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); + KASSERT(val >= 0, ("negative offset")); if ((flags & FOF_NOUPDATE) == 0) atomic_store_long(&fp->f_offset, val); @@ -848,6 +851,10 @@ mtx_lock(mtxp); if ((flags & FOF_NOLOCK) == 0) { while (fp->f_vnread_flags & FOFFSET_LOCKED) { + if ((flags & FOF_NONBLOCK) != 0) { + mtx_unlock(mtxp); + return (-1); + } fp->f_vnread_flags |= FOFFSET_LOCK_WAITING; msleep(&fp->f_vnread_flags, mtxp, PUSER -1, "vofflock", 0); diff --git a/sys/sys/file.h b/sys/sys/file.h --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -85,6 +85,7 @@ #define FOF_NEXTOFF_R 0x04 /* Also update f_nextoff[UIO_READ] */ #define FOF_NEXTOFF_W 0x08 /* Also update f_nextoff[UIO_WRITE] */ #define FOF_NOUPDATE 0x10 /* Do not update f_offset */ +#define FOF_NONBLOCK 0x20 /* Do not block if the offset is locked */ off_t foffset_lock(struct file *fp, int flags); void foffset_lock_uio(struct file *fp, struct uio *uio, int flags); void foffset_unlock(struct file *fp, off_t val, int flags);