diff options
author | David Howells <dhowells@redhat.com> | 2019-05-13 18:14:32 +0300 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-05-17 00:23:21 +0300 |
commit | f642404a0436a50912c218009ccc7856d48d784c (patch) | |
tree | ddf39d1741f07866333581e66f1abc0e6709d453 /fs/afs/dir.c | |
parent | c925bd0ac4741badb567f594c41c8cba5e9e9732 (diff) | |
download | linux-f642404a0436a50912c218009ccc7856d48d784c.tar.xz |
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/dir.c')
-rw-r--r-- | fs/afs/dir.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index f7344b045799..338c2260b0a0 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -638,11 +638,12 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry, struct key *key) { struct afs_lookup_cookie *cookie; - struct afs_cb_interest *cbi = NULL; + struct afs_cb_interest *dcbi, *cbi = NULL; struct afs_super_info *as = dir->i_sb->s_fs_info; struct afs_status_cb *scb; struct afs_iget_data data; struct afs_fs_cursor fc; + struct afs_server *server; struct afs_vnode *dvnode = AFS_FS_I(dir); struct inode *inode = NULL; int ret, i; @@ -658,10 +659,14 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry, cookie->nr_fids = 1; /* slot 0 is saved for the fid we actually want */ read_seqlock_excl(&dvnode->cb_lock); - if (dvnode->cb_interest && - dvnode->cb_interest->server && - test_bit(AFS_SERVER_FL_NO_IBULK, &dvnode->cb_interest->server->flags)) - cookie->one_only = true; + dcbi = rcu_dereference_protected(dvnode->cb_interest, + lockdep_is_held(&dvnode->cb_lock.lock)); + if (dcbi) { + server = dcbi->server; + if (server && + test_bit(AFS_SERVER_FL_NO_IBULK, &server->flags)) + cookie->one_only = true; + } read_sequnlock_excl(&dvnode->cb_lock); for (i = 0; i < 50; i++) |