All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@infradead.org>
To: S?bastien Dugu? <sebastien.dugue@bull.net>
Cc: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Suparna Bhattacharya <suparna@in.ibm.com>,
	Ulrich Drepper <drepper@redhat.com>,
	Zach Brown <zach.brown@oracle.com>, Dave Jones <davej@redhat.com>,
	Jean Pierre Dion <jean-pierre.dion@bull.net>,
	"linux-aio@kvack.org" <linux-aio@kvack.org>
Subject: Re: [PATCH -mm 3/3][AIO] - AIO completion signal notification
Date: Thu, 9 Nov 2006 19:08:43 +0000	[thread overview]
Message-ID: <20061109190843.GA20321@infradead.org> (raw)
In-Reply-To: <1163087946.3879.43.camel@frecb000686>

> +static long aio_setup_sigevent(struct kiocb *iocb,
> +			       struct sigevent __user *user_event)
> +{
> +	int error = 0;
> +	sigevent_t event;
> +	struct task_struct *target;
> +	unsigned long flags;
> +
> +	if (!access_ok(VERIFY_READ, user_event, sizeof(struct sigevent)))
> +		return -EFAULT;
> +
> +	if (copy_from_user(&event, user_event, sizeof (event)))
> +		return -EFAULT;

> +

> +
> +	/* Check for the SIGEV_NONE case */
> +	if (event.sigev_notify == SIGEV_NONE)
> +		return 0;
> +
> +	/* Setup the request completion notification parameters */
> +	iocb->ki_notify.notify = event.sigev_notify;
> +	iocb->ki_notify.signo = event.sigev_signo;
> +	iocb->ki_notify.value = event.sigev_value;
> +
> +	/* Now get the notification target */
> +	read_lock(&tasklist_lock);
> +
> +	if ((target = good_sigevent(&event))) {
> +
> +		spin_lock_irqsave(&target->sighand->siglock, flags);
> +
> +		if (!(target->flags & PF_EXITING)) {
> +			iocb->ki_notify.target = target;
> +
> +			spin_unlock_irqrestore(&target->sighand->siglock, flags);
> +

I don't think there's a need to have the siglock for checking PF_EXITING,
and I also don't see why you need it for the assignment to
iocb->ki_notify.target.  What is it intended to protect?

> +			/*
> +			 * Get a ref on the task. It is dropped in really_put_req()
> +			 * when we're done with the iocb, be it from the normal
> +			 * completion path, the cancellation path or an error path.
> +			 */
> +			if (iocb->ki_notify.notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
> +				get_task_struct(target);
> +		} else {
> +			spin_unlock_irqrestore(&target->sighand->siglock, flags);
> +			error = -EINVAL;
> +		}
> +	} else
> +		error = -EINVAL;
> +
> +	read_unlock(&tasklist_lock);
> +
> +	if (!error) {
> +		/*
> +		 * Alloc a sigqueue for this request
> +		 *
> +		 * NOTE: we cannot free the sigqueue in the completion path as
> +		 * the signal may not have been delivered to the target task.
> +		 * Therefore it has to be freed in __sigqueue_free() when the
> +		 * signal is collected if si_code is SI_ASYNCIO.
> +		 */
> +		if (unlikely(!(iocb->ki_sigq = sigqueue_alloc())))
> +			error =  -EAGAIN;

We leak the task reference here.

All in all aio_setup_sigevent is a big mess and the style is very odd.
It's also overcommented on what's beeing done instead of why.
I've attached an draft on how it should look like below.

> +	/* handle setting up the sigevent for POSIX AIO signals */
> +	req->ki_notify.notify = SIGEV_NONE;
> +
> +	if (iocb->aio_sigeventp) {
> +		ret = aio_setup_sigevent(req,
> +				     (struct sigevent __user *)(unsigned long)
> +				     iocb->aio_sigeventp);
> +		if (ret)
> +			goto out_put_req;
> +	}
> +
>  	ret = aio_setup_iocb(req);
>  
>  	if (ret)
> @@ -1610,6 +1729,10 @@ int fastcall io_submit_one(struct kioctx
>  	return 0;
>  
>  out_put_req:
> +	/* Undo the sigqueue alloc if someting went bad */
> +	if (req->ki_sigq)
> +		sigqueue_free(req->ki_sigq);
> +

Please put this after a separate label, so only callers after
aio_setup_sigevent try to check ki_sigq.



static long aio_setup_sigevent(struct kiocb *iocb,
			       struct sigevent __user *user_event)
{
	sigevent_t event;
	struct task_struct *target;
	unsigned long flags;

	if (copy_from_user(&event, user_event, sizeof (event)))
		return -EFAULT;

	if (event.sigev_notify == SIGEV_NONE)
		return 0;

	iocb->ki_notify.notify = event.sigev_notify;
	iocb->ki_notify.signo = event.sigev_signo;
	iocb->ki_notify.value = event.sigev_value;

	read_lock(&tasklist_lock);
	target = good_sigevent(&event);
	if (unlikely(!target || (target->flags & PF_EXITING)))
		goto out_unlock;
	iocb->ki_notify.target = target;

	if (iocb->ki_notify.notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID)) {
		/*
		 * This reference will be dropped when we're done with
		 * the request.
		 */
		get_task_struct(target);
	}
	read_unlock(&tasklist_lock);

	/*
	 * NOTE: we cannot free the sigqueue in the completion path as
	 * the signal may not have been delivered to the target task.
	 * Therefore it has to be freed in __sigqueue_free() when the
	 * signal is collected if si_code is SI_ASYNCIO.
	 */
	iocb->ki_sigq = sigqueue_alloc();
	if (unlikely(!iocb->ki_sigq)) {
		put_task_struct(target);
		return -EAGAIN;
	}

	return 0;
 out_unlock:
	read_unlock(&tasklist_lock);
	return -EINVAL;
}


  parent reply	other threads:[~2006-11-09 19:08 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-11-09 15:55 [PATCH -mm 0/3][AIO] - AIO completion signal notification Sébastien Dugué
2006-11-09 15:58 ` [PATCH -mm 1/3][AIO] " Sébastien Dugué
2006-11-09 15:59 ` [PATCH -mm 2/3][AIO] " Sébastien Dugué
2006-11-09 15:59 ` [PATCH -mm 3/3][AIO] " Sébastien Dugué
2006-11-09 18:46   ` Badari Pulavarty
2006-11-10  9:05     ` Sébastien Dugué
2006-11-09 19:08   ` Christoph Hellwig [this message]
2006-11-09 19:27     ` Badari Pulavarty
2006-11-10  9:20       ` Sébastien Dugué
2006-11-10  9:14     ` Sébastien Dugué
2006-11-09 19:18   ` Badari Pulavarty
2006-11-10  9:22     ` Sébastien Dugué
2006-11-10  1:52   ` Badari Pulavarty
2006-11-10  1:54     ` Badari Pulavarty

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=20061109190843.GA20321@infradead.org \
    --to=hch@infradead.org \
    --cc=davej@redhat.com \
    --cc=drepper@redhat.com \
    --cc=jean-pierre.dion@bull.net \
    --cc=linux-aio@kvack.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sebastien.dugue@bull.net \
    --cc=suparna@in.ibm.com \
    --cc=zach.brown@oracle.com \
    /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.