| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* AFS fileserver list management. |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved. |
|---|
| 4 | 5 | * Written by David Howells (dhowells@redhat.com) |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or |
|---|
| 7 | | - * modify it under the terms of the GNU General Public License |
|---|
| 8 | | - * as published by the Free Software Foundation; either version |
|---|
| 9 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 10 | 6 | */ |
|---|
| 11 | 7 | |
|---|
| 12 | 8 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 18 | 14 | int i; |
|---|
| 19 | 15 | |
|---|
| 20 | 16 | if (slist && refcount_dec_and_test(&slist->usage)) { |
|---|
| 21 | | - for (i = 0; i < slist->nr_servers; i++) { |
|---|
| 22 | | - afs_put_cb_interest(net, slist->servers[i].cb_interest); |
|---|
| 23 | | - afs_put_server(net, slist->servers[i].server); |
|---|
| 24 | | - } |
|---|
| 17 | + for (i = 0; i < slist->nr_servers; i++) |
|---|
| 18 | + afs_unuse_server(net, slist->servers[i].server, |
|---|
| 19 | + afs_server_trace_put_slist); |
|---|
| 25 | 20 | kfree(slist); |
|---|
| 26 | 21 | } |
|---|
| 27 | 22 | } |
|---|
| .. | .. |
|---|
| 42 | 37 | if (vldb->fs_mask[i] & type_mask) |
|---|
| 43 | 38 | nr_servers++; |
|---|
| 44 | 39 | |
|---|
| 45 | | - slist = kzalloc(sizeof(struct afs_server_list) + |
|---|
| 46 | | - sizeof(struct afs_server_entry) * nr_servers, |
|---|
| 47 | | - GFP_KERNEL); |
|---|
| 40 | + slist = kzalloc(struct_size(slist, servers, nr_servers), GFP_KERNEL); |
|---|
| 48 | 41 | if (!slist) |
|---|
| 49 | 42 | goto error; |
|---|
| 50 | 43 | |
|---|
| 51 | 44 | refcount_set(&slist->usage, 1); |
|---|
| 52 | 45 | rwlock_init(&slist->lock); |
|---|
| 53 | 46 | |
|---|
| 47 | + for (i = 0; i < AFS_MAXTYPES; i++) |
|---|
| 48 | + slist->vids[i] = vldb->vid[i]; |
|---|
| 49 | + |
|---|
| 54 | 50 | /* Make sure a records exists for each server in the list. */ |
|---|
| 55 | 51 | for (i = 0; i < vldb->nr_servers; i++) { |
|---|
| 56 | 52 | if (!(vldb->fs_mask[i] & type_mask)) |
|---|
| 57 | 53 | continue; |
|---|
| 58 | 54 | |
|---|
| 59 | | - server = afs_lookup_server(cell, key, &vldb->fs_server[i]); |
|---|
| 55 | + server = afs_lookup_server(cell, key, &vldb->fs_server[i], |
|---|
| 56 | + vldb->addr_version[i]); |
|---|
| 60 | 57 | if (IS_ERR(server)) { |
|---|
| 61 | 58 | ret = PTR_ERR(server); |
|---|
| 62 | 59 | if (ret == -ENOENT || |
|---|
| .. | .. |
|---|
| 73 | 70 | break; |
|---|
| 74 | 71 | if (j < slist->nr_servers) { |
|---|
| 75 | 72 | if (slist->servers[j].server == server) { |
|---|
| 76 | | - afs_put_server(cell->net, server); |
|---|
| 73 | + afs_put_server(cell->net, server, |
|---|
| 74 | + afs_server_trace_put_slist_isort); |
|---|
| 77 | 75 | continue; |
|---|
| 78 | 76 | } |
|---|
| 79 | 77 | |
|---|
| .. | .. |
|---|
| 118 | 116 | return false; |
|---|
| 119 | 117 | |
|---|
| 120 | 118 | changed: |
|---|
| 121 | | - /* Maintain the same current server as before if possible. */ |
|---|
| 122 | | - cur = old->servers[old->index].server; |
|---|
| 119 | + /* Maintain the same preferred server as before if possible. */ |
|---|
| 120 | + cur = old->servers[old->preferred].server; |
|---|
| 123 | 121 | for (j = 0; j < new->nr_servers; j++) { |
|---|
| 124 | 122 | if (new->servers[j].server == cur) { |
|---|
| 125 | | - new->index = j; |
|---|
| 123 | + new->preferred = j; |
|---|
| 126 | 124 | break; |
|---|
| 127 | 125 | } |
|---|
| 128 | | - } |
|---|
| 129 | | - |
|---|
| 130 | | - /* Keep the old callback interest records where possible so that we |
|---|
| 131 | | - * maintain callback interception. |
|---|
| 132 | | - */ |
|---|
| 133 | | - i = 0; |
|---|
| 134 | | - j = 0; |
|---|
| 135 | | - while (i < old->nr_servers && j < new->nr_servers) { |
|---|
| 136 | | - if (new->servers[j].server == old->servers[i].server) { |
|---|
| 137 | | - struct afs_cb_interest *cbi = old->servers[i].cb_interest; |
|---|
| 138 | | - if (cbi) { |
|---|
| 139 | | - new->servers[j].cb_interest = cbi; |
|---|
| 140 | | - refcount_inc(&cbi->usage); |
|---|
| 141 | | - } |
|---|
| 142 | | - i++; |
|---|
| 143 | | - j++; |
|---|
| 144 | | - continue; |
|---|
| 145 | | - } |
|---|
| 146 | | - |
|---|
| 147 | | - if (new->servers[j].server < old->servers[i].server) { |
|---|
| 148 | | - j++; |
|---|
| 149 | | - continue; |
|---|
| 150 | | - } |
|---|
| 151 | | - |
|---|
| 152 | | - i++; |
|---|
| 153 | | - continue; |
|---|
| 154 | 126 | } |
|---|
| 155 | 127 | |
|---|
| 156 | 128 | return true; |
|---|