Applied to master, thanks,
On Thu, May 29, 2014 at 11:25 PM, Ryan Wilson <wr...@nicira.com> wrote: > Due to patch fe83f8 (netdev: Remove netdev from global shash when > the user is changing interface configuration), netdevs can be > destructed and deallocated by revalidator and RCU threads. When > netdevs with class bsd are destroyed, the rtbsd notifier is > unregistered, possibly causing memory to be freed. This causes a > race condition with the main thread which calls rtbsd_notifier_run > periodically to check for any netdev change events. > > This patch makes the rtbsd module thread-safe via a mutex. > > Note this patch removes rtbsd_notifier_run() in > rtbsd_notifier_register() due to locking requirements. Since the > rtbsd_notifier_run() is always run by the main thread often, > receiving stale notifications from the notifier is unlikely. > > Bug #1258532 > Signed-off-by: Ryan Wilson <wr...@nicira.com> > Acked-by: YAMAMOTO Takashi <yamam...@valinux.co.jp> > > --- > v2: Fix OVS_EXCLUDES/OVS_EXCLUDED typo > --- > lib/rtbsd.c | 39 +++++++++++++++++++++++++++++---------- > 1 file changed, 29 insertions(+), 10 deletions(-) > > diff --git a/lib/rtbsd.c b/lib/rtbsd.c > index b706c20..ffffbb7 100644 > --- a/lib/rtbsd.c > +++ b/lib/rtbsd.c > @@ -32,14 +32,17 @@ > VLOG_DEFINE_THIS_MODULE(rtbsd); > COVERAGE_DEFINE(rtbsd_changed); > > +static struct ovs_mutex rtbsd_mutex = OVS_MUTEX_INITIALIZER; > + > /* PF_ROUTE socket. */ > static int notify_sock = -1; > > /* All registered notifiers. */ > static struct list all_notifiers = LIST_INITIALIZER(&all_notifiers); > > -static void rtbsd_report_change(const struct if_msghdr *); > -static void rtbsd_report_notify_error(void); > +static void rtbsd_report_change(const struct if_msghdr *) > + OVS_REQUIRES(rtbsd_mutex); > +static void rtbsd_report_notify_error(void) OVS_REQUIRES(rtbsd_mutex); > > /* Registers 'cb' to be called with auxiliary data 'aux' with network > device > * change notifications. The notifier is stored in 'notifier', which the > @@ -49,53 +52,63 @@ static void rtbsd_report_notify_error(void); > int > rtbsd_notifier_register(struct rtbsd_notifier *notifier, > rtbsd_notify_func *cb, void *aux) > + OVS_EXCLUDED(rtbsd_mutex) > { > + int error = 0; > + > + ovs_mutex_lock(&rtbsd_mutex); > if (notify_sock < 0) { > - int error; > notify_sock = socket(PF_ROUTE, SOCK_RAW, 0); > if (notify_sock < 0) { > VLOG_WARN("could not create PF_ROUTE socket: %s", > ovs_strerror(errno)); > - return errno; > + error = errno; > + goto out; > } > error = set_nonblocking(notify_sock); > if (error) { > VLOG_WARN("error set_nonblocking PF_ROUTE socket: %s", > ovs_strerror(error)); > - return error; > + goto out; > } > - } else { > - /* Catch up on notification work so that the new notifier won't > - * receive any stale notifications. XXX*/ > - rtbsd_notifier_run(); > } > > list_push_back(&all_notifiers, ¬ifier->node); > notifier->cb = cb; > notifier->aux = aux; > - return 0; > + > +out: > + ovs_mutex_unlock(&rtbsd_mutex); > + return error; > } > > /* Cancels notification on 'notifier', which must have previously been > * registered with rtbsd_notifier_register(). */ > void > rtbsd_notifier_unregister(struct rtbsd_notifier *notifier) > + OVS_EXCLUDED(rtbsd_mutex) > { > + ovs_mutex_lock(&rtbsd_mutex); > list_remove(¬ifier->node); > if (list_is_empty(&all_notifiers)) { > close(notify_sock); > notify_sock = -1; > } > + ovs_mutex_unlock(&rtbsd_mutex); > } > > /* Calls all of the registered notifiers, passing along any > as-yet-unreported > * netdev change events. */ > void > rtbsd_notifier_run(void) > + OVS_EXCLUDED(rtbsd_mutex) > { > static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); > struct if_msghdr msg; > + > + ovs_mutex_lock(&rtbsd_mutex); > if (notify_sock < 0) { > + ovs_mutex_unlock(&rtbsd_mutex); > return; > } > > @@ -114,6 +127,7 @@ rtbsd_notifier_run(void) > rtbsd_report_change(&msg); > } > } else if (errno == EAGAIN) { > + ovs_mutex_unlock(&rtbsd_mutex); > return; > } else { > if (errno == ENOBUFS) { > @@ -131,14 +145,18 @@ rtbsd_notifier_run(void) > * ready. */ > void > rtbsd_notifier_wait(void) > + OVS_EXCLUDED(rtbsd_mutex) > { > + ovs_mutex_lock(&rtbsd_mutex); > if (notify_sock >= 0) { > poll_fd_wait(notify_sock, POLLIN); > } > + ovs_mutex_unlock(&rtbsd_mutex); > } > > static void > rtbsd_report_change(const struct if_msghdr *msg) > + OVS_REQUIRES(rtbsd_mutex) > { > struct rtbsd_notifier *notifier; > struct rtbsd_change change; > @@ -158,6 +176,7 @@ rtbsd_report_change(const struct if_msghdr *msg) > /* If an error occurs the notifiers' callbacks are called with NULL > changes */ > static void > rtbsd_report_notify_error(void) > + OVS_REQUIRES(rtbsd_mutex) > { > struct rtbsd_notifier *notifier; > > -- > 1.7.9.5 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev >
_______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev