aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-09-16 17:06:50 -0400
committerTakashi Iwai <tiwai@suse.de>2010-09-16 17:06:50 -0400
commit901d46d5a8eb821b03ca9e8cf005beb0c92f31ea (patch)
treefe3b5d015c456834ee2b900de2cfdd1d1b62b4bb
parent8699a0b657b43fa6401537dfe345bee7aa8115ec (diff)
ALSA: pcm - Fix race with proc files
The PCM proc files may open a race against substream close, which can end up with an Oops. Use the open_mutex to protect for it. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/core/pcm.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 204af48c5cc1..ac242a377aea 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -372,14 +372,17 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
372 struct snd_info_buffer *buffer) 372 struct snd_info_buffer *buffer)
373{ 373{
374 struct snd_pcm_substream *substream = entry->private_data; 374 struct snd_pcm_substream *substream = entry->private_data;
375 struct snd_pcm_runtime *runtime = substream->runtime; 375 struct snd_pcm_runtime *runtime;
376
377 mutex_lock(&substream->pcm->open_mutex);
378 runtime = substream->runtime;
376 if (!runtime) { 379 if (!runtime) {
377 snd_iprintf(buffer, "closed\n"); 380 snd_iprintf(buffer, "closed\n");
378 return; 381 goto unlock;
379 } 382 }
380 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { 383 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
381 snd_iprintf(buffer, "no setup\n"); 384 snd_iprintf(buffer, "no setup\n");
382 return; 385 goto unlock;
383 } 386 }
384 snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access)); 387 snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));
385 snd_iprintf(buffer, "format: %s\n", snd_pcm_format_name(runtime->format)); 388 snd_iprintf(buffer, "format: %s\n", snd_pcm_format_name(runtime->format));
@@ -398,20 +401,25 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
398 snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames); 401 snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);
399 } 402 }
400#endif 403#endif
404 unlock:
405 mutex_unlock(&substream->pcm->open_mutex);
401} 406}
402 407
403static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, 408static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
404 struct snd_info_buffer *buffer) 409 struct snd_info_buffer *buffer)
405{ 410{
406 struct snd_pcm_substream *substream = entry->private_data; 411 struct snd_pcm_substream *substream = entry->private_data;
407 struct snd_pcm_runtime *runtime = substream->runtime; 412 struct snd_pcm_runtime *runtime;
413
414 mutex_lock(&substream->pcm->open_mutex);
415 runtime = substream->runtime;
408 if (!runtime) { 416 if (!runtime) {
409 snd_iprintf(buffer, "closed\n"); 417 snd_iprintf(buffer, "closed\n");
410 return; 418 goto unlock;
411 } 419 }
412 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { 420 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
413 snd_iprintf(buffer, "no setup\n"); 421 snd_iprintf(buffer, "no setup\n");
414 return; 422 goto unlock;
415 } 423 }
416 snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode)); 424 snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
417 snd_iprintf(buffer, "period_step: %u\n", runtime->period_step); 425 snd_iprintf(buffer, "period_step: %u\n", runtime->period_step);
@@ -421,24 +429,29 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
421 snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold); 429 snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
422 snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size); 430 snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size);
423 snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary); 431 snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);
432 unlock:
433 mutex_unlock(&substream->pcm->open_mutex);
424} 434}
425 435
426static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, 436static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
427 struct snd_info_buffer *buffer) 437 struct snd_info_buffer *buffer)
428{ 438{
429 struct snd_pcm_substream *substream = entry->private_data; 439 struct snd_pcm_substream *substream = entry->private_data;
430 struct snd_pcm_runtime *runtime = substream->runtime; 440 struct snd_pcm_runtime *runtime;
431 struct snd_pcm_status status; 441 struct snd_pcm_status status;
432 int err; 442 int err;
443
444 mutex_lock(&substream->pcm->open_mutex);
445 runtime = substream->runtime;
433 if (!runtime) { 446 if (!runtime) {
434 snd_iprintf(buffer, "closed\n"); 447 snd_iprintf(buffer, "closed\n");
435 return; 448 goto unlock;
436 } 449 }
437 memset(&status, 0, sizeof(status)); 450 memset(&status, 0, sizeof(status));
438 err = snd_pcm_status(substream, &status); 451 err = snd_pcm_status(substream, &status);
439 if (err < 0) { 452 if (err < 0) {
440 snd_iprintf(buffer, "error %d\n", err); 453 snd_iprintf(buffer, "error %d\n", err);
441 return; 454 goto unlock;
442 } 455 }
443 snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state)); 456 snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
444 snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid)); 457 snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid));
@@ -452,6 +465,8 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
452 snd_iprintf(buffer, "-----\n"); 465 snd_iprintf(buffer, "-----\n");
453 snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr); 466 snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr);
454 snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr); 467 snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr);
468 unlock:
469 mutex_unlock(&substream->pcm->open_mutex);
455} 470}
456 471
457#ifdef CONFIG_SND_PCM_XRUN_DEBUG 472#ifdef CONFIG_SND_PCM_XRUN_DEBUG