aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authorAndy Gospodarek <andy@greyhouse.net>2011-07-26 07:12:27 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-28 01:39:30 -0400
commitf4bb2e9c4fa9e5fdddf90589703613fd1a9c519f (patch)
tree5f47d2f426c63e1c1d787fbb69e9d52ba6136038 /drivers/net/bonding
parent550fd08c2cebad61c548def135f67aba284c6162 (diff)
bonding: fix string comparison errors
When a bond contains a device where one name is the subset of another (eth1 and eth10, for example), one cannot properly set the primary device or the currently active device. This was reported and based on work by Takuma Umeya. I also verified the problem and tested that this fix resolves it. V2: A few did not like the the current code or my changes, so I refactored bonding_store_primary and bonding_store_active_slave to be a bit cleaner, dropped the use of strnicmp since we did not really need the comparison to be case insensitive, and formatted the input string from sysfs so a comparison to IFNAMSIZ could be used. I also discovered an error in bonding_store_active_slave that would modify bond->primary_slave rather than bond->curr_active_slave before forcing the bonding driver to choose a new active slave. V3: Actually sending the proper patch.... Signed-off-by: Andy Gospodarek <andy@greyhouse.net> Reported-by: Takuma Umeya <tumeya@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_sysfs.c133
1 files changed, 71 insertions, 62 deletions
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index b60835f58650..2dfb4bf90087 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1025,6 +1025,7 @@ static ssize_t bonding_store_primary(struct device *d,
1025 int i; 1025 int i;
1026 struct slave *slave; 1026 struct slave *slave;
1027 struct bonding *bond = to_bond(d); 1027 struct bonding *bond = to_bond(d);
1028 char ifname[IFNAMSIZ];
1028 1029
1029 if (!rtnl_trylock()) 1030 if (!rtnl_trylock())
1030 return restart_syscall(); 1031 return restart_syscall();
@@ -1035,32 +1036,33 @@ static ssize_t bonding_store_primary(struct device *d,
1035 if (!USES_PRIMARY(bond->params.mode)) { 1036 if (!USES_PRIMARY(bond->params.mode)) {
1036 pr_info("%s: Unable to set primary slave; %s is in mode %d\n", 1037 pr_info("%s: Unable to set primary slave; %s is in mode %d\n",
1037 bond->dev->name, bond->dev->name, bond->params.mode); 1038 bond->dev->name, bond->dev->name, bond->params.mode);
1038 } else { 1039 goto out;
1039 bond_for_each_slave(bond, slave, i) { 1040 }
1040 if (strnicmp
1041 (slave->dev->name, buf,
1042 strlen(slave->dev->name)) == 0) {
1043 pr_info("%s: Setting %s as primary slave.\n",
1044 bond->dev->name, slave->dev->name);
1045 bond->primary_slave = slave;
1046 strcpy(bond->params.primary, slave->dev->name);
1047 bond_select_active_slave(bond);
1048 goto out;
1049 }
1050 }
1051 1041
1052 /* if we got here, then we didn't match the name of any slave */ 1042 sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
1053 1043
1054 if (strlen(buf) == 0 || buf[0] == '\n') { 1044 /* check to see if we are clearing primary */
1055 pr_info("%s: Setting primary slave to None.\n", 1045 if (!strlen(ifname) || buf[0] == '\n') {
1056 bond->dev->name); 1046 pr_info("%s: Setting primary slave to None.\n",
1057 bond->primary_slave = NULL; 1047 bond->dev->name);
1058 bond_select_active_slave(bond); 1048 bond->primary_slave = NULL;
1059 } else { 1049 bond_select_active_slave(bond);
1060 pr_info("%s: Unable to set %.*s as primary slave as it is not a slave.\n", 1050 goto out;
1061 bond->dev->name, (int)strlen(buf) - 1, buf); 1051 }
1052
1053 bond_for_each_slave(bond, slave, i) {
1054 if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
1055 pr_info("%s: Setting %s as primary slave.\n",
1056 bond->dev->name, slave->dev->name);
1057 bond->primary_slave = slave;
1058 strcpy(bond->params.primary, slave->dev->name);
1059 bond_select_active_slave(bond);
1060 goto out;
1062 } 1061 }
1063 } 1062 }
1063
1064 pr_info("%s: Unable to set %.*s as primary slave.\n",
1065 bond->dev->name, (int)strlen(buf) - 1, buf);
1064out: 1066out:
1065 write_unlock_bh(&bond->curr_slave_lock); 1067 write_unlock_bh(&bond->curr_slave_lock);
1066 read_unlock(&bond->lock); 1068 read_unlock(&bond->lock);
@@ -1195,6 +1197,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
1195 struct slave *old_active = NULL; 1197 struct slave *old_active = NULL;
1196 struct slave *new_active = NULL; 1198 struct slave *new_active = NULL;
1197 struct bonding *bond = to_bond(d); 1199 struct bonding *bond = to_bond(d);
1200 char ifname[IFNAMSIZ];
1198 1201
1199 if (!rtnl_trylock()) 1202 if (!rtnl_trylock())
1200 return restart_syscall(); 1203 return restart_syscall();
@@ -1203,56 +1206,62 @@ static ssize_t bonding_store_active_slave(struct device *d,
1203 read_lock(&bond->lock); 1206 read_lock(&bond->lock);
1204 write_lock_bh(&bond->curr_slave_lock); 1207 write_lock_bh(&bond->curr_slave_lock);
1205 1208
1206 if (!USES_PRIMARY(bond->params.mode)) 1209 if (!USES_PRIMARY(bond->params.mode)) {
1207 pr_info("%s: Unable to change active slave; %s is in mode %d\n", 1210 pr_info("%s: Unable to change active slave; %s is in mode %d\n",
1208 bond->dev->name, bond->dev->name, bond->params.mode); 1211 bond->dev->name, bond->dev->name, bond->params.mode);
1209 else { 1212 goto out;
1210 bond_for_each_slave(bond, slave, i) { 1213 }
1211 if (strnicmp 1214
1212 (slave->dev->name, buf, 1215 sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
1213 strlen(slave->dev->name)) == 0) { 1216
1214 old_active = bond->curr_active_slave; 1217 /* check to see if we are clearing active */
1215 new_active = slave; 1218 if (!strlen(ifname) || buf[0] == '\n') {
1216 if (new_active == old_active) { 1219 pr_info("%s: Clearing current active slave.\n",
1217 /* do nothing */ 1220 bond->dev->name);
1218 pr_info("%s: %s is already the current active slave.\n", 1221 bond->curr_active_slave = NULL;
1222 bond_select_active_slave(bond);
1223 goto out;
1224 }
1225
1226 bond_for_each_slave(bond, slave, i) {
1227 if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
1228 old_active = bond->curr_active_slave;
1229 new_active = slave;
1230 if (new_active == old_active) {
1231 /* do nothing */
1232 pr_info("%s: %s is already the current"
1233 " active slave.\n",
1234 bond->dev->name,
1235 slave->dev->name);
1236 goto out;
1237 }
1238 else {
1239 if ((new_active) &&
1240 (old_active) &&
1241 (new_active->link == BOND_LINK_UP) &&
1242 IS_UP(new_active->dev)) {
1243 pr_info("%s: Setting %s as active"
1244 " slave.\n",
1219 bond->dev->name, 1245 bond->dev->name,
1220 slave->dev->name); 1246 slave->dev->name);
1221 goto out; 1247 bond_change_active_slave(bond,
1248 new_active);
1222 } 1249 }
1223 else { 1250 else {
1224 if ((new_active) && 1251 pr_info("%s: Could not set %s as"
1225 (old_active) && 1252 " active slave; either %s is"
1226 (new_active->link == BOND_LINK_UP) && 1253 " down or the link is down.\n",
1227 IS_UP(new_active->dev)) { 1254 bond->dev->name,
1228 pr_info("%s: Setting %s as active slave.\n", 1255 slave->dev->name,
1229 bond->dev->name, 1256 slave->dev->name);
1230 slave->dev->name);
1231 bond_change_active_slave(bond, new_active);
1232 }
1233 else {
1234 pr_info("%s: Could not set %s as active slave; either %s is down or the link is down.\n",
1235 bond->dev->name,
1236 slave->dev->name,
1237 slave->dev->name);
1238 }
1239 goto out;
1240 } 1257 }
1258 goto out;
1241 } 1259 }
1242 } 1260 }
1243
1244 /* if we got here, then we didn't match the name of any slave */
1245
1246 if (strlen(buf) == 0 || buf[0] == '\n') {
1247 pr_info("%s: Setting active slave to None.\n",
1248 bond->dev->name);
1249 bond->primary_slave = NULL;
1250 bond_select_active_slave(bond);
1251 } else {
1252 pr_info("%s: Unable to set %.*s as active slave as it is not a slave.\n",
1253 bond->dev->name, (int)strlen(buf) - 1, buf);
1254 }
1255 } 1261 }
1262
1263 pr_info("%s: Unable to set %.*s as active slave.\n",
1264 bond->dev->name, (int)strlen(buf) - 1, buf);
1256 out: 1265 out:
1257 write_unlock_bh(&bond->curr_slave_lock); 1266 write_unlock_bh(&bond->curr_slave_lock);
1258 read_unlock(&bond->lock); 1267 read_unlock(&bond->lock);