Bug#280743: kernel-image-2.6.8-1-686: scheduler error with preemptible kernel and 802.1q vlans
On Wed, Nov 17, 2004 at 01:32:08PM +0600, devd@ccfit.nsu.ru wrote:
> uhm... there were no any patches attached :(
>
> On Fri, Nov 12, 2004 at 04:44:09PM +0900, Horms wrote:
> > On Thu, Nov 11, 2004 at 06:18:08PM +0600, Dmitry L. Evdokimov wrote:
> > > Package: kernel-image-2.6.8-1-686
> > > Version: 2.6.8-4
> > > Severity: normal
> > >
> > > when preemptible kernel option is enabled, and you turn on a 802.1q
> > > vlan interface, kernel starts flooding with "Scheduling while atomic"
> > > error message. there is no this problem with preemptible kernel
> > > disabled.
> >
> > Hi,
> >
> > thanks for the bug report. Are you in a position to test the
> > two attached patches to see if they resolve your problem?
> > I can produce updated packages for you if that helps.
Sorry, here they are.
--
Horms
#! /bin/sh -e
## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Description: Sync code and feature set with 2.4.x
## DP: Patch author: David Miller, Ben Greear
## DP: Upstream status: upstream
. $(dirname $0)/DPATCH
@DPATCH@
# origin: greearb (BitKeeper)
# cset: 1.2026.32.3 (2.6) key=4180303dxO_jU4ssNg8I1rEuY11kRA
# inclusion: upstream
# descrition: [VLAN]: Sync code and feature set with 2.4.x
# revision date: Fri, 12 Nov 2004 16:24:20 +0900
#
# rset: ChangeSet|1.2026.32.2..1.2026.32.3
# rset: include/linux/if_vlan.h|1.10..1.11
# rset: net/8021q/vlan.h|1.10..1.11
# rset: net/8021q/vlan.c|1.30..1.31
# rset: net/8021q/vlan_dev.c|1.21..1.22
#
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2004/10/27 16:33:17-07:00 greearb@candelatech.com
# [VLAN]: Sync code and feature set with 2.4.x
#
# Signed-off-by: David S. Miller <davem@davemloft.net>
#
# net/8021q/vlan_dev.c
# 2004/10/27 16:32:46-07:00 greearb@candelatech.com +57 -6
# [VLAN]: Sync code and feature set with 2.4.x
#
# net/8021q/vlan.h
# 2004/10/27 16:32:46-07:00 greearb@candelatech.com +2 -0
# [VLAN]: Sync code and feature set with 2.4.x
#
# net/8021q/vlan.c
# 2004/10/27 16:32:46-07:00 greearb@candelatech.com +50 -17
# [VLAN]: Sync code and feature set with 2.4.x
#
# include/linux/if_vlan.h
# 2004/10/27 16:32:46-07:00 greearb@candelatech.com +3 -1
# [VLAN]: Sync code and feature set with 2.4.x
#
diff -Nru a/include/linux/if_vlan.h b/include/linux/if_vlan.h
--- a/include/linux/if_vlan.h 2004-11-12 16:24:20 +09:00
+++ b/include/linux/if_vlan.h 2004-11-12 16:24:20 +09:00
@@ -366,7 +366,9 @@
GET_VLAN_INGRESS_PRIORITY_CMD,
GET_VLAN_EGRESS_PRIORITY_CMD,
SET_VLAN_NAME_TYPE_CMD,
- SET_VLAN_FLAG_CMD
+ SET_VLAN_FLAG_CMD,
+ GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
+ GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
};
enum vlan_name_types {
diff -Nru a/net/8021q/vlan.c b/net/8021q/vlan.c
--- a/net/8021q/vlan.c 2004-11-12 16:24:20 +09:00
+++ b/net/8021q/vlan.c 2004-11-12 16:24:20 +09:00
@@ -647,15 +647,9 @@
static int vlan_ioctl_handler(void __user *arg)
{
int err = 0;
+ unsigned short vid = 0;
struct vlan_ioctl_args args;
- /* everything here needs root permissions, except aguably the
- * hack ioctls for sending packets. However, I know _I_ don't
- * want users running that on my network! --BLG
- */
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
return -EFAULT;
@@ -669,24 +663,32 @@
switch (args.cmd) {
case SET_VLAN_INGRESS_PRIORITY_CMD:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
err = vlan_dev_set_ingress_priority(args.device1,
args.u.skb_priority,
args.vlan_qos);
break;
case SET_VLAN_EGRESS_PRIORITY_CMD:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
err = vlan_dev_set_egress_priority(args.device1,
args.u.skb_priority,
args.vlan_qos);
break;
case SET_VLAN_FLAG_CMD:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
err = vlan_dev_set_vlan_flag(args.device1,
args.u.flag,
args.vlan_qos);
break;
case SET_VLAN_NAME_TYPE_CMD:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
if ((args.u.name_type >= 0) &&
(args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
vlan_name_type = args.u.name_type;
@@ -696,17 +698,9 @@
}
break;
- /* TODO: Figure out how to pass info back...
- case GET_VLAN_INGRESS_PRIORITY_IOCTL:
- err = vlan_dev_get_ingress_priority(args);
- break;
-
- case GET_VLAN_EGRESS_PRIORITY_IOCTL:
- err = vlan_dev_get_egress_priority(args);
- break;
- */
-
case ADD_VLAN_CMD:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
/* we have been given the name of the Ethernet Device we want to
* talk to: args.dev1 We also have the
* VLAN ID: args.u.VID
@@ -719,10 +713,49 @@
break;
case DEL_VLAN_CMD:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
/* Here, the args.dev1 is the actual VLAN we want
* to get rid of.
*/
err = unregister_vlan_device(args.device1);
+ break;
+
+ case GET_VLAN_INGRESS_PRIORITY_CMD:
+ /* TODO: Implement
+ err = vlan_dev_get_ingress_priority(args);
+ if (copy_to_user((void*)arg, &args,
+ sizeof(struct vlan_ioctl_args))) {
+ err = -EFAULT;
+ }
+ */
+ err = -EINVAL;
+ break;
+ case GET_VLAN_EGRESS_PRIORITY_CMD:
+ /* TODO: Implement
+ err = vlan_dev_get_egress_priority(args.device1, &(args.args);
+ if (copy_to_user((void*)arg, &args,
+ sizeof(struct vlan_ioctl_args))) {
+ err = -EFAULT;
+ }
+ */
+ err = -EINVAL;
+ break;
+ case GET_VLAN_REALDEV_NAME_CMD:
+ err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
+ if (copy_to_user((void*)arg, &args,
+ sizeof(struct vlan_ioctl_args))) {
+ err = -EFAULT;
+ }
+ break;
+
+ case GET_VLAN_VID_CMD:
+ err = vlan_dev_get_vid(args.device1, &vid);
+ args.u.VID = vid;
+ if (copy_to_user((void*)arg, &args,
+ sizeof(struct vlan_ioctl_args))) {
+ err = -EFAULT;
+ }
break;
default:
diff -Nru a/net/8021q/vlan.h b/net/8021q/vlan.h
--- a/net/8021q/vlan.h 2004-11-12 16:24:20 +09:00
+++ b/net/8021q/vlan.h 2004-11-12 16:24:20 +09:00
@@ -66,6 +66,8 @@
int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
+int vlan_dev_get_realdev_name(const char* dev_name, char* result);
+int vlan_dev_get_vid(const char* dev_name, unsigned short* result);
void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
#endif /* !(__BEN_VLAN_802_1Q_INC__) */
diff -Nru a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
--- a/net/8021q/vlan_dev.c 2004-11-12 16:24:20 +09:00
+++ b/net/8021q/vlan_dev.c 2004-11-12 16:24:20 +09:00
@@ -1,4 +1,4 @@
-/*
+/* -*- linux-c -*-
* INET 802.1Q VLAN
* Ethernet-type device handling.
*
@@ -484,13 +484,26 @@
veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto);
#endif
- stats->tx_packets++; /* for statics only */
- stats->tx_bytes += skb->len;
-
skb->dev = VLAN_DEV_INFO(dev)->real_dev;
- dev_queue_xmit(skb);
- return 0;
+ {
+ /* Please note, dev_queue_xmit consumes the pkt regardless of the
+ * error value. So, will copy the skb first and free if successful.
+ */
+ struct sk_buff* skb2 = skb_get(skb);
+ int rv = dev_queue_xmit(skb2);
+ if (rv == 0) {
+ /* Was success, need to free the skb reference since we bumped up the
+ * user count above.
+ */
+
+ stats->tx_packets++; /* for statics only */
+ stats->tx_bytes += skb->len;
+
+ kfree_skb(skb);
+ }
+ return rv;
+ }
}
int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -621,6 +634,44 @@
return -EINVAL;
}
+
+
+int vlan_dev_get_realdev_name(const char *dev_name, char* result)
+{
+ struct net_device *dev = dev_get_by_name(dev_name);
+ int rv = 0;
+ if (dev) {
+ if (dev->priv_flags & IFF_802_1Q_VLAN) {
+ strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
+ rv = 0;
+ } else {
+ rv = -EINVAL;
+ }
+ dev_put(dev);
+ } else {
+ rv = -ENODEV;
+ }
+ return rv;
+}
+
+int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
+{
+ struct net_device *dev = dev_get_by_name(dev_name);
+ int rv = 0;
+ if (dev) {
+ if (dev->priv_flags & IFF_802_1Q_VLAN) {
+ *result = VLAN_DEV_INFO(dev)->vlan_id;
+ rv = 0;
+ } else {
+ rv = -EINVAL;
+ }
+ dev_put(dev);
+ } else {
+ rv = -ENODEV;
+ }
+ return rv;
+}
+
int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
{
#! /bin/sh -e
## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Description: Revert vlan_dev_hard_start_xmit part of Ben Greear's changes
## DP: Patch author: David Miller
## DP: Upstream status: upstream
. $(dirname $0)/DPATCH
@DPATCH@
# origin: davem (BitKeeper)
# cset: 1.2026.36.3 (2.6) key=41817f91MDHefCaP3_LsVzJAliK5ig
# inclusion: upstream
# descrition: [VLAN]: Revert vlan_dev_hard_start_xmit part of Ben Greear's changes
# revision date: Fri, 12 Nov 2004 16:24:31 +0900
#
# rset: ChangeSet|1.2026.36.2..1.2026.36.3
# rset: net/8021q/vlan_dev.c|1.22..1.23
#
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2004/10/28 16:24:01-07:00 davem@nuts.davemloft.net
# [VLAN]: Revert vlan_dev_hard_start_xmit part of Ben Greear's changes
#
# They are questionable at best. Based upon commentary
# by Tommy Christensen.
#
# Signed-off-by: David S. Miller <davem@davemloft.net>
#
# net/8021q/vlan_dev.c
# 2004/10/28 16:23:09-07:00 davem@nuts.davemloft.net +5 -18
# [VLAN]: Revert vlan_dev_hard_start_xmit part of Ben Greear's changes
#
diff -Nru a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
--- a/net/8021q/vlan_dev.c 2004-11-12 16:24:31 +09:00
+++ b/net/8021q/vlan_dev.c 2004-11-12 16:24:31 +09:00
@@ -484,26 +484,13 @@
veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto);
#endif
- skb->dev = VLAN_DEV_INFO(dev)->real_dev;
-
- {
- /* Please note, dev_queue_xmit consumes the pkt regardless of the
- * error value. So, will copy the skb first and free if successful.
- */
- struct sk_buff* skb2 = skb_get(skb);
- int rv = dev_queue_xmit(skb2);
- if (rv == 0) {
- /* Was success, need to free the skb reference since we bumped up the
- * user count above.
- */
+ stats->tx_packets++; /* for statics only */
+ stats->tx_bytes += skb->len;
- stats->tx_packets++; /* for statics only */
- stats->tx_bytes += skb->len;
+ skb->dev = VLAN_DEV_INFO(dev)->real_dev;
+ dev_queue_xmit(skb);
- kfree_skb(skb);
- }
- return rv;
- }
+ return 0;
}
int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
Reply to: