summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-10-03 09:32:57 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2015-10-14 01:17:53 -0400
commit13a83fc9096dfaf2a7f4671b5777780bbe1d4a30 (patch)
tree2874119928c790fb2c1706a12cbc9ff305aa9644 /fs
parentea9ed9cff47e7932925982c8fdaf2d4d1708884f (diff)
ocfs2/cluster: move locking into attribute store methods
The test and separate set bit scheme was racy to start with, so move to do a test_and_set_bit after doing the earlier error checks inside the actual store methods. Also remove the locking for the local attribute which already has a different scheme to synchronize. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/cluster/nodemanager.c54
1 files changed, 19 insertions, 35 deletions
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index 441c84e169e6..7a398f6346ed 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -188,7 +188,6 @@ enum {
188 O2NM_NODE_ATTR_NUM = 0, 188 O2NM_NODE_ATTR_NUM = 0,
189 O2NM_NODE_ATTR_PORT, 189 O2NM_NODE_ATTR_PORT,
190 O2NM_NODE_ATTR_ADDRESS, 190 O2NM_NODE_ATTR_ADDRESS,
191 O2NM_NODE_ATTR_LOCAL,
192}; 191};
193 192
194static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page, 193static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page,
@@ -197,6 +196,7 @@ static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page,
197 struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); 196 struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
198 unsigned long tmp; 197 unsigned long tmp;
199 char *p = (char *)page; 198 char *p = (char *)page;
199 int ret = 0;
200 200
201 tmp = simple_strtoul(p, &p, 0); 201 tmp = simple_strtoul(p, &p, 0);
202 if (!p || (*p && (*p != '\n'))) 202 if (!p || (*p && (*p != '\n')))
@@ -215,15 +215,18 @@ static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page,
215 215
216 write_lock(&cluster->cl_nodes_lock); 216 write_lock(&cluster->cl_nodes_lock);
217 if (cluster->cl_nodes[tmp]) 217 if (cluster->cl_nodes[tmp])
218 p = NULL; 218 ret = -EEXIST;
219 else if (test_and_set_bit(O2NM_NODE_ATTR_NUM,
220 &node->nd_set_attributes))
221 ret = -EBUSY;
219 else { 222 else {
220 cluster->cl_nodes[tmp] = node; 223 cluster->cl_nodes[tmp] = node;
221 node->nd_num = tmp; 224 node->nd_num = tmp;
222 set_bit(tmp, cluster->cl_nodes_bitmap); 225 set_bit(tmp, cluster->cl_nodes_bitmap);
223 } 226 }
224 write_unlock(&cluster->cl_nodes_lock); 227 write_unlock(&cluster->cl_nodes_lock);
225 if (p == NULL) 228 if (ret)
226 return -EEXIST; 229 return ret;
227 230
228 return count; 231 return count;
229} 232}
@@ -247,6 +250,8 @@ static ssize_t o2nm_node_ipv4_port_write(struct o2nm_node *node,
247 if (tmp >= (u16)-1) 250 if (tmp >= (u16)-1)
248 return -ERANGE; 251 return -ERANGE;
249 252
253 if (test_and_set_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
254 return -EBUSY;
250 node->nd_ipv4_port = htons(tmp); 255 node->nd_ipv4_port = htons(tmp);
251 256
252 return count; 257 return count;
@@ -282,6 +287,9 @@ static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node,
282 write_lock(&cluster->cl_nodes_lock); 287 write_lock(&cluster->cl_nodes_lock);
283 if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent)) 288 if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent))
284 ret = -EEXIST; 289 ret = -EEXIST;
290 else if (test_and_set_bit(O2NM_NODE_ATTR_ADDRESS,
291 &node->nd_set_attributes))
292 ret = -EBUSY;
285 else { 293 else {
286 rb_link_node(&node->nd_ip_node, parent, p); 294 rb_link_node(&node->nd_ip_node, parent, p);
287 rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree); 295 rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree);
@@ -388,24 +396,13 @@ static struct o2nm_node_attribute o2nm_node_attr_local = {
388}; 396};
389 397
390static struct configfs_attribute *o2nm_node_attrs[] = { 398static struct configfs_attribute *o2nm_node_attrs[] = {
391 [O2NM_NODE_ATTR_NUM] = &o2nm_node_attr_num.attr, 399 &o2nm_node_attr_num.attr,
392 [O2NM_NODE_ATTR_PORT] = &o2nm_node_attr_ipv4_port.attr, 400 &o2nm_node_attr_ipv4_port.attr,
393 [O2NM_NODE_ATTR_ADDRESS] = &o2nm_node_attr_ipv4_address.attr, 401 &o2nm_node_attr_ipv4_address.attr,
394 [O2NM_NODE_ATTR_LOCAL] = &o2nm_node_attr_local.attr, 402 &o2nm_node_attr_local.attr,
395 NULL, 403 NULL,
396}; 404};
397 405
398static int o2nm_attr_index(struct configfs_attribute *attr)
399{
400 int i;
401 for (i = 0; i < ARRAY_SIZE(o2nm_node_attrs); i++) {
402 if (attr == o2nm_node_attrs[i])
403 return i;
404 }
405 BUG();
406 return 0;
407}
408
409static ssize_t o2nm_node_show(struct config_item *item, 406static ssize_t o2nm_node_show(struct config_item *item,
410 struct configfs_attribute *attr, 407 struct configfs_attribute *attr,
411 char *page) 408 char *page)
@@ -427,24 +424,11 @@ static ssize_t o2nm_node_store(struct config_item *item,
427 struct o2nm_node *node = to_o2nm_node(item); 424 struct o2nm_node *node = to_o2nm_node(item);
428 struct o2nm_node_attribute *o2nm_node_attr = 425 struct o2nm_node_attribute *o2nm_node_attr =
429 container_of(attr, struct o2nm_node_attribute, attr); 426 container_of(attr, struct o2nm_node_attribute, attr);
430 ssize_t ret;
431 int attr_index = o2nm_attr_index(attr);
432 427
433 if (o2nm_node_attr->store == NULL) { 428 if (o2nm_node_attr->store == NULL)
434 ret = -EINVAL; 429 return -EINVAL;
435 goto out;
436 }
437
438 if (test_bit(attr_index, &node->nd_set_attributes))
439 return -EBUSY;
440
441 ret = o2nm_node_attr->store(node, page, count);
442 if (ret < count)
443 goto out;
444 430
445 set_bit(attr_index, &node->nd_set_attributes); 431 return o2nm_node_attr->store(node, page, count);
446out:
447 return ret;
448} 432}
449 433
450static struct configfs_item_operations o2nm_node_item_ops = { 434static struct configfs_item_operations o2nm_node_item_ops = {