datapath: Fix OOPS when dp_sysfs_add_if() fails.
authorBen Pfaff <blp@nicira.com>
Wed, 5 Aug 2009 22:22:25 +0000 (15:22 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 6 Aug 2009 23:57:06 +0000 (16:57 -0700)
commit58c342f617051e9e2ffb09710b4ef2b22c34e79a
treef52309ca52d45bd920cef58c9e30fc2cc8d1ca3a
parent3de35df914e39692470a5d4546cb1fae2d93a316
datapath: Fix OOPS when dp_sysfs_add_if() fails.

Until now, when dp_sysfs_add_if() failed, the caller ignored the failure.
This is a minor problem, because everything else should continue working,
without sysfs entries for the interface, in theory anyhow.  In actual
practice, the error exit path of dp_sysfs_add_if() does a kobject_put(),
and that kobject_put() calls release_nbp(), so that the new port gets
freed.  The next reference to the new port (usually in an ovs-vswitchd call
to the ODP_PORT_LIST ioctl) will then use the freed data and probably OOPS.

The fix is to make the datapath code, as opposed to the sysfs code,
responsible for creating and destroying the net_bridge_port kobject.  The
dp_sysfs_{add,del}_if() functions then just attach and detach the kobject
to sysfs and their cleanup routines no longer need to destroy the kobject
and indeed we don't care whether dp_sysfs_add_if() really succeeds.

This commit also makes the same transformation to the datapath's ifobj,
for consistency.

It is easy to trigger the OOPS fixed by this commit by adding a network
device A to a datapath, then renaming network device A to B, then renaming
network device C to A, then adding A to the datapath.  The last attempt to
add A will fail because a file named /sys/class/net/<datapath>/brif/A
already exists from the time that C was added to the datapath under the
name A.

This commit also adds some compatibility infrastructure, because it moves
code out of #ifdef SUPPORT_SYSFS and it otherwise wouldn't build.
datapath/datapath.c
datapath/datapath.h
datapath/dp_sysfs.h
datapath/dp_sysfs_dp.c
datapath/dp_sysfs_if.c
datapath/linux-2.6/Modules.mk
datapath/linux-2.6/compat-2.6/include/linux/kobject.h [new file with mode: 0644]
datapath/linux-2.6/compat-2.6/include/linux/netdevice.h