@@ -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
874847void
875848foffset_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
892879static 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
927886off_t
928887foffset_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}
0 commit comments