All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Hurley <peter@hurleysoftware.com>
To: Oleg Nesterov <oleg@redhat.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jiri Slaby <jslaby@suse.com>
Cc: Milos Vyletel <milos@redhat.com>,
	Stanislav Kozina <skozina@redhat.com>,
	linux-kernel@vger.kernel.org
Subject: Re: Q: tty_open() && hangup
Date: Fri, 15 Apr 2016 12:29:06 -0700	[thread overview]
Message-ID: <57114102.3050507@hurleysoftware.com> (raw)
In-Reply-To: <20160415171950.GA17586@redhat.com>

Hi Oleg,

On 04/15/2016 10:19 AM, Oleg Nesterov wrote:
> Hi,
> 
> I am fingting with obscure pty bug in rhel6 which _might be_ explained
> by some hangup/reopen races, and this motivated me to look at upstream
> code which I can't understand too ;)
> 
> Lets look at tty_open(),
> 
>   2112          tty = tty_open_current_tty(device, filp);
>   2113          if (!tty)
>   2114                  tty = tty_open_by_driver(device, inode, filp);
>   2115
>   2116          if (IS_ERR(tty)) {
>   2117                  tty_free_file(filp);
>   2118                  retval = PTR_ERR(tty);
>   2119                  if (retval != -EAGAIN || signal_pending(current))
>   2120                          return retval;
>   2121                  schedule();
>   2122                  goto retry_open;
> 
> And why do we need this schedule() above? It is nop in TASK_RUNNING.
> 
> If we need it for non-preempt kernels to avoid some sort of livelock
> this can't work if rt_task(current) == T.
> 
> If we just want to add a preemption point then perhaps we should use
> cond_resched/might_resched ?

Yeah, it's just a preemption point that pre-dates cond_resched.


> I am not saying this is wrong, but looks confusing.
> 
>   2130          if (tty->ops->open)
>   2131                  retval = tty->ops->open(tty, filp);
>   2132          else
>   2133                  retval = -ENODEV;
>   2134          filp->f_flags = saved_flags;
>   2135
>   2136          if (retval) {
>   2137                  tty_debug_hangup(tty, "open error %d, releasing\n", retval);
>   2138
>   2139                  tty_unlock(tty); /* need to call tty_release without BTM */
>   2140                  tty_release(inode, filp);
>   2141                  if (retval != -ERESTARTSYS)
>   2142                          return retval;
>   2143
>   2144                  if (signal_pending(current))
>   2145                          return retval;
> 
> So we can only get here if tty->ops->open returns -ERESTARTSYS without
> signal_pending(). This doesn't look good. But OK, lets forget this.

tty_port_block_til_ready() returns -ERESTARTSYS if !ASYNC_HUP_NOTIFY and
tty was hungup or the h/w was reset (eg. while waiting for tty lock).
IOW, parallel hangup() or release() happened at the point where the
tty lock was not held.


>   2147                  schedule();
> 
> Again, this looks confusing.
> 
>   2148                  /*
>   2149                   * Need to reset f_op in case a hangup happened.
>   2150                   */
>   2151                  if (tty_hung_up_p(filp))
>   2152                          filp->f_op = &tty_fops;
> 
> And this is called after tty_add_file() which makes this filp visible to
> __tty_hangup(), and without tty_lock().

tty_release() has removed the filp from the files list already (with the
tty lock held), so if the file operations were reset it's because a
hangup happened when the tty lock was not held (eg. waiting for reopen
or after dropping the lock and reacquiring it in tty_release())


> How can we trust this check? __tty_hangup() can set hung_up_tty_fops()
> right after tty_hung_up_p() returns F.

__tty_hangup() will not have had visibility to this filp after
tty_release().


> Don't we need something like below? Otherwise afaics tty_open() can
> actually succeed (and clear TTY_HUPPED) after restart, but return with
> tty_hung_up_p(filp) == T.

No.

Regards,
Peter Hurley



> --- x/drivers/tty/tty_io.c
> +++ x/drivers/tty/tty_io.c
> @@ -2122,6 +2122,13 @@ retry_open:
>  		goto retry_open;
>  	}
>  
> +	/*
> +	 * This is only possible after retry_open, we drop tty_lock()
> +	 * without tty_del_file().
> +	 */
> +	if (tty_hung_up_p(filp))
> +		filp->f_op = &tty_fops;
> +
>  	tty_add_file(tty, filp);
>  
>  	check_tty_count(tty, __func__);
> @@ -2145,11 +2152,6 @@ retry_open:
>  			return retval;
>  
>  		schedule();
> -		/*
> -		 * Need to reset f_op in case a hangup happened.
> -		 */
> -		if (tty_hung_up_p(filp))
> -			filp->f_op = &tty_fops;
>  		goto retry_open;
>  	}
>  	clear_bit(TTY_HUPPED, &tty->flags);
> 

  reply	other threads:[~2016-04-15 19:29 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-15 17:19 Q: tty_open() && hangup Oleg Nesterov
2016-04-15 19:29 ` Peter Hurley [this message]
2016-04-16 15:27   ` Oleg Nesterov

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=57114102.3050507@hurleysoftware.com \
    --to=peter@hurleysoftware.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jslaby@suse.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=milos@redhat.com \
    --cc=oleg@redhat.com \
    --cc=skozina@redhat.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.