All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
To: Takashi Iwai <tiwai@suse.de>
Cc: alsa-devel@alsa-project.org, clemens@ladisch.de
Subject: Re: [PATCH 2/2] ALSA: ctl: refactoring for read operation
Date: Fri, 10 Apr 2015 19:32:58 +0900	[thread overview]
Message-ID: <5527A6DA.50800@sakamocchi.jp> (raw)
In-Reply-To: <s5h61945spk.wl-tiwai@suse.de>

On Apr 10 2015 16:48, Takashi Iwai wrote:
> At Fri, 10 Apr 2015 08:43:01 +0900,
> Takashi Sakamoto wrote:
>>
>> snd_ctl_read() has nested loop and complicated condition for return
>> value. This is not better for reading.
>>
>> This commit applies refactoring with two loops.
>>
>> Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
>> ---
>>  sound/core/control.c | 77 ++++++++++++++++++++++++++++++++--------------------
>>  1 file changed, 47 insertions(+), 30 deletions(-)
>>
>> diff --git a/sound/core/control.c b/sound/core/control.c
>> index de19d56..da6497d 100644
>> --- a/sound/core/control.c
>> +++ b/sound/core/control.c
>> @@ -1520,58 +1520,75 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
>>  			    size_t count, loff_t * offset)
>>  {
>>  	struct snd_ctl_file *ctl;
>> -	int err = 0;
>> -	ssize_t result = 0;
>> +	struct snd_ctl_event ev;
>> +	struct snd_kctl_event *kev;
>> +	wait_queue_t wait;
>> +	ssize_t result;
>>  
>>  	ctl = file->private_data;
>>  	if (snd_BUG_ON(!ctl || !ctl->card))
>>  		return -ENXIO;
>>  	if (!ctl->subscribed)
>>  		return -EBADFD;
>> +
>> +	/* The size of given buffer should be larger than at least one event. */
>>  	if (count < sizeof(struct snd_ctl_event))
>>  		return -EINVAL;
>> +
>> +	/* Block till any events were queued. */
>>  	spin_lock_irq(&ctl->read_lock);
>> -	while (count >= sizeof(struct snd_ctl_event)) {
>> -		struct snd_ctl_event ev;
>> -		struct snd_kctl_event *kev;
>> -		while (list_empty(&ctl->events)) {
>> -			wait_queue_t wait;
>> -			if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
>> -				err = -EAGAIN;
>> -				goto __end_lock;
>> -			}
>> -			init_waitqueue_entry(&wait, current);
>> -			add_wait_queue(&ctl->change_sleep, &wait);
>> -			set_current_state(TASK_INTERRUPTIBLE);
>> -			spin_unlock_irq(&ctl->read_lock);
>> -			schedule();
>> -			remove_wait_queue(&ctl->change_sleep, &wait);
>> -			if (ctl->card->shutdown)
>> -				return -ENODEV;
>> -			if (signal_pending(current))
>> -				return -ERESTARTSYS;
>> -			spin_lock_irq(&ctl->read_lock);
>> +	while (list_empty(&ctl->events)) {
>> +		if (file->f_flags & O_NONBLOCK) {
>> +			result = -EAGAIN;
>> +			goto unlock;
>>  		}
>> +
>> +		/* The card was disconnected. The queued events are dropped. */
>> +		if (ctl->card->shutdown) {
>> +			result = -ENODEV;
>> +			goto unlock;
>> +		}
>> +
>> +
>> +		init_waitqueue_entry(&wait, current);
>> +		add_wait_queue(&ctl->change_sleep, &wait);
>> +		set_current_state(TASK_INTERRUPTIBLE);
>> +		spin_unlock_irq(&ctl->read_lock);
>> +
>> +		schedule();
>> +
>> +		remove_wait_queue(&ctl->change_sleep, &wait);
>> +
>> +		if (signal_pending(current))
>> +			return -ERESTARTSYS;
>> +
>> +		spin_lock_irq(&ctl->read_lock);
>> +	}
>> +
>> +	/* Copy events till the buffer filled, or no events are remained. */
>> +	result = 0;
>> +	while (count >= sizeof(struct snd_ctl_event)) {
>> +		if (list_empty(&ctl->events))
>> +			break;
>>  		kev = snd_kctl_event(ctl->events.next);
>> +		list_del(&kev->list);
>> +
>>  		ev.type = SNDRV_CTL_EVENT_ELEM;
>>  		ev.data.elem.mask = kev->mask;
>>  		ev.data.elem.id = kev->id;
>> -		list_del(&kev->list);
>> -		spin_unlock_irq(&ctl->read_lock);
>>  		kfree(kev);
>>  		if (copy_to_user(buffer, &ev, sizeof(struct snd_ctl_event))) {
>> -			err = -EFAULT;
>> -			goto __end;
>> +			result = -EFAULT;
>> +			break;
> 
> This still changes the behavior.  The read returns the size that has
> been read at first even when an error happens if some data was already
> read.  The error code is returned at the next read.  This is a design
> problem of read syscall.

I'm unaware of it... These code should be:

if (copy_to_user(buffer, &ev, sizeof(struct snd_ctl_event))) {
    if (result == 0)
        result = -EFAULT;
    break;

And I realize sound/firewire/fireworks/fireworks_hwdep.c has the same
bug. I'll post another patch for this bug.


Thanks

Takashi Sakamoto

> Takashi
> 
>>  		}
>> -		spin_lock_irq(&ctl->read_lock);
>> +
>>  		buffer += sizeof(struct snd_ctl_event);
>>  		count -= sizeof(struct snd_ctl_event);
>>  		result += sizeof(struct snd_ctl_event);
>>  	}
>> -      __end_lock:
>> +unlock:
>>  	spin_unlock_irq(&ctl->read_lock);
>> -      __end:
>> -      	return result > 0 ? result : err;
>> +	return result;
>>  }
>>  
>>  static unsigned int snd_ctl_poll(struct file *file, poll_table * wait)
>> -- 
>> 2.1.0

  reply	other threads:[~2015-04-10 10:33 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-08 16:55 [PATCH 0/2 RFC] control core refactoring Takashi Sakamoto
2015-04-08 16:55 ` [PATCH 1/2] ALSA: ctl: evaluate macro instead of numerical value Takashi Sakamoto
2015-04-08 16:55 ` [PATCH 2/2] ALSA: ctl: refactoring for read operation Takashi Sakamoto
2015-04-09  5:33   ` Takashi Iwai
2015-04-09  7:35     ` Takashi Sakamoto
2015-04-09  8:17       ` Takashi Iwai
2015-04-09 23:42 ` [PATCH 0/2] control core refactoring Takashi Sakamoto
2015-04-09 23:43   ` [PATCH 1/2] ALSA: ctl: evaluate macro instead of numerical value Takashi Sakamoto
2015-04-10  7:49     ` Takashi Iwai
2015-04-12  7:20       ` Takashi Iwai
2015-04-09 23:43   ` [PATCH 2/2] ALSA: ctl: refactoring for read operation Takashi Sakamoto
2015-04-10  7:48     ` Takashi Iwai
2015-04-10 10:32       ` Takashi Sakamoto [this message]
2015-04-10 10:43         ` Takashi Iwai
2015-04-10 10:52           ` Takashi Sakamoto

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5527A6DA.50800@sakamocchi.jp \
    --to=o-takashi@sakamocchi.jp \
    --cc=alsa-devel@alsa-project.org \
    --cc=clemens@ladisch.de \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.