diff options
| -rw-r--r-- | fs/afs/Makefile | 4 | ||||
| -rw-r--r-- | fs/afs/addr_list.c | 40 | ||||
| -rw-r--r-- | fs/afs/cmservice.c | 129 | ||||
| -rw-r--r-- | fs/afs/fs_probe.c | 270 | ||||
| -rw-r--r-- | fs/afs/fsclient.c | 27 | ||||
| -rw-r--r-- | fs/afs/internal.h | 98 | ||||
| -rw-r--r-- | fs/afs/proc.c | 6 | ||||
| -rw-r--r-- | fs/afs/rotate.c | 174 | ||||
| -rw-r--r-- | fs/afs/rxrpc.c | 44 | ||||
| -rw-r--r-- | fs/afs/server.c | 109 | ||||
| -rw-r--r-- | fs/afs/server_list.c | 6 | ||||
| -rw-r--r-- | fs/afs/vl_list.c | 6 | ||||
| -rw-r--r-- | fs/afs/vl_probe.c | 273 | ||||
| -rw-r--r-- | fs/afs/vl_rotate.c | 159 | ||||
| -rw-r--r-- | fs/afs/vlclient.c | 35 | ||||
| -rw-r--r-- | fs/afs/volume.c | 16 | ||||
| -rw-r--r-- | include/trace/events/afs.h | 4 |
17 files changed, 1050 insertions, 350 deletions
diff --git a/fs/afs/Makefile b/fs/afs/Makefile index cc942b790cff..0738e2bf5193 100644 --- a/fs/afs/Makefile +++ b/fs/afs/Makefile | |||
| @@ -17,6 +17,7 @@ kafs-y := \ | |||
| 17 | file.o \ | 17 | file.o \ |
| 18 | flock.o \ | 18 | flock.o \ |
| 19 | fsclient.o \ | 19 | fsclient.o \ |
| 20 | fs_probe.o \ | ||
| 20 | inode.o \ | 21 | inode.o \ |
| 21 | main.o \ | 22 | main.o \ |
| 22 | misc.o \ | 23 | misc.o \ |
| @@ -29,8 +30,9 @@ kafs-y := \ | |||
| 29 | super.o \ | 30 | super.o \ |
| 30 | netdevices.o \ | 31 | netdevices.o \ |
| 31 | vlclient.o \ | 32 | vlclient.o \ |
| 32 | vl_rotate.o \ | ||
| 33 | vl_list.o \ | 33 | vl_list.o \ |
| 34 | vl_probe.o \ | ||
| 35 | vl_rotate.o \ | ||
| 34 | volume.o \ | 36 | volume.o \ |
| 35 | write.o \ | 37 | write.o \ |
| 36 | xattr.o \ | 38 | xattr.o \ |
diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c index 1536d1d21c33..967db336d11a 100644 --- a/fs/afs/addr_list.c +++ b/fs/afs/addr_list.c | |||
| @@ -303,6 +303,8 @@ void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port) | |||
| 303 | sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); | 303 | sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); |
| 304 | 304 | ||
| 305 | srx = &alist->addrs[i]; | 305 | srx = &alist->addrs[i]; |
| 306 | srx->srx_family = AF_RXRPC; | ||
| 307 | srx->transport_type = SOCK_DGRAM; | ||
| 306 | srx->transport_len = sizeof(srx->transport.sin); | 308 | srx->transport_len = sizeof(srx->transport.sin); |
| 307 | srx->transport.sin.sin_family = AF_INET; | 309 | srx->transport.sin.sin_family = AF_INET; |
| 308 | srx->transport.sin.sin_port = htons(port); | 310 | srx->transport.sin.sin_port = htons(port); |
| @@ -341,6 +343,8 @@ void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port) | |||
| 341 | sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); | 343 | sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); |
| 342 | 344 | ||
| 343 | srx = &alist->addrs[i]; | 345 | srx = &alist->addrs[i]; |
| 346 | srx->srx_family = AF_RXRPC; | ||
| 347 | srx->transport_type = SOCK_DGRAM; | ||
| 344 | srx->transport_len = sizeof(srx->transport.sin6); | 348 | srx->transport_len = sizeof(srx->transport.sin6); |
| 345 | srx->transport.sin6.sin6_family = AF_INET6; | 349 | srx->transport.sin6.sin6_family = AF_INET6; |
| 346 | srx->transport.sin6.sin6_port = htons(port); | 350 | srx->transport.sin6.sin6_port = htons(port); |
| @@ -353,23 +357,32 @@ void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port) | |||
| 353 | */ | 357 | */ |
| 354 | bool afs_iterate_addresses(struct afs_addr_cursor *ac) | 358 | bool afs_iterate_addresses(struct afs_addr_cursor *ac) |
| 355 | { | 359 | { |
| 356 | _enter("%hu+%hd", ac->start, (short)ac->index); | 360 | unsigned long set, failed; |
| 361 | int index; | ||
| 357 | 362 | ||
| 358 | if (!ac->alist) | 363 | if (!ac->alist) |
| 359 | return false; | 364 | return false; |
| 360 | 365 | ||
| 366 | set = ac->alist->responded; | ||
| 367 | failed = ac->alist->failed; | ||
| 368 | _enter("%lx-%lx-%lx,%d", set, failed, ac->tried, ac->index); | ||
| 369 | |||
| 361 | ac->nr_iterations++; | 370 | ac->nr_iterations++; |
| 362 | 371 | ||
| 363 | if (ac->begun) { | 372 | set &= ~(failed | ac->tried); |
| 364 | ac->index++; | ||
| 365 | if (ac->index == ac->alist->nr_addrs) | ||
| 366 | ac->index = 0; | ||
| 367 | 373 | ||
| 368 | if (ac->index == ac->start) | 374 | if (!set) |
| 369 | return false; | 375 | return false; |
| 370 | } | 376 | |
| 377 | index = READ_ONCE(ac->alist->preferred); | ||
| 378 | if (test_bit(index, &set)) | ||
| 379 | goto selected; | ||
| 380 | |||
| 381 | index = __ffs(set); | ||
| 371 | 382 | ||
| 372 | ac->begun = true; | 383 | selected: |
| 384 | ac->index = index; | ||
| 385 | set_bit(index, &ac->tried); | ||
| 373 | ac->responded = false; | 386 | ac->responded = false; |
| 374 | return true; | 387 | return true; |
| 375 | } | 388 | } |
| @@ -383,12 +396,13 @@ int afs_end_cursor(struct afs_addr_cursor *ac) | |||
| 383 | 396 | ||
| 384 | alist = ac->alist; | 397 | alist = ac->alist; |
| 385 | if (alist) { | 398 | if (alist) { |
| 386 | if (ac->responded && ac->index != ac->start) | 399 | if (ac->responded && |
| 387 | WRITE_ONCE(alist->index, ac->index); | 400 | ac->index != alist->preferred && |
| 401 | test_bit(ac->alist->preferred, &ac->tried)) | ||
| 402 | WRITE_ONCE(alist->preferred, ac->index); | ||
| 388 | afs_put_addrlist(alist); | 403 | afs_put_addrlist(alist); |
| 404 | ac->alist = NULL; | ||
| 389 | } | 405 | } |
| 390 | 406 | ||
| 391 | ac->alist = NULL; | ||
| 392 | ac->begun = false; | ||
| 393 | return ac->error; | 407 | return ac->error; |
| 394 | } | 408 | } |
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index 8cf8d10daa6c..8ee5972893ed 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c | |||
| @@ -122,6 +122,8 @@ bool afs_cm_incoming_call(struct afs_call *call) | |||
| 122 | { | 122 | { |
| 123 | _enter("{%u, CB.OP %u}", call->service_id, call->operation_ID); | 123 | _enter("{%u, CB.OP %u}", call->service_id, call->operation_ID); |
| 124 | 124 | ||
| 125 | call->epoch = rxrpc_kernel_get_epoch(call->net->socket, call->rxcall); | ||
| 126 | |||
| 125 | switch (call->operation_ID) { | 127 | switch (call->operation_ID) { |
| 126 | case CBCallBack: | 128 | case CBCallBack: |
| 127 | call->type = &afs_SRXCBCallBack; | 129 | call->type = &afs_SRXCBCallBack; |
| @@ -152,6 +154,91 @@ bool afs_cm_incoming_call(struct afs_call *call) | |||
| 152 | } | 154 | } |
| 153 | 155 | ||
| 154 | /* | 156 | /* |
| 157 | * Record a probe to the cache manager from a server. | ||
| 158 | */ | ||
| 159 | static int afs_record_cm_probe(struct afs_call *call, struct afs_server *server) | ||
| 160 | { | ||
| 161 | _enter(""); | ||
| 162 | |||
| 163 | if (test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags) && | ||
| 164 | !test_bit(AFS_SERVER_FL_PROBING, &server->flags)) { | ||
| 165 | if (server->cm_epoch == call->epoch) | ||
| 166 | return 0; | ||
| 167 | |||
| 168 | if (!server->probe.said_rebooted) { | ||
| 169 | pr_notice("kAFS: FS rebooted %pU\n", &server->uuid); | ||
| 170 | server->probe.said_rebooted = true; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | spin_lock(&server->probe_lock); | ||
| 175 | |||
| 176 | if (!test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags)) { | ||
| 177 | server->cm_epoch = call->epoch; | ||
| 178 | server->probe.cm_epoch = call->epoch; | ||
| 179 | goto out; | ||
| 180 | } | ||
| 181 | |||
| 182 | if (server->probe.cm_probed && | ||
| 183 | call->epoch != server->probe.cm_epoch && | ||
| 184 | !server->probe.said_inconsistent) { | ||
| 185 | pr_notice("kAFS: FS endpoints inconsistent %pU\n", | ||
| 186 | &server->uuid); | ||
| 187 | server->probe.said_inconsistent = true; | ||
| 188 | } | ||
| 189 | |||
| 190 | if (!server->probe.cm_probed || call->epoch == server->cm_epoch) | ||
| 191 | server->probe.cm_epoch = server->cm_epoch; | ||
| 192 | |||
| 193 | out: | ||
| 194 | server->probe.cm_probed = true; | ||
| 195 | spin_unlock(&server->probe_lock); | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | |||
| 199 | /* | ||
| 200 | * Find the server record by peer address and record a probe to the cache | ||
| 201 | * manager from a server. | ||
| 202 | */ | ||
| 203 | static int afs_find_cm_server_by_peer(struct afs_call *call) | ||
| 204 | { | ||
| 205 | struct sockaddr_rxrpc srx; | ||
| 206 | struct afs_server *server; | ||
| 207 | |||
| 208 | rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx); | ||
| 209 | |||
| 210 | server = afs_find_server(call->net, &srx); | ||
| 211 | if (!server) { | ||
| 212 | trace_afs_cm_no_server(call, &srx); | ||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | call->cm_server = server; | ||
| 217 | return afs_record_cm_probe(call, server); | ||
| 218 | } | ||
| 219 | |||
