@@ -215,6 +215,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode)
215
215
if (!ast_type ) {
216
216
kref_get (& lkb -> lkb_ref );
217
217
list_add_tail (& lkb -> lkb_astqueue , & proc -> asts );
218
+ lkb -> lkb_ast_first = type ;
218
219
wake_up_interruptible (& proc -> wait );
219
220
}
220
221
if (type == AST_COMP && (ast_type & AST_COMP ))
@@ -223,7 +224,6 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode)
223
224
224
225
eol = lkb_is_endoflife (lkb , ua -> lksb .sb_status , type );
225
226
if (eol ) {
226
- lkb -> lkb_ast_type &= ~AST_BAST ;
227
227
lkb -> lkb_flags |= DLM_IFL_ENDOFLIFE ;
228
228
}
229
229
@@ -706,7 +706,7 @@ static int device_close(struct inode *inode, struct file *file)
706
706
}
707
707
708
708
static int copy_result_to_user (struct dlm_user_args * ua , int compat , int type ,
709
- int bmode , char __user * buf , size_t count )
709
+ int mode , char __user * buf , size_t count )
710
710
{
711
711
#ifdef CONFIG_COMPAT
712
712
struct dlm_lock_result32 result32 ;
@@ -733,7 +733,7 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
733
733
if (type == AST_BAST ) {
734
734
result .user_astaddr = ua -> bastaddr ;
735
735
result .user_astparam = ua -> bastparam ;
736
- result .bast_mode = bmode ;
736
+ result .bast_mode = mode ;
737
737
} else {
738
738
result .user_astaddr = ua -> castaddr ;
739
739
result .user_astparam = ua -> castparam ;
@@ -801,7 +801,9 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
801
801
struct dlm_user_proc * proc = file -> private_data ;
802
802
struct dlm_lkb * lkb ;
803
803
DECLARE_WAITQUEUE (wait , current );
804
- int error , type = 0 , bmode = 0 , removed = 0 ;
804
+ int error = 0 , removed ;
805
+ int ret_type , ret_mode ;
806
+ int bastmode , castmode , do_bast , do_cast ;
805
807
806
808
if (count == sizeof (struct dlm_device_version )) {
807
809
error = copy_version_to_user (buf , count );
@@ -820,6 +822,8 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
820
822
#endif
821
823
return - EINVAL ;
822
824
825
+ try_another :
826
+
823
827
/* do we really need this? can a read happen after a close? */
824
828
if (test_bit (DLM_PROC_FLAGS_CLOSING , & proc -> flags ))
825
829
return - EINVAL ;
@@ -855,13 +859,55 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
855
859
856
860
lkb = list_entry (proc -> asts .next , struct dlm_lkb , lkb_astqueue );
857
861
858
- if (lkb -> lkb_ast_type & AST_COMP ) {
859
- lkb -> lkb_ast_type &= ~AST_COMP ;
860
- type = AST_COMP ;
861
- } else if (lkb -> lkb_ast_type & AST_BAST ) {
862
- lkb -> lkb_ast_type &= ~AST_BAST ;
863
- type = AST_BAST ;
864
- bmode = lkb -> lkb_bastmode ;
862
+ removed = 0 ;
863
+ ret_type = 0 ;
864
+ ret_mode = 0 ;
865
+ do_bast = lkb -> lkb_ast_type & AST_BAST ;
866
+ do_cast = lkb -> lkb_ast_type & AST_COMP ;
867
+ bastmode = lkb -> lkb_bastmode ;
868
+ castmode = lkb -> lkb_castmode ;
869
+
870
+ /* when both are queued figure out which to do first and
871
+ switch first so the other goes in the next read */
872
+
873
+ if (do_cast && do_bast ) {
874
+ if (lkb -> lkb_ast_first == AST_COMP ) {
875
+ ret_type = AST_COMP ;
876
+ ret_mode = castmode ;
877
+ lkb -> lkb_ast_type &= ~AST_COMP ;
878
+ lkb -> lkb_ast_first = AST_BAST ;
879
+ } else {
880
+ ret_type = AST_BAST ;
881
+ ret_mode = bastmode ;
882
+ lkb -> lkb_ast_type &= ~AST_BAST ;
883
+ lkb -> lkb_ast_first = AST_COMP ;
884
+ }
885
+ } else {
886
+ ret_type = lkb -> lkb_ast_first ;
887
+ ret_mode = (ret_type == AST_COMP ) ? castmode : bastmode ;
888
+ lkb -> lkb_ast_type &= ~ret_type ;
889
+ lkb -> lkb_ast_first = 0 ;
890
+ }
891
+
892
+ /* if we're doing a bast but the bast is unnecessary, then
893
+ switch to do nothing or do a cast if that was needed next */
894
+
895
+ if ((ret_type == AST_BAST ) &&
896
+ dlm_modes_compat (bastmode , lkb -> lkb_castmode_done )) {
897
+ ret_type = 0 ;
898
+ ret_mode = 0 ;
899
+
900
+ if (do_cast ) {
901
+ ret_type = AST_COMP ;
902
+ ret_mode = castmode ;
903
+ lkb -> lkb_ast_type &= ~AST_COMP ;
904
+ lkb -> lkb_ast_first = 0 ;
905
+ }
906
+ }
907
+
908
+ if (lkb -> lkb_ast_first != lkb -> lkb_ast_type ) {
909
+ log_print ("device_read %x ast_first %x ast_type %x" ,
910
+ lkb -> lkb_id , lkb -> lkb_ast_first , lkb -> lkb_ast_type );
865
911
}
866
912
867
913
if (!lkb -> lkb_ast_type ) {
@@ -870,15 +916,29 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
870
916
}
871
917
spin_unlock (& proc -> asts_spin );
872
918
873
- error = copy_result_to_user (lkb -> lkb_ua ,
874
- test_bit (DLM_PROC_FLAGS_COMPAT , & proc -> flags ),
875
- type , bmode , buf , count );
919
+ if (ret_type ) {
920
+ error = copy_result_to_user (lkb -> lkb_ua ,
921
+ test_bit (DLM_PROC_FLAGS_COMPAT , & proc -> flags ),
922
+ ret_type , ret_mode , buf , count );
923
+
924
+ if (ret_type == AST_COMP )
925
+ lkb -> lkb_castmode_done = castmode ;
926
+ if (ret_type == AST_BAST )
927
+ lkb -> lkb_bastmode_done = bastmode ;
928
+ }
876
929
877
930
/* removes reference for the proc->asts lists added by
878
931
dlm_user_add_ast() and may result in the lkb being freed */
932
+
879
933
if (removed )
880
934
dlm_put_lkb (lkb );
881
935
936
+ /* the bast that was queued was eliminated (see unnecessary above),
937
+ leaving nothing to return */
938
+
939
+ if (!ret_type )
940
+ goto try_another ;
941
+
882
942
return error ;
883
943
}
884
944
0 commit comments