aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/rotate.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-05-13 11:14:32 -0400
committerDavid Howells <dhowells@redhat.com>2019-05-16 17:23:21 -0400
commitf642404a0436a50912c218009ccc7856d48d784c (patch)
treeddf39d1741f07866333581e66f1abc0e6709d453 /fs/afs/rotate.c
parentc925bd0ac4741badb567f594c41c8cba5e9e9732 (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.c18
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:
487bool afs_select_current_fileserver(struct afs_fs_cursor *fc) 490bool 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,