diff options
author | David Howells <dhowells@redhat.com> | 2019-05-13 11:14:32 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-05-16 17:23:21 -0400 |
commit | f642404a0436a50912c218009ccc7856d48d784c (patch) | |
tree | ddf39d1741f07866333581e66f1abc0e6709d453 /fs/afs/rotate.c | |
parent | c925bd0ac4741badb567f594c41c8cba5e9e9732 (diff) |
afs: Make vnode->cb_interest RCU safe
Use RCU-based freeing for afs_cb_interest struct objects and use RCU on
vnode->cb_interest. Use that change to allow afs_check_validity() to use
read_seqbegin_or_lock() instead of read_seqlock_excl().
This also requires the caller of afs_check_validity() to hold the RCU read
lock across the call.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs/rotate.c')
-rw-r--r-- | fs/afs/rotate.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index 52f3a9910f0d..b00c739e0e63 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c | |||
@@ -66,7 +66,8 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc, | |||
66 | fc->untried = (1UL << fc->server_list->nr_servers) - 1; | 66 | fc->untried = (1UL << fc->server_list->nr_servers) - 1; |
67 | fc->index = READ_ONCE(fc->server_list->preferred); | 67 | fc->index = READ_ONCE(fc->server_list->preferred); |
68 | 68 | ||
69 | cbi = vnode->cb_interest; | 69 | cbi = rcu_dereference_protected(vnode->cb_interest, |
70 | lockdep_is_held(&vnode->io_lock)); | ||
70 | if (cbi) { | 71 | if (cbi) { |
71 | /* See if the vnode's preferred record is still available */ | 72 | /* See if the vnode's preferred record is still available */ |
72 | for (i = 0; i < fc->server_list->nr_servers; i++) { | 73 | for (i = 0; i < fc->server_list->nr_servers; i++) { |
@@ -87,8 +88,8 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc, | |||
87 | 88 | ||
88 | /* Note that the callback promise is effectively broken */ | 89 | /* Note that the callback promise is effectively broken */ |
89 | write_seqlock(&vnode->cb_lock); | 90 | write_seqlock(&vnode->cb_lock); |
90 | ASSERTCMP(cbi, ==, vnode->cb_interest); | 91 | ASSERTCMP(cbi, ==, rcu_access_pointer(vnode->cb_interest)); |
91 | vnode->cb_interest = NULL; | 92 | rcu_assign_pointer(vnode->cb_interest, NULL); |
92 | if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) | 93 | if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) |
93 | vnode->cb_break++; | 94 | vnode->cb_break++; |
94 | write_sequnlock(&vnode->cb_lock); | 95 | write_sequnlock(&vnode->cb_lock); |
@@ -417,7 +418,9 @@ selected_server: | |||
417 | if (error < 0) | 418 | if (error < 0) |
418 | goto failed_set_error; | 419 | goto failed_set_error; |
419 | 420 | ||
420 | fc->cbi = afs_get_cb_interest(vnode->cb_interest); | 421 | fc->cbi = afs_get_cb_interest( |
422 | rcu_dereference_protected(vnode->cb_interest, | ||
423 | lockdep_is_held(&vnode->io_lock))); | ||
421 | 424 | ||
422 | read_lock(&server->fs_lock); | 425 | read_lock(&server->fs_lock); |
423 | alist = rcu_dereference_protected(server->addresses, | 426 | alist = rcu_dereference_protected(server->addresses, |
@@ -487,12 +490,15 @@ failed: | |||
487 | bool afs_select_current_fileserver(struct afs_fs_cursor *fc) | 490 | bool afs_select_current_fileserver(struct afs_fs_cursor *fc) |
488 | { | 491 | { |
489 | struct afs_vnode *vnode = fc->vnode; | 492 | struct afs_vnode *vnode = fc->vnode; |
490 | struct afs_cb_interest *cbi = vnode->cb_interest; | 493 | struct afs_cb_interest *cbi; |
491 | struct afs_addr_list *alist; | 494 | struct afs_addr_list *alist; |
492 | int error = fc->ac.error; | 495 | int error = fc->ac.error; |
493 | 496 | ||
494 | _enter(""); | 497 | _enter(""); |
495 | 498 | ||
499 | cbi = rcu_dereference_protected(vnode->cb_interest, | ||
500 | lockdep_is_held(&vnode->io_lock)); | ||
501 | |||
496 | switch (error) { | 502 | switch (error) { |
497 | case SHRT_MAX: | 503 | case SHRT_MAX: |
498 | if (!cbi) { | 504 | if (!cbi) { |
@@ -501,7 +507,7 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc) | |||
501 | return false; | 507 | return false; |
502 | } | 508 | } |
503 | 509 | ||
504 | fc->cbi = afs_get_cb_interest(vnode->cb_interest); | 510 | fc->cbi = afs_get_cb_interest(cbi); |
505 | 511 | ||
506 | read_lock(&cbi->server->fs_lock); | 512 | read_lock(&cbi->server->fs_lock); |
507 | alist = rcu_dereference_protected(cbi->server->addresses, | 513 | alist = rcu_dereference_protected(cbi->server->addresses, |