diff options
Diffstat (limited to 'drivers/net/netconsole.c')
| -rw-r--r-- | drivers/net/netconsole.c | 20 | 
1 files changed, 16 insertions, 4 deletions
| diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 4822aafe638b..c9a15925a1f7 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -102,6 +102,7 @@ struct netconsole_target {  	struct config_item	item;  #endif  	int			enabled; +	struct mutex		mutex;  	struct netpoll		np;  }; @@ -181,6 +182,7 @@ static struct netconsole_target *alloc_param_target(char *target_config)  	strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);  	nt->np.local_port = 6665;  	nt->np.remote_port = 6666; +	mutex_init(&nt->mutex);  	memset(nt->np.remote_mac, 0xff, ETH_ALEN);  	/* Parse parameters and setup netpoll */ @@ -308,6 +310,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,  			     const char *buf,  			     size_t count)  { +	unsigned long flags;  	int enabled;  	int err; @@ -323,7 +326,6 @@ static ssize_t store_enabled(struct netconsole_target *nt,  	}  	if (enabled) {	/* 1 */ -  		/*  		 * Skip netpoll_parse_options() -- all the attributes are  		 * already configured via configfs. Just print them out. @@ -335,8 +337,14 @@ static ssize_t store_enabled(struct netconsole_target *nt,  			return err;  		printk(KERN_INFO "netconsole: network logging started\n"); -  	} else {	/* 0 */ +		/* We need to disable the netconsole before cleaning it up +		 * otherwise we might end up in write_msg() with +		 * nt->np.dev == NULL and nt->enabled == 1 +		 */ +		spin_lock_irqsave(&target_list_lock, flags); +		nt->enabled = 0; +		spin_unlock_irqrestore(&target_list_lock, flags);  		netpoll_cleanup(&nt->np);  	} @@ -557,8 +565,10 @@ static ssize_t netconsole_target_attr_store(struct config_item *item,  	struct netconsole_target_attr *na =  		container_of(attr, struct netconsole_target_attr, attr); +	mutex_lock(&nt->mutex);  	if (na->store)  		ret = na->store(nt, buf, count); +	mutex_unlock(&nt->mutex);  	return ret;  } @@ -597,6 +607,7 @@ static struct config_item *make_netconsole_target(struct config_group *group,  	strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);  	nt->np.local_port = 6665;  	nt->np.remote_port = 6666; +	mutex_init(&nt->mutex);  	memset(nt->np.remote_mac, 0xff, ETH_ALEN);  	/* Initialize the config_item member */ @@ -677,12 +688,13 @@ restart:  			case NETDEV_RELEASE:  			case NETDEV_JOIN:  			case NETDEV_UNREGISTER: -				/* -				 * rtnl_lock already held +				/* rtnl_lock already held  				 * we might sleep in __netpoll_cleanup()  				 */  				spin_unlock_irqrestore(&target_list_lock, flags); +  				__netpoll_cleanup(&nt->np); +  				spin_lock_irqsave(&target_list_lock, flags);  				dev_put(nt->np.dev);  				nt->np.dev = NULL; |