From 25d27eded1f4fc728e64f443adc339b5229be5d7 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 2 Nov 2009 09:35:44 +0100 Subject: control: use reference-counted pid Instead of storing the PID number, take a reference to the task's pid structure. This protects against duplicates due to PID overflows, and using pid_vnr() ensures that the PID returned by snd_ctl_elem_info() is correct as seen from the current namespace. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/core/rawmidi.c') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index c0adc14..8a81bda 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -415,7 +415,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) subdevice = -1; read_lock(&card->ctl_files_rwlock); list_for_each_entry(kctl, &card->ctl_files, list) { - if (kctl->pid == current->pid) { + if (kctl->pid == task_pid(current)) { subdevice = kctl->prefer_rawmidi_subdevice; if (subdevice != -1) break; -- cgit v1.1 From 8579d2d7779d7ff41ea2a0183015e0e5038f1043 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 21 Oct 2009 09:09:38 +0200 Subject: sound: rawmidi: fix double init when opening MIDI device with O_APPEND Commit 9a1b64caac82aa02cb74587ffc798e6f42c6170a in 2.6.30 moved the substream initialization code to where it would be executed every time the substream is opened. This had the consequence that any further opening would drop and leak the data in the existing buffer, and that the device driver's open callback would be called multiple times, unexpectedly. Signed-off-by: Clemens Ladisch Cc: Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'sound/core/rawmidi.c') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index c0adc14..3071e6f 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -266,17 +266,19 @@ static int open_substream(struct snd_rawmidi *rmidi, { int err; - err = snd_rawmidi_runtime_create(substream); - if (err < 0) - return err; - err = substream->ops->open(substream); - if (err < 0) - return err; - substream->opened = 1; - if (substream->use_count++ == 0) + if (substream->use_count == 0) { + err = snd_rawmidi_runtime_create(substream); + if (err < 0) + return err; + err = substream->ops->open(substream); + if (err < 0) + return err; + substream->opened = 1; substream->active_sensing = 0; - if (mode & SNDRV_RAWMIDI_LFLG_APPEND) - substream->append = 1; + if (mode & SNDRV_RAWMIDI_LFLG_APPEND) + substream->append = 1; + } + substream->use_count++; rmidi->streams[substream->stream].substream_opened++; return 0; } -- cgit v1.1 From 16fb109644b5644e42ececeff644514de6f4bd03 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 21 Oct 2009 09:10:16 +0200 Subject: sound: rawmidi: fix checking of O_APPEND when opening MIDI device Commit 9a1b64caac82aa02cb74587ffc798e6f42c6170a in 2.6.30 dropped the check that a substream must already have been opened with O_APPEND to be able to open it a second time. This would make it possible for a substream to be switched to append mode, which would mean that non-atomic writes would fail unexpectedly. Signed-off-by: Clemens Ladisch Cc: Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/core/rawmidi.c') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 3071e6f..0914053 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -248,7 +248,8 @@ static int assign_substream(struct snd_rawmidi *rmidi, int subdevice, list_for_each_entry(substream, &s->substreams, list) { if (substream->opened) { if (stream == SNDRV_RAWMIDI_STREAM_INPUT || - !(mode & SNDRV_RAWMIDI_LFLG_APPEND)) + !(mode & SNDRV_RAWMIDI_LFLG_APPEND) || + !substream->append) continue; } if (subdevice < 0 || subdevice == substream->number) { -- cgit v1.1 From b7fe750fcceda4fa6bef399b0e2812562728ea82 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 21 Oct 2009 09:11:43 +0200 Subject: sound: rawmidi: fix MIDI device O_APPEND error handling Commit 9a1b64caac82aa02cb74587ffc798e6f42c6170a in 2.6.30 broke the error handling code in rawmidi_open_priv(). If only the output substream of a RawMIDI device has been opened and if this device is then opened with O_RDWR | O_APPEND and if the initialization of the input substream fails (either because of low memory or because the device driver's open callback fails), then the runtime structure of the already open output substream will be freed and all following writes through the first handle will cause snd_rawmidi_write() to use the NULL runtime pointer. Signed-off-by: Clemens Ladisch Cc: Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'sound/core/rawmidi.c') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 0914053..70d6f25 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -272,8 +272,10 @@ static int open_substream(struct snd_rawmidi *rmidi, if (err < 0) return err; err = substream->ops->open(substream); - if (err < 0) + if (err < 0) { + snd_rawmidi_runtime_free(substream); return err; + } substream->opened = 1; substream->active_sensing = 0; if (mode & SNDRV_RAWMIDI_LFLG_APPEND) @@ -300,27 +302,27 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, SNDRV_RAWMIDI_STREAM_INPUT, mode, &sinput); if (err < 0) - goto __error; + return err; } if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { err = assign_substream(rmidi, subdevice, SNDRV_RAWMIDI_STREAM_OUTPUT, mode, &soutput); if (err < 0) - goto __error; + return err; } if (sinput) { err = open_substream(rmidi, sinput, mode); if (err < 0) - goto __error; + return err; } if (soutput) { err = open_substream(rmidi, soutput, mode); if (err < 0) { if (sinput) close_substream(rmidi, sinput, 0); - goto __error; + return err; } } @@ -328,13 +330,6 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, rfile->input = sinput; rfile->output = soutput; return 0; - - __error: - if (sinput && sinput->runtime) - snd_rawmidi_runtime_free(sinput); - if (soutput && soutput->runtime) - snd_rawmidi_runtime_free(soutput); - return err; } /* called from sound/core/seq/seq_midi.c */ -- cgit v1.1 From 91d12c485b8949cce6c13ab641147c5bc86ce8b9 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 21 Oct 2009 09:12:26 +0200 Subject: sound: rawmidi: fix opened substreams count The substream_opened field is to count the number of opened substreams, not the number of times that any substreams have been opened. Furthermore, all substreams being opened does not imply that the next open would fail, due to the possibility of O_APPEND. With this wrong check, opening a substream multiple times would succeed only if the device had more unopened substreams. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound/core/rawmidi.c') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 4e26563..818b129 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -242,8 +242,6 @@ static int assign_substream(struct snd_rawmidi *rmidi, int subdevice, return -ENXIO; if (subdevice >= 0 && subdevice >= s->substream_count) return -ENODEV; - if (s->substream_opened >= s->substream_count) - return -EAGAIN; list_for_each_entry(substream, &s->substreams, list) { if (substream->opened) { @@ -280,9 +278,9 @@ static int open_substream(struct snd_rawmidi *rmidi, substream->active_sensing = 0; if (mode & SNDRV_RAWMIDI_LFLG_APPEND) substream->append = 1; + rmidi->streams[substream->stream].substream_opened++; } substream->use_count++; - rmidi->streams[substream->stream].substream_opened++; return 0; } @@ -466,7 +464,6 @@ static void close_substream(struct snd_rawmidi *rmidi, struct snd_rawmidi_substream *substream, int cleanup) { - rmidi->streams[substream->stream].substream_opened--; if (--substream->use_count) return; @@ -491,6 +488,7 @@ static void close_substream(struct snd_rawmidi *rmidi, snd_rawmidi_runtime_free(substream); substream->opened = 0; substream->append = 0; + rmidi->streams[substream->stream].substream_opened--; } static void rawmidi_release_priv(struct snd_rawmidi_file *rfile) -- cgit v1.1 From 7584af10cf46e0f4aa1696f1be79fa0f19a945ba Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 10 Nov 2009 10:14:04 +0100 Subject: sound: rawmidi: record a substream's owner process Record the pid of the task that opened a RawMIDI substream. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'sound/core/rawmidi.c') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 818b129..2f76612 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -278,6 +278,7 @@ static int open_substream(struct snd_rawmidi *rmidi, substream->active_sensing = 0; if (mode & SNDRV_RAWMIDI_LFLG_APPEND) substream->append = 1; + substream->pid = get_pid(task_pid(current)); rmidi->streams[substream->stream].substream_opened++; } substream->use_count++; @@ -488,6 +489,8 @@ static void close_substream(struct snd_rawmidi *rmidi, snd_rawmidi_runtime_free(substream); substream->opened = 0; substream->append = 0; + put_pid(substream->pid); + substream->pid = NULL; rmidi->streams[substream->stream].substream_opened--; } @@ -1336,6 +1339,9 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, substream->number, (unsigned long) substream->bytes); if (substream->opened) { + snd_iprintf(buffer, + " Owner PID : %d\n", + pid_vnr(substream->pid)); runtime = substream->runtime; snd_iprintf(buffer, " Mode : %s\n" @@ -1357,6 +1363,9 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, substream->number, (unsigned long) substream->bytes); if (substream->opened) { + snd_iprintf(buffer, + " Owner PID : %d\n", + pid_vnr(substream->pid)); runtime = substream->runtime; snd_iprintf(buffer, " Buffer size : %lu\n" -- cgit v1.1 From 6b2f3d1f769be5779b479c37800229d9a4809fc3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 27 Oct 2009 11:05:28 +0100 Subject: vfs: Implement proper O_SYNC semantics While Linux provided an O_SYNC flag basically since day 1, it took until Linux 2.4.0-test12pre2 to actually get it implemented for filesystems, since that day we had generic_osync_around with only minor changes and the great "For now, when the user asks for O_SYNC, we'll actually give O_DSYNC" comment. This patch intends to actually give us real O_SYNC semantics in addition to the O_DSYNC semantics. After Jan's O_SYNC patches which are required before this patch it's actually surprisingly simple, we just need to figure out when to set the datasync flag to vfs_fsync_range and when not. This patch renames the existing O_SYNC flag to O_DSYNC while keeping it's numerical value to keep binary compatibility, and adds a new real O_SYNC flag. To guarantee backwards compatiblity it is defined as expanding to both the O_DSYNC and the new additional binary flag (__O_SYNC) to make sure we are backwards-compatible when compiled against the new headers. This also means that all places that don't care about the differences can just check O_DSYNC and get the right behaviour for O_SYNC, too - only places that actuall care need to check __O_SYNC in addition. Drivers and network filesystems have been updated in a fail safe way to always do the full sync magic if O_DSYNC is set. The few places setting O_SYNC for lower layers are kept that way for now to stay failsafe. We enforce that O_DSYNC is set when __O_SYNC is set early in the open path to make sure we always get these sane options. Note that parisc really screwed up their headers as they already define a O_DSYNC that has always been a no-op. We try to repair it by using it for the new O_DSYNC and redefinining O_SYNC to send both the traditional O_SYNC numerical value _and_ the O_DSYNC one. Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Grant Grundler Cc: "David S. Miller" Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Thomas Gleixner Cc: Al Viro Cc: Andreas Dilger Acked-by: Trond Myklebust Acked-by: Kyle McMartin Acked-by: Ulrich Drepper Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Jan Kara --- sound/core/rawmidi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/core/rawmidi.c') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 2f76612..0f5a194 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -1257,7 +1257,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, break; count -= count1; } - if (file->f_flags & O_SYNC) { + if (file->f_flags & O_DSYNC) { spin_lock_irq(&runtime->lock); while (runtime->avail != runtime->buffer_size) { wait_queue_t wait; -- cgit v1.1