diff options
author | David Howells <dhowells@redhat.com> | 2019-05-07 10:16:26 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-05-15 12:35:53 -0400 |
commit | 6b8812fc8ec28c13c09c89f88ce3958f19238838 (patch) | |
tree | 9cbdfed7205a1b2255706b1293893639b1122ba4 /fs/afs | |
parent | 773e0c40253443e0ce5491cb0e414b62f7cc45ed (diff) |
afs: Fix missing lock when replacing VL server list
When afs_update_cell() replaces the cell->vl_servers list, it uses RCU
protocol so that proc is protected, but doesn't take ->vl_servers_lock to
protect afs_start_vl_iteration() (which does actually take a shared lock).
Fix this by making afs_update_cell() take an exclusive lock when replacing
->vl_servers.
Fixes: 0a5143f2f89c ("afs: Implement VL server rotation")
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs')
-rw-r--r-- | fs/afs/cell.c | 5 |
1 files changed, 2 insertions, 3 deletions
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index 9de46116c749..9ca075e11239 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
@@ -404,12 +404,11 @@ static void afs_update_cell(struct afs_cell *cell) | |||
404 | clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags); | 404 | clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags); |
405 | clear_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags); | 405 | clear_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags); |
406 | 406 | ||
407 | /* Exclusion on changing vl_addrs is achieved by a | 407 | write_lock(&cell->vl_servers_lock); |
408 | * non-reentrant work item. | ||
409 | */ | ||
410 | old = rcu_dereference_protected(cell->vl_servers, true); | 408 | old = rcu_dereference_protected(cell->vl_servers, true); |
411 | rcu_assign_pointer(cell->vl_servers, vllist); | 409 | rcu_assign_pointer(cell->vl_servers, vllist); |
412 | cell->dns_expiry = expiry; | 410 | cell->dns_expiry = expiry; |
411 | write_unlock(&cell->vl_servers_lock); | ||
413 | 412 | ||
414 | if (old) | 413 | if (old) |
415 | afs_put_vlserverlist(cell->net, old); | 414 | afs_put_vlserverlist(cell->net, old); |