aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Nenciarini <mnencia@debian.org>2006-07-11 16:08:40 -0700
committerStephen Hemminger <shemminger@dxpl.pdx.osdl.net>2006-07-11 16:08:40 -0700
commit4d480f55ae79cd3b3d1b2681a852e8317a23c977 (patch)
tree83ebf434b0ccfee2c6c30cf9232f068e82b755e9
parent3f28faf1a984ae611bc37ff9b9cdd21071df771b (diff)
downloadandroid_external_brctl-4d480f55ae79cd3b3d1b2681a852e8317a23c977.tar.gz
android_external_brctl-4d480f55ae79cd3b3d1b2681a852e8317a23c977.tar.bz2
android_external_brctl-4d480f55ae79cd3b3d1b2681a852e8317a23c977.zip
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=376914
some libsysfs2 internal stucts are corrupted during execution of brctl by unneeded and erroneous calls to sysfs_close_class_device() Long description of my troubles On my xen Dom0 with 5 bridges and many interfaces every brctl show invocations fails with a strange error. bridge name bridge id STP enabled interfaces xenbr0 8000.feffffffffff no vif1.0 peth0 vif0.0 xenbr1 8000.feffffffffff no vif3.0 vif2.0 vif1.1 peth1 vif0.1 xenbr2 8000.feffffffffff no vif1.2 peth2 vif0.2 xenbr3 8000.feffffffffff no can't get port info: No such device xenbr4 8000.feffffffffff no vif2.2 peth4 vif0.4 but xenbr3 was fully up and functional, as stated by the contents of /sys/class/net/xenbr3 directory. Investigating with strace i've found that brctl give this error because it is trying to read xenbr3 interfaces in /sys/class/net/eth0/brif directory! ..... lstat64("/sys/class/net/xenbr3/bridge/topology_change_detected", {st_mode=S_IFREG|0444, st_size=4096, ...}) = 0 stat64("/sys/class/net/xenbr3/bridge/topology_change_detected", {st_mode=S_IFREG|0444, st_size=4096, ...}) = 0 open("/sys/class/net/xenbr3/bridge/topology_change_detected", O_RDONLY) = 4 read(4, "0\n", 4096) = 2 close(4) = 0 open("/sys/class/net/eth0/brif", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY) = -1 ENOENT (No such file or directory) ioctl(3, SIOCDEVPRIVATE, 0xafdec36c) = -1 ENODEV (No such device) write(1, "8000.feffffffffff\tno\t\t can\'t get"..., 59) = 59 lstat64("/sys/class/net/xenbr4/bridge", {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0 write(1, "xenbr4\t\t", 8) = 8 ..... after some gdb and documentation reading sessions i've discovered that all calls to sysfs_close_class_device() in libbridge code are wrong, because their arguments are pointers returned by sysfs_get_* functions. This is explicitly forbidden by libsysfs documentation[1] at 6.1.b and corrupt libsysfs internal structures freeing memory that still being used. [1] /usr/share/doc/libsysfs-dev/libsysfs.txt.gz ..... 6.1 Calling Conventions in Libsysfs ----------------------------------- Libsysfs uses a simple API calling convention. APIs are classified to be one of "open", "get", "close" types. The convention is as follows: a. All "open" APIs have a corresponding "close" API. b. References obtained using "get" calls should not be closed explicitly. c. All "opened" references have to be closed with a call to their corresponding "close" call. This takes care of freeing structure references obtained with "get" calls. ..... I have checked all other sysfs_close_* calls and they seem to be correct. Attached patch removes the wrong call, so i can operate correctly on my bridges.
-rw-r--r--libbridge/libbridge_devif.c6
1 files changed, 0 insertions, 6 deletions
diff --git a/libbridge/libbridge_devif.c b/libbridge/libbridge_devif.c
index d3052a1..3703f4b 100644
--- a/libbridge/libbridge_devif.c
+++ b/libbridge/libbridge_devif.c
@@ -188,7 +188,6 @@ int br_get_bridge_info(const char *bridge, struct bridge_info *info)
snprintf(path, SYSFS_PATH_MAX, "%s/bridge", dev->path);
if (sysfs_path_is_dir(path)) {
dprintf("path '%s' is not a directory\n", path);
- sysfs_close_class_device(dev);
goto fallback;
}
@@ -214,7 +213,6 @@ int br_get_bridge_info(const char *bridge, struct bridge_info *info)
info->topology_change = fetch_int(dev, BRIDGEATTR("topology_change"));
info->topology_change_detected = fetch_int(dev,
BRIDGEATTR("topology_change_detected"));
- sysfs_close_class_device(dev);
return 0;
@@ -287,7 +285,6 @@ int br_get_port_info(const char *brname, const char *port,
snprintf(path, SYSFS_PATH_MAX, "%s/brport", dev->path);
if (sysfs_path_is_dir(path)) {
- sysfs_close_class_device(dev);
goto fallback;
}
@@ -309,7 +306,6 @@ int br_get_port_info(const char *brname, const char *port,
&info->forward_delay_timer_value);
fetch_tv(dev, BRPORT("hold_timer"),
&info->hold_timer_value);
- sysfs_close_class_device(dev);
return 0;
fallback:
@@ -339,7 +335,6 @@ static int br_set(const char *bridge, const char *name,
ret = sysfs_write_attribute(attr, buf, strlen(buf));
sysfs_close_attribute(attr);
}
- sysfs_close_class_device(dev);
} else
#endif
{
@@ -411,7 +406,6 @@ static int port_set(const char *bridge, const char *ifname,
ret = sysfs_write_attribute(attr, buf, strlen(buf));
sysfs_close_attribute(attr);
}
- sysfs_close_class_device(dev);
} else
#endif
{