@@ -108,6 +108,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
108
108
return - ENOMEM ;
109
109
runtime -> substream = substream ;
110
110
spin_lock_init (& runtime -> lock );
111
+ mutex_init (& runtime -> realloc_mutex );
111
112
init_waitqueue_head (& runtime -> sleep );
112
113
INIT_WORK (& runtime -> event_work , snd_rawmidi_input_event_work );
113
114
runtime -> event = NULL ;
@@ -622,8 +623,9 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
622
623
struct snd_rawmidi_params * params )
623
624
{
624
625
char * newbuf ;
626
+ char * oldbuf ;
625
627
struct snd_rawmidi_runtime * runtime = substream -> runtime ;
626
-
628
+ unsigned long flags ;
627
629
if (substream -> append && substream -> use_count > 1 )
628
630
return - EBUSY ;
629
631
snd_rawmidi_drain_output (substream );
@@ -634,13 +636,22 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
634
636
return - EINVAL ;
635
637
}
636
638
if (params -> buffer_size != runtime -> buffer_size ) {
637
- newbuf = krealloc (runtime -> buffer , params -> buffer_size ,
639
+ mutex_lock (& runtime -> realloc_mutex );
640
+ newbuf = __krealloc (runtime -> buffer , params -> buffer_size ,
638
641
GFP_KERNEL );
639
- if (!newbuf )
642
+ if (!newbuf ) {
643
+ mutex_unlock (& runtime -> realloc_mutex );
640
644
return - ENOMEM ;
645
+ }
646
+ spin_lock_irqsave (& runtime -> lock , flags );
647
+ oldbuf = runtime -> buffer ;
641
648
runtime -> buffer = newbuf ;
642
649
runtime -> buffer_size = params -> buffer_size ;
643
650
runtime -> avail = runtime -> buffer_size ;
651
+ spin_unlock_irqrestore (& runtime -> lock , flags );
652
+ if (oldbuf != newbuf )
653
+ kfree (oldbuf );
654
+ mutex_unlock (& runtime -> realloc_mutex );
644
655
}
645
656
runtime -> avail_min = params -> avail_min ;
646
657
substream -> active_sensing = !params -> no_active_sensing ;
@@ -651,7 +662,9 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
651
662
struct snd_rawmidi_params * params )
652
663
{
653
664
char * newbuf ;
665
+ char * oldbuf ;
654
666
struct snd_rawmidi_runtime * runtime = substream -> runtime ;
667
+ unsigned long flags ;
655
668
656
669
snd_rawmidi_drain_input (substream );
657
670
if (params -> buffer_size < 32 || params -> buffer_size > 1024L * 1024L ) {
@@ -661,12 +674,21 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
661
674
return - EINVAL ;
662
675
}
663
676
if (params -> buffer_size != runtime -> buffer_size ) {
664
- newbuf = krealloc (runtime -> buffer , params -> buffer_size ,
677
+ mutex_lock (& runtime -> realloc_mutex );
678
+ newbuf = __krealloc (runtime -> buffer , params -> buffer_size ,
665
679
GFP_KERNEL );
666
- if (!newbuf )
680
+ if (!newbuf ) {
681
+ mutex_unlock (& runtime -> realloc_mutex );
667
682
return - ENOMEM ;
683
+ }
684
+ spin_lock_irqsave (& runtime -> lock , flags );
685
+ oldbuf = runtime -> buffer ;
668
686
runtime -> buffer = newbuf ;
669
687
runtime -> buffer_size = params -> buffer_size ;
688
+ spin_unlock_irqrestore (& runtime -> lock , flags );
689
+ if (oldbuf != newbuf )
690
+ kfree (oldbuf );
691
+ mutex_unlock (& runtime -> realloc_mutex );
670
692
}
671
693
runtime -> avail_min = params -> avail_min ;
672
694
return 0 ;
@@ -935,6 +957,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
935
957
long result = 0 , count1 ;
936
958
struct snd_rawmidi_runtime * runtime = substream -> runtime ;
937
959
960
+ if (userbuf )
961
+ mutex_lock (& runtime -> realloc_mutex );
938
962
while (count > 0 && runtime -> avail ) {
939
963
count1 = runtime -> buffer_size - runtime -> appl_ptr ;
940
964
if (count1 > count )
@@ -948,6 +972,7 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
948
972
spin_unlock_irqrestore (& runtime -> lock , flags );
949
973
if (copy_to_user (userbuf + result ,
950
974
runtime -> buffer + runtime -> appl_ptr , count1 )) {
975
+ mutex_unlock (& runtime -> realloc_mutex );
951
976
return result > 0 ? result : - EFAULT ;
952
977
}
953
978
spin_lock_irqsave (& runtime -> lock , flags );
@@ -959,6 +984,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
959
984
result += count1 ;
960
985
count -= count1 ;
961
986
}
987
+ if (userbuf )
988
+ mutex_unlock (& runtime -> realloc_mutex );
962
989
return result ;
963
990
}
964
991
@@ -1168,10 +1195,14 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
1168
1195
return - EINVAL ;
1169
1196
1170
1197
result = 0 ;
1198
+ if (userbuf )
1199
+ mutex_lock (& runtime -> realloc_mutex );
1171
1200
spin_lock_irqsave (& runtime -> lock , flags );
1172
1201
if (substream -> append ) {
1173
1202
if ((long )runtime -> avail < count ) {
1174
1203
spin_unlock_irqrestore (& runtime -> lock , flags );
1204
+ if (userbuf )
1205
+ mutex_unlock (& runtime -> realloc_mutex );
1175
1206
return - EAGAIN ;
1176
1207
}
1177
1208
}
@@ -1203,6 +1234,8 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
1203
1234
__end :
1204
1235
count1 = runtime -> avail < runtime -> buffer_size ;
1205
1236
spin_unlock_irqrestore (& runtime -> lock , flags );
1237
+ if (userbuf )
1238
+ mutex_unlock (& runtime -> realloc_mutex );
1206
1239
if (count1 )
1207
1240
snd_rawmidi_output_trigger (substream , 1 );
1208
1241
return result ;
0 commit comments