Commit ad9e036c authored by Paul Mackerras's avatar Paul Mackerras Committed by Linus Torvalds

[PATCH] Multilink fix for ppp_generic.c

I released ppp-2.4.3 yesterday, with much improved support for multilink
operation - when the first link is terminated, its pppd no longer exits
immediately, but keeps running in order to keep the ppp interface up while
there are other links still in the bundle.

However, this shows up a bug in the kernel ppp driver, which is that there is
no way for the pppd controlling the bundle to know when the last link in the
bundle is terminated.  This patch provides such a way: with this patch, pppd
will get an EOF when reading from the /dev/ppp instance for the bundle when
there are no channels connected.

The change does not affect older versions of pppd or normal non-multilink
operation (I have tested to make sure of that).
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ef4535ef
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
* PPP driver, written by Michael Callahan and Al Longyear, and * PPP driver, written by Michael Callahan and Al Longyear, and
* subsequently hacked by Paul Mackerras. * subsequently hacked by Paul Mackerras.
* *
* ==FILEVERSION 20020217== * ==FILEVERSION 20041108==
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -412,6 +412,17 @@ static ssize_t ppp_read(struct file *file, char __user *buf, ...@@ -412,6 +412,17 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
ret = 0; ret = 0;
if (pf->dead) if (pf->dead)
break; break;
if (pf->kind == INTERFACE) {
/*
* Return 0 (EOF) on an interface that has no
* channels connected, unless it is looping
* network traffic (demand mode).
*/
struct ppp *ppp = PF_TO_PPP(pf);
if (ppp->n_channels == 0
&& (ppp->flags & SC_LOOP_TRAFFIC) == 0)
break;
}
ret = -EAGAIN; ret = -EAGAIN;
if (file->f_flags & O_NONBLOCK) if (file->f_flags & O_NONBLOCK)
break; break;
...@@ -491,6 +502,14 @@ static unsigned int ppp_poll(struct file *file, poll_table *wait) ...@@ -491,6 +502,14 @@ static unsigned int ppp_poll(struct file *file, poll_table *wait)
mask |= POLLIN | POLLRDNORM; mask |= POLLIN | POLLRDNORM;
if (pf->dead) if (pf->dead)
mask |= POLLHUP; mask |= POLLHUP;
else if (pf->kind == INTERFACE) {
/* see comment in ppp_read */
struct ppp *ppp = PF_TO_PPP(pf);
if (ppp->n_channels == 0
&& (ppp->flags & SC_LOOP_TRAFFIC) == 0)
mask |= POLLIN | POLLRDNORM;
}
return mask; return mask;
} }
...@@ -2559,7 +2578,8 @@ ppp_disconnect_channel(struct channel *pch) ...@@ -2559,7 +2578,8 @@ ppp_disconnect_channel(struct channel *pch)
/* remove it from the ppp unit's list */ /* remove it from the ppp unit's list */
ppp_lock(ppp); ppp_lock(ppp);
list_del(&pch->clist); list_del(&pch->clist);
--ppp->n_channels; if (--ppp->n_channels == 0)
wake_up_interruptible(&ppp->file.rwait);
ppp_unlock(ppp); ppp_unlock(ppp);
if (atomic_dec_and_test(&ppp->file.refcnt)) if (atomic_dec_and_test(&ppp->file.refcnt))
ppp_destroy_interface(ppp); ppp_destroy_interface(ppp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment