diff options
author | Christoph Hellwig <hch@lst.de> | 2015-10-03 09:32:57 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-10-14 01:17:53 -0400 |
commit | 13a83fc9096dfaf2a7f4671b5777780bbe1d4a30 (patch) | |
tree | 2874119928c790fb2c1706a12cbc9ff305aa9644 /fs | |
parent | ea9ed9cff47e7932925982c8fdaf2d4d1708884f (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.c | 54 |
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 | ||
194 | static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page, | 193 | static 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 | ||
390 | static struct configfs_attribute *o2nm_node_attrs[] = { | 398 | static 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 | ||
398 | static 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 | |||
409 | static ssize_t o2nm_node_show(struct config_item *item, | 406 | static 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); |
446 | out: | ||
447 | return ret; | ||
448 | } | 432 | } |
449 | 433 | ||
450 | static struct configfs_item_operations o2nm_node_item_ops = { | 434 | static struct configfs_item_operations o2nm_node_item_ops = { |