Skip to content

Commit 1f2a652

Browse files
committed
Revert "kern/vfs_vnops.c: generalize the lock primitive for file foffset"
Temporarily back this out to fix the tree while I try 16.0 snapshot builds. It will come back once D52626 lands. This reverts commit 94a0f9f. Discussed with: kib
1 parent 8f26824 commit 1f2a652

File tree

2 files changed

+60
-94
lines changed

2 files changed

+60
-94
lines changed

sys/kern/vfs_vnops.c

Lines changed: 57 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -798,82 +798,58 @@ vn_rdwr_inchunks(enum uio_rw rw, struct vnode *vp, void *base, size_t len,
798798
}
799799

800800
#if OFF_MAX <= LONG_MAX
801-
static void
802-
file_v_lock(struct file *fp, short lock_bit, short lock_wait_bit)
801+
off_t
802+
foffset_lock(struct file *fp, int flags)
803803
{
804-
short *flagsp;
804+
volatile short *flagsp;
805+
off_t res;
805806
short state;
806807

807-
flagsp = &fp->f_vflags;
808-
state = atomic_load_16(flagsp);
809-
if ((state & lock_bit) == 0 &&
810-
atomic_cmpset_acq_16(flagsp, state, state | lock_bit))
811-
return;
808+
KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed"));
809+
810+
if ((flags & FOF_NOLOCK) != 0)
811+
return (atomic_load_long(&fp->f_offset));
812812

813-
sleepq_lock(flagsp);
813+
/*
814+
* According to McKusick the vn lock was protecting f_offset here.
815+
* It is now protected by the FOFFSET_LOCKED flag.
816+
*/
817+
flagsp = &fp->f_vnread_flags;
818+
if (atomic_cmpset_acq_16(flagsp, 0, FOFFSET_LOCKED))
819+
return (atomic_load_long(&fp->f_offset));
820+
821+
sleepq_lock(&fp->f_vnread_flags);
814822
state = atomic_load_16(flagsp);
815823
for (;;) {
816-
if ((state & lock_bit) == 0) {
824+
if ((state & FOFFSET_LOCKED) == 0) {
817825
if (!atomic_fcmpset_acq_16(flagsp, &state,
818-
state | lock_bit))
826+
FOFFSET_LOCKED))
819827
continue;
820828
break;
821829
}
822-
if ((state & lock_wait_bit) == 0) {
830+
if ((state & FOFFSET_LOCK_WAITING) == 0) {
823831
if (!atomic_fcmpset_acq_16(flagsp, &state,
824-
state | lock_wait_bit))
832+
state | FOFFSET_LOCK_WAITING))
825833
continue;
826834
}
827835
DROP_GIANT();
828-
sleepq_add(flagsp, NULL, "vofflock", 0, 0);
829-
sleepq_wait(flagsp, PRI_MAX_KERN);
836+
sleepq_add(&fp->f_vnread_flags, NULL, "vofflock", 0, 0);
837+
sleepq_wait(&fp->f_vnread_flags, PRI_MAX_KERN);
830838
PICKUP_GIANT();
831-
sleepq_lock(flagsp);
839+
sleepq_lock(&fp->f_vnread_flags);
832840
state = atomic_load_16(flagsp);
833841
}
834-
sleepq_release(flagsp);
835-
}
836-
837-
static void
838-
file_v_unlock(struct file *fp, short lock_bit, short lock_wait_bit)
839-
{
840-
short *flagsp;
841-
short state;
842-
843-
flagsp = &fp->f_vflags;
844-
state = atomic_load_16(flagsp);
845-
if ((state & lock_wait_bit) == 0 &&
846-
atomic_cmpset_rel_16(flagsp, state, state & ~lock_bit))
847-
return;
848-
849-
sleepq_lock(flagsp);
850-
MPASS((*flagsp & lock_bit) != 0);
851-
MPASS((*flagsp & lock_wait_bit) != 0);
852-
atomic_clear_16(flagsp, lock_bit | lock_wait_bit);
853-
sleepq_broadcast(flagsp, SLEEPQ_SLEEP, 0, 0);
854-
sleepq_release(flagsp);
855-
}
856-
857-
off_t
858-
foffset_lock(struct file *fp, int flags)
859-
{
860-
KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed"));
861-
862-
if ((flags & FOF_NOLOCK) == 0) {
863-
file_v_lock(fp, FILE_V_FOFFSET_LOCKED,
864-
FILE_V_FOFFSET_LOCK_WAITING);
865-
}
866-
867-
/*
868-
* According to McKusick the vn lock was protecting f_offset here.
869-
* It is now protected by the FOFFSET_LOCKED flag.
870-
*/
871-
return (atomic_load_long(&fp->f_offset));
842+
res = atomic_load_long(&fp->f_offset);
843+
sleepq_release(&fp->f_vnread_flags);
844+
return (res);
872845
}
873846

874847
void
875848
foffset_unlock(struct file *fp, off_t val, int flags)
876849
{
850+
volatile short *flagsp;
851+
short state;
852+
877853
KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed"));
878854

879855
if ((flags & FOF_NOUPDATE) == 0)
@@ -883,10 +859,21 @@ foffset_unlock(struct file *fp, off_t val, int flags)
883859
if ((flags & FOF_NEXTOFF_W) != 0)
884860
fp->f_nextoff[UIO_WRITE] = val;
885861

886-
if ((flags & FOF_NOLOCK) == 0) {
887-
file_v_unlock(fp, FILE_V_FOFFSET_LOCKED,
888-
FILE_V_FOFFSET_LOCK_WAITING);
889-
}
862+
if ((flags & FOF_NOLOCK) != 0)
863+
return;
864+
865+
flagsp = &fp->f_vnread_flags;
866+
state = atomic_load_16(flagsp);
867+
if ((state & FOFFSET_LOCK_WAITING) == 0 &&
868+
atomic_cmpset_rel_16(flagsp, state, 0))
869+
return;
870+
871+
sleepq_lock(&fp->f_vnread_flags);
872+
MPASS((fp->f_vnread_flags & FOFFSET_LOCKED) != 0);
873+
MPASS((fp->f_vnread_flags & FOFFSET_LOCK_WAITING) != 0);
874+
fp->f_vnread_flags = 0;
875+
sleepq_broadcast(&fp->f_vnread_flags, SLEEPQ_SLEEP, 0, 0);
876+
sleepq_release(&fp->f_vnread_flags);
890877
}
891878

892879
static off_t
@@ -895,35 +882,7 @@ foffset_read(struct file *fp)
895882

896883
return (atomic_load_long(&fp->f_offset));
897884
}
898-
899-
#else /* OFF_MAX <= LONG_MAX */
900-
901-
static void
902-
file_v_lock_mtxp(struct file *fp, struct mtx *mtxp, short lock_bit,
903-
short lock_wait_bit)
904-
{
905-
mtx_assert(mtxp, MA_OWNED);
906-
907-
while ((fp->f_vflags & lock_bit) != 0) {
908-
fp->f_vflags |= lock_wait_bit;
909-
msleep(&fp->f_vflags, mtxp, PRI_MAX_KERN,
910-
"vofflock", 0);
911-
}
912-
fp->f_vflags |= lock_bit;
913-
}
914-
915-
static void
916-
file_v_unlock_mtxp(struct file *fp, struct mtx *mtxp, short lock_bit,
917-
short lock_wait_bit)
918-
{
919-
mtx_assert(mtxp, MA_OWNED);
920-
921-
KASSERT((fp->f_vflags & lock_bit) != 0, ("Lost lock_bit"));
922-
if ((fp->f_vflags & lock_wait_bit) != 0)
923-
wakeup(&fp->f_vflags);
924-
fp->f_vflags &= ~(lock_bit | lock_wait_bit);
925-
}
926-
885+
#else
927886
off_t
928887
foffset_lock(struct file *fp, int flags)
929888
{
@@ -935,8 +894,12 @@ foffset_lock(struct file *fp, int flags)
935894
mtxp = mtx_pool_find(mtxpool_sleep, fp);
936895
mtx_lock(mtxp);
937896
if ((flags & FOF_NOLOCK) == 0) {
938-
file_v_lock_mtxp(fp, mtxp, FILE_V_FOFFSET_LOCKED,
939-
FILE_V_FOFFSET_LOCK_WAITING);
897+
while (fp->f_vnread_flags & FOFFSET_LOCKED) {
898+
fp->f_vnread_flags |= FOFFSET_LOCK_WAITING;
899+
msleep(&fp->f_vnread_flags, mtxp, PRI_MAX_KERN,
900+
"vofflock", 0);
901+
}
902+
fp->f_vnread_flags |= FOFFSET_LOCKED;
940903
}
941904
res = fp->f_offset;
942905
mtx_unlock(mtxp);
@@ -959,8 +922,11 @@ foffset_unlock(struct file *fp, off_t val, int flags)
959922
if ((flags & FOF_NEXTOFF_W) != 0)
960923
fp->f_nextoff[UIO_WRITE] = val;
961924
if ((flags & FOF_NOLOCK) == 0) {
962-
file_v_unlock_mtxp(fp, mtxp, FILE_V_FOFFSET_LOCKED,
963-
FILE_V_FOFFSET_LOCK_WAITING);
925+
KASSERT((fp->f_vnread_flags & FOFFSET_LOCKED) != 0,
926+
("Lost FOFFSET_LOCKED"));
927+
if (fp->f_vnread_flags & FOFFSET_LOCK_WAITING)
928+
wakeup(&fp->f_vnread_flags);
929+
fp->f_vnread_flags = 0;
964930
}
965931
mtx_unlock(mtxp);
966932
}

sys/sys/file.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ struct file {
197197
struct vnode *f_vnode; /* NULL or applicable vnode */
198198
struct ucred *f_cred; /* associated credentials. */
199199
short f_type; /* descriptor type */
200-
short f_vflags; /* (f) Sleep lock flags for members */
200+
short f_vnread_flags; /* (f) Sleep lock for f_offset */
201201
/*
202202
* DTYPE_VNODE specific fields.
203203
*/
@@ -220,8 +220,8 @@ struct file {
220220
#define f_cdevpriv f_vnun.fvn_cdevpriv
221221
#define f_advice f_vnun.fvn_advice
222222

223-
#define FILE_V_FOFFSET_LOCKED 0x0001
224-
#define FILE_V_FOFFSET_LOCK_WAITING 0x0002
223+
#define FOFFSET_LOCKED 0x1
224+
#define FOFFSET_LOCK_WAITING 0x2
225225
#endif /* __BSD_VISIBLE */
226226

227227
#endif /* _KERNEL || _WANT_FILE */

0 commit comments

Comments
 (0)