mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
afs: Fix ignored callbacks over ipv4
When searching for a matching peer, all addresses need to be searched,
not just the ipv6 ones in the fs_addresses6 list.
Given that the lists no longer contain addresses, there is little
reason to splitting things between separate lists, so unify them
into a single list.
When processing an incoming callback from an ipv4 address, this would
lead to a failure to set call->server, resulting in the callback being
ignored and the client seeing stale contents.
Fixes: 72904d7b9b
("rxrpc, afs: Allow afs to pin rxrpc_peer objects")
Reported-by: Markus Suvanto <markus.suvanto@gmail.com>
Link: https://lists.infradead.org/pipermail/linux-afs/2024-February/008035.html
Signed-off-by: Marc Dionne <marc.dionne@auristor.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://lists.infradead.org/pipermail/linux-afs/2024-February/008037.html # v1
Link: https://lists.infradead.org/pipermail/linux-afs/2024-February/008066.html # v2
Link: https://lore.kernel.org/r/20240219143906.138346-2-dhowells@redhat.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
e21a2f1756
commit
bfacaf71a1
@ -321,8 +321,7 @@ struct afs_net {
|
|||||||
struct list_head fs_probe_slow; /* List of afs_server to probe at 5m intervals */
|
struct list_head fs_probe_slow; /* List of afs_server to probe at 5m intervals */
|
||||||
struct hlist_head fs_proc; /* procfs servers list */
|
struct hlist_head fs_proc; /* procfs servers list */
|
||||||
|
|
||||||
struct hlist_head fs_addresses4; /* afs_server (by lowest IPv4 addr) */
|
struct hlist_head fs_addresses; /* afs_server (by lowest IPv6 addr) */
|
||||||
struct hlist_head fs_addresses6; /* afs_server (by lowest IPv6 addr) */
|
|
||||||
seqlock_t fs_addr_lock; /* For fs_addresses[46] */
|
seqlock_t fs_addr_lock; /* For fs_addresses[46] */
|
||||||
|
|
||||||
struct work_struct fs_manager;
|
struct work_struct fs_manager;
|
||||||
@ -561,8 +560,7 @@ struct afs_server {
|
|||||||
struct afs_server __rcu *uuid_next; /* Next server with same UUID */
|
struct afs_server __rcu *uuid_next; /* Next server with same UUID */
|
||||||
struct afs_server *uuid_prev; /* Previous server with same UUID */
|
struct afs_server *uuid_prev; /* Previous server with same UUID */
|
||||||
struct list_head probe_link; /* Link in net->fs_probe_list */
|
struct list_head probe_link; /* Link in net->fs_probe_list */
|
||||||
struct hlist_node addr4_link; /* Link in net->fs_addresses4 */
|
struct hlist_node addr_link; /* Link in net->fs_addresses6 */
|
||||||
struct hlist_node addr6_link; /* Link in net->fs_addresses6 */
|
|
||||||
struct hlist_node proc_link; /* Link in net->fs_proc */
|
struct hlist_node proc_link; /* Link in net->fs_proc */
|
||||||
struct list_head volumes; /* RCU list of afs_server_entry objects */
|
struct list_head volumes; /* RCU list of afs_server_entry objects */
|
||||||
struct afs_server *gc_next; /* Next server in manager's list */
|
struct afs_server *gc_next; /* Next server in manager's list */
|
||||||
|
@ -90,8 +90,7 @@ static int __net_init afs_net_init(struct net *net_ns)
|
|||||||
INIT_LIST_HEAD(&net->fs_probe_slow);
|
INIT_LIST_HEAD(&net->fs_probe_slow);
|
||||||
INIT_HLIST_HEAD(&net->fs_proc);
|
INIT_HLIST_HEAD(&net->fs_proc);
|
||||||
|
|
||||||
INIT_HLIST_HEAD(&net->fs_addresses4);
|
INIT_HLIST_HEAD(&net->fs_addresses);
|
||||||
INIT_HLIST_HEAD(&net->fs_addresses6);
|
|
||||||
seqlock_init(&net->fs_addr_lock);
|
seqlock_init(&net->fs_addr_lock);
|
||||||
|
|
||||||
INIT_WORK(&net->fs_manager, afs_manage_servers);
|
INIT_WORK(&net->fs_manager, afs_manage_servers);
|
||||||
|
@ -38,7 +38,7 @@ struct afs_server *afs_find_server(struct afs_net *net, const struct rxrpc_peer
|
|||||||
seq++; /* 2 on the 1st/lockless path, otherwise odd */
|
seq++; /* 2 on the 1st/lockless path, otherwise odd */
|
||||||
read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
|
read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
|
||||||
|
|
||||||
hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) {
|
hlist_for_each_entry_rcu(server, &net->fs_addresses, addr_link) {
|
||||||
estate = rcu_dereference(server->endpoint_state);
|
estate = rcu_dereference(server->endpoint_state);
|
||||||
alist = estate->addresses;
|
alist = estate->addresses;
|
||||||
for (i = 0; i < alist->nr_addrs; i++)
|
for (i = 0; i < alist->nr_addrs; i++)
|
||||||
@ -177,10 +177,8 @@ added_dup:
|
|||||||
* bit, but anything we might want to do gets messy and memory
|
* bit, but anything we might want to do gets messy and memory
|
||||||
* intensive.
|
* intensive.
|
||||||
*/
|
*/
|
||||||
if (alist->nr_ipv4 > 0)
|
if (alist->nr_addrs > 0)
|
||||||
hlist_add_head_rcu(&server->addr4_link, &net->fs_addresses4);
|
hlist_add_head_rcu(&server->addr_link, &net->fs_addresses);
|
||||||
if (alist->nr_addrs > alist->nr_ipv4)
|
|
||||||
hlist_add_head_rcu(&server->addr6_link, &net->fs_addresses6);
|
|
||||||
|
|
||||||
write_sequnlock(&net->fs_addr_lock);
|
write_sequnlock(&net->fs_addr_lock);
|
||||||
|
|
||||||
@ -511,10 +509,8 @@ static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list)
|
|||||||
|
|
||||||
list_del(&server->probe_link);
|
list_del(&server->probe_link);
|
||||||
hlist_del_rcu(&server->proc_link);
|
hlist_del_rcu(&server->proc_link);
|
||||||
if (!hlist_unhashed(&server->addr4_link))
|
if (!hlist_unhashed(&server->addr_link))
|
||||||
hlist_del_rcu(&server->addr4_link);
|
hlist_del_rcu(&server->addr_link);
|
||||||
if (!hlist_unhashed(&server->addr6_link))
|
|
||||||
hlist_del_rcu(&server->addr6_link);
|
|
||||||
}
|
}
|
||||||
write_sequnlock(&net->fs_lock);
|
write_sequnlock(&net->fs_lock);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user