Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.19-rc6 619 lines 15 kB view raw
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* AFS Cache Manager Service 3 * 4 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8#include <linux/module.h> 9#include <linux/init.h> 10#include <linux/slab.h> 11#include <linux/sched.h> 12#include <linux/ip.h> 13#include "internal.h" 14#include "afs_cm.h" 15#include "protocol_yfs.h" 16#define RXRPC_TRACE_ONLY_DEFINE_ENUMS 17#include <trace/events/rxrpc.h> 18 19static int afs_deliver_cb_init_call_back_state(struct afs_call *); 20static int afs_deliver_cb_init_call_back_state3(struct afs_call *); 21static int afs_deliver_cb_probe(struct afs_call *); 22static int afs_deliver_cb_callback(struct afs_call *); 23static int afs_deliver_cb_probe_uuid(struct afs_call *); 24static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *); 25static void afs_cm_destructor(struct afs_call *); 26static void SRXAFSCB_CallBack(struct work_struct *); 27static void SRXAFSCB_InitCallBackState(struct work_struct *); 28static void SRXAFSCB_Probe(struct work_struct *); 29static void SRXAFSCB_ProbeUuid(struct work_struct *); 30static void SRXAFSCB_TellMeAboutYourself(struct work_struct *); 31 32static int afs_deliver_yfs_cb_callback(struct afs_call *); 33 34/* 35 * CB.CallBack operation type 36 */ 37static const struct afs_call_type afs_SRXCBCallBack = { 38 .name = "CB.CallBack", 39 .deliver = afs_deliver_cb_callback, 40 .destructor = afs_cm_destructor, 41 .work = SRXAFSCB_CallBack, 42}; 43 44/* 45 * CB.InitCallBackState operation type 46 */ 47static const struct afs_call_type afs_SRXCBInitCallBackState = { 48 .name = "CB.InitCallBackState", 49 .deliver = afs_deliver_cb_init_call_back_state, 50 .destructor = afs_cm_destructor, 51 .work = SRXAFSCB_InitCallBackState, 52}; 53 54/* 55 * CB.InitCallBackState3 operation type 56 */ 57static const struct afs_call_type afs_SRXCBInitCallBackState3 = { 58 .name = "CB.InitCallBackState3", 59 .deliver = afs_deliver_cb_init_call_back_state3, 60 .destructor = afs_cm_destructor, 61 .work = SRXAFSCB_InitCallBackState, 62}; 63 64/* 65 * CB.Probe operation type 66 */ 67static const struct afs_call_type afs_SRXCBProbe = { 68 .name = "CB.Probe", 69 .deliver = afs_deliver_cb_probe, 70 .destructor = afs_cm_destructor, 71 .work = SRXAFSCB_Probe, 72}; 73 74/* 75 * CB.ProbeUuid operation type 76 */ 77static const struct afs_call_type afs_SRXCBProbeUuid = { 78 .name = "CB.ProbeUuid", 79 .deliver = afs_deliver_cb_probe_uuid, 80 .destructor = afs_cm_destructor, 81 .work = SRXAFSCB_ProbeUuid, 82}; 83 84/* 85 * CB.TellMeAboutYourself operation type 86 */ 87static const struct afs_call_type afs_SRXCBTellMeAboutYourself = { 88 .name = "CB.TellMeAboutYourself", 89 .deliver = afs_deliver_cb_tell_me_about_yourself, 90 .destructor = afs_cm_destructor, 91 .work = SRXAFSCB_TellMeAboutYourself, 92}; 93 94/* 95 * YFS CB.CallBack operation type 96 */ 97static const struct afs_call_type afs_SRXYFSCB_CallBack = { 98 .name = "YFSCB.CallBack", 99 .deliver = afs_deliver_yfs_cb_callback, 100 .destructor = afs_cm_destructor, 101 .work = SRXAFSCB_CallBack, 102}; 103 104/* 105 * route an incoming cache manager call 106 * - return T if supported, F if not 107 */ 108bool afs_cm_incoming_call(struct afs_call *call) 109{ 110 _enter("{%u, CB.OP %u}", call->service_id, call->operation_ID); 111 112 switch (call->operation_ID) { 113 case CBCallBack: 114 call->type = &afs_SRXCBCallBack; 115 return true; 116 case CBInitCallBackState: 117 call->type = &afs_SRXCBInitCallBackState; 118 return true; 119 case CBInitCallBackState3: 120 call->type = &afs_SRXCBInitCallBackState3; 121 return true; 122 case CBProbe: 123 call->type = &afs_SRXCBProbe; 124 return true; 125 case CBProbeUuid: 126 call->type = &afs_SRXCBProbeUuid; 127 return true; 128 case CBTellMeAboutYourself: 129 call->type = &afs_SRXCBTellMeAboutYourself; 130 return true; 131 case YFSCBCallBack: 132 if (call->service_id != YFS_CM_SERVICE) 133 return false; 134 call->type = &afs_SRXYFSCB_CallBack; 135 return true; 136 default: 137 return false; 138 } 139} 140 141/* 142 * Clean up a cache manager call. 143 */ 144static void afs_cm_destructor(struct afs_call *call) 145{ 146 kfree(call->buffer); 147 call->buffer = NULL; 148} 149 150/* 151 * Abort a service call from within an action function. 152 */ 153static void afs_abort_service_call(struct afs_call *call, u32 abort_code, int error, 154 enum rxrpc_abort_reason why) 155{ 156 rxrpc_kernel_abort_call(call->net->socket, call->rxcall, 157 abort_code, error, why); 158 afs_set_call_complete(call, error, 0); 159} 160 161/* 162 * The server supplied a list of callbacks that it wanted to break. 163 */ 164static void SRXAFSCB_CallBack(struct work_struct *work) 165{ 166 struct afs_call *call = container_of(work, struct afs_call, work); 167 168 _enter(""); 169 170 /* We need to break the callbacks before sending the reply as the 171 * server holds up change visibility till it receives our reply so as 172 * to maintain cache coherency. 173 */ 174 if (call->server) { 175 trace_afs_server(call->server->debug_id, 176 refcount_read(&call->server->ref), 177 atomic_read(&call->server->active), 178 afs_server_trace_callback); 179 afs_break_callbacks(call->server, call->count, call->request); 180 } 181 182 afs_send_empty_reply(call); 183 afs_put_call(call); 184 _leave(""); 185} 186 187/* 188 * deliver request data to a CB.CallBack call 189 */ 190static int afs_deliver_cb_callback(struct afs_call *call) 191{ 192 struct afs_callback_break *cb; 193 __be32 *bp; 194 int ret, loop; 195 196 _enter("{%u}", call->unmarshall); 197 198 switch (call->unmarshall) { 199 case 0: 200 afs_extract_to_tmp(call); 201 call->unmarshall++; 202 203 /* extract the FID array and its count in two steps */ 204 fallthrough; 205 case 1: 206 _debug("extract FID count"); 207 ret = afs_extract_data(call, true); 208 if (ret < 0) 209 return ret; 210 211 call->count = ntohl(call->tmp); 212 _debug("FID count: %u", call->count); 213 if (call->count > AFSCBMAX) 214 return afs_protocol_error(call, afs_eproto_cb_fid_count); 215 216 call->buffer = kmalloc(array3_size(call->count, 3, 4), 217 GFP_KERNEL); 218 if (!call->buffer) 219 return -ENOMEM; 220 afs_extract_to_buf(call, call->count * 3 * 4); 221 call->unmarshall++; 222 223 fallthrough; 224 case 2: 225 _debug("extract FID array"); 226 ret = afs_extract_data(call, true); 227 if (ret < 0) 228 return ret; 229 230 _debug("unmarshall FID array"); 231 call->request = kcalloc(call->count, 232 sizeof(struct afs_callback_break), 233 GFP_KERNEL); 234 if (!call->request) 235 return -ENOMEM; 236 237 cb = call->request; 238 bp = call->buffer; 239 for (loop = call->count; loop > 0; loop--, cb++) { 240 cb->fid.vid = ntohl(*bp++); 241 cb->fid.vnode = ntohl(*bp++); 242 cb->fid.unique = ntohl(*bp++); 243 } 244 245 afs_extract_to_tmp(call); 246 call->unmarshall++; 247 248 /* extract the callback array and its count in two steps */ 249 fallthrough; 250 case 3: 251 _debug("extract CB count"); 252 ret = afs_extract_data(call, true); 253 if (ret < 0) 254 return ret; 255 256 call->count2 = ntohl(call->tmp); 257 _debug("CB count: %u", call->count2); 258 if (call->count2 != call->count && call->count2 != 0) 259 return afs_protocol_error(call, afs_eproto_cb_count); 260 call->iter = &call->def_iter; 261 iov_iter_discard(&call->def_iter, ITER_DEST, call->count2 * 3 * 4); 262 call->unmarshall++; 263 264 fallthrough; 265 case 4: 266 _debug("extract discard %zu/%u", 267 iov_iter_count(call->iter), call->count2 * 3 * 4); 268 269 ret = afs_extract_data(call, false); 270 if (ret < 0) 271 return ret; 272 273 call->unmarshall++; 274 fallthrough; 275 276 case 5: 277 break; 278 } 279 280 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) 281 return afs_io_error(call, afs_io_error_cm_reply); 282 return 0; 283} 284 285/* 286 * allow the fileserver to request callback state (re-)initialisation 287 */ 288static void SRXAFSCB_InitCallBackState(struct work_struct *work) 289{ 290 struct afs_call *call = container_of(work, struct afs_call, work); 291 292 _enter("{%p}", call->server); 293 294 if (call->server) 295 afs_init_callback_state(call->server); 296 afs_send_empty_reply(call); 297 afs_put_call(call); 298 _leave(""); 299} 300 301/* 302 * deliver request data to a CB.InitCallBackState call 303 */ 304static int afs_deliver_cb_init_call_back_state(struct afs_call *call) 305{ 306 _enter(""); 307 308 afs_extract_discard(call, 0); 309 return afs_extract_data(call, false); 310} 311 312/* 313 * deliver request data to a CB.InitCallBackState3 call 314 */ 315static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) 316{ 317 struct afs_uuid *r; 318 unsigned loop; 319 __be32 *b; 320 int ret; 321 322 _enter("{%u}", call->unmarshall); 323 324 switch (call->unmarshall) { 325 case 0: 326 call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL); 327 if (!call->buffer) 328 return -ENOMEM; 329 afs_extract_to_buf(call, 11 * sizeof(__be32)); 330 call->unmarshall++; 331 332 fallthrough; 333 case 1: 334 _debug("extract UUID"); 335 ret = afs_extract_data(call, false); 336 switch (ret) { 337 case 0: break; 338 case -EAGAIN: return 0; 339 default: return ret; 340 } 341 342 _debug("unmarshall UUID"); 343 call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL); 344 if (!call->request) 345 return -ENOMEM; 346 347 b = call->buffer; 348 r = call->request; 349 r->time_low = b[0]; 350 r->time_mid = htons(ntohl(b[1])); 351 r->time_hi_and_version = htons(ntohl(b[2])); 352 r->clock_seq_hi_and_reserved = ntohl(b[3]); 353 r->clock_seq_low = ntohl(b[4]); 354 355 for (loop = 0; loop < 6; loop++) 356 r->node[loop] = ntohl(b[loop + 5]); 357 358 call->unmarshall++; 359 fallthrough; 360 361 case 2: 362 break; 363 } 364 365 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) 366 return afs_io_error(call, afs_io_error_cm_reply); 367 368 if (memcmp(call->request, &call->server->_uuid, sizeof(call->server->_uuid)) != 0) { 369 pr_notice("Callback UUID does not match fileserver UUID\n"); 370 trace_afs_cm_no_server_u(call, call->request); 371 return 0; 372 } 373 374 return 0; 375} 376 377/* 378 * allow the fileserver to see if the cache manager is still alive 379 */ 380static void SRXAFSCB_Probe(struct work_struct *work) 381{ 382 struct afs_call *call = container_of(work, struct afs_call, work); 383 384 _enter(""); 385 afs_send_empty_reply(call); 386 afs_put_call(call); 387 _leave(""); 388} 389 390/* 391 * deliver request data to a CB.Probe call 392 */ 393static int afs_deliver_cb_probe(struct afs_call *call) 394{ 395 int ret; 396 397 _enter(""); 398 399 afs_extract_discard(call, 0); 400 ret = afs_extract_data(call, false); 401 if (ret < 0) 402 return ret; 403 404 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) 405 return afs_io_error(call, afs_io_error_cm_reply); 406 return 0; 407} 408 409/* 410 * Allow the fileserver to quickly find out if the cache manager has been 411 * rebooted. 412 */ 413static void SRXAFSCB_ProbeUuid(struct work_struct *work) 414{ 415 struct afs_call *call = container_of(work, struct afs_call, work); 416 struct afs_uuid *r = call->request; 417 418 _enter(""); 419 420 if (memcmp(r, &call->net->uuid, sizeof(call->net->uuid)) == 0) 421 afs_send_empty_reply(call); 422 else 423 afs_abort_service_call(call, 1, 1, afs_abort_probeuuid_negative); 424 425 afs_put_call(call); 426 _leave(""); 427} 428 429/* 430 * deliver request data to a CB.ProbeUuid call 431 */ 432static int afs_deliver_cb_probe_uuid(struct afs_call *call) 433{ 434 struct afs_uuid *r; 435 unsigned loop; 436 __be32 *b; 437 int ret; 438 439 _enter("{%u}", call->unmarshall); 440 441 switch (call->unmarshall) { 442 case 0: 443 call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL); 444 if (!call->buffer) 445 return -ENOMEM; 446 afs_extract_to_buf(call, 11 * sizeof(__be32)); 447 call->unmarshall++; 448 449 fallthrough; 450 case 1: 451 _debug("extract UUID"); 452 ret = afs_extract_data(call, false); 453 switch (ret) { 454 case 0: break; 455 case -EAGAIN: return 0; 456 default: return ret; 457 } 458 459 _debug("unmarshall UUID"); 460 call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL); 461 if (!call->request) 462 return -ENOMEM; 463 464 b = call->buffer; 465 r = call->request; 466 r->time_low = b[0]; 467 r->time_mid = htons(ntohl(b[1])); 468 r->time_hi_and_version = htons(ntohl(b[2])); 469 r->clock_seq_hi_and_reserved = ntohl(b[3]); 470 r->clock_seq_low = ntohl(b[4]); 471 472 for (loop = 0; loop < 6; loop++) 473 r->node[loop] = ntohl(b[loop + 5]); 474 475 call->unmarshall++; 476 fallthrough; 477 478 case 2: 479 break; 480 } 481 482 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) 483 return afs_io_error(call, afs_io_error_cm_reply); 484 return 0; 485} 486 487/* 488 * allow the fileserver to ask about the cache manager's capabilities 489 */ 490static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work) 491{ 492 struct afs_call *call = container_of(work, struct afs_call, work); 493 int loop; 494 495 struct { 496 struct /* InterfaceAddr */ { 497 __be32 nifs; 498 __be32 uuid[11]; 499 __be32 ifaddr[32]; 500 __be32 netmask[32]; 501 __be32 mtu[32]; 502 } ia; 503 struct /* Capabilities */ { 504 __be32 capcount; 505 __be32 caps[1]; 506 } cap; 507 } reply; 508 509 _enter(""); 510 511 memset(&reply, 0, sizeof(reply)); 512 513 reply.ia.uuid[0] = call->net->uuid.time_low; 514 reply.ia.uuid[1] = htonl(ntohs(call->net->uuid.time_mid)); 515 reply.ia.uuid[2] = htonl(ntohs(call->net->uuid.time_hi_and_version)); 516 reply.ia.uuid[3] = htonl((s8) call->net->uuid.clock_seq_hi_and_reserved); 517 reply.ia.uuid[4] = htonl((s8) call->net->uuid.clock_seq_low); 518 for (loop = 0; loop < 6; loop++) 519 reply.ia.uuid[loop + 5] = htonl((s8) call->net->uuid.node[loop]); 520 521 reply.cap.capcount = htonl(1); 522 reply.cap.caps[0] = htonl(AFS_CAP_ERROR_TRANSLATION); 523 afs_send_simple_reply(call, &reply, sizeof(reply)); 524 afs_put_call(call); 525 _leave(""); 526} 527 528/* 529 * deliver request data to a CB.TellMeAboutYourself call 530 */ 531static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call) 532{ 533 int ret; 534 535 _enter(""); 536 537 afs_extract_discard(call, 0); 538 ret = afs_extract_data(call, false); 539 if (ret < 0) 540 return ret; 541 542 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) 543 return afs_io_error(call, afs_io_error_cm_reply); 544 return 0; 545} 546 547/* 548 * deliver request data to a YFS CB.CallBack call 549 */ 550static int afs_deliver_yfs_cb_callback(struct afs_call *call) 551{ 552 struct afs_callback_break *cb; 553 struct yfs_xdr_YFSFid *bp; 554 size_t size; 555 int ret, loop; 556 557 _enter("{%u}", call->unmarshall); 558 559 switch (call->unmarshall) { 560 case 0: 561 afs_extract_to_tmp(call); 562 call->unmarshall++; 563 564 /* extract the FID array and its count in two steps */ 565 fallthrough; 566 case 1: 567 _debug("extract FID count"); 568 ret = afs_extract_data(call, true); 569 if (ret < 0) 570 return ret; 571 572 call->count = ntohl(call->tmp); 573 _debug("FID count: %u", call->count); 574 if (call->count > YFSCBMAX) 575 return afs_protocol_error(call, afs_eproto_cb_fid_count); 576 577 size = array_size(call->count, sizeof(struct yfs_xdr_YFSFid)); 578 call->buffer = kmalloc(size, GFP_KERNEL); 579 if (!call->buffer) 580 return -ENOMEM; 581 afs_extract_to_buf(call, size); 582 call->unmarshall++; 583 584 fallthrough; 585 case 2: 586 _debug("extract FID array"); 587 ret = afs_extract_data(call, false); 588 if (ret < 0) 589 return ret; 590 591 _debug("unmarshall FID array"); 592 call->request = kcalloc(call->count, 593 sizeof(struct afs_callback_break), 594 GFP_KERNEL); 595 if (!call->request) 596 return -ENOMEM; 597 598 cb = call->request; 599 bp = call->buffer; 600 for (loop = call->count; loop > 0; loop--, cb++) { 601 cb->fid.vid = xdr_to_u64(bp->volume); 602 cb->fid.vnode = xdr_to_u64(bp->vnode.lo); 603 cb->fid.vnode_hi = ntohl(bp->vnode.hi); 604 cb->fid.unique = ntohl(bp->vnode.unique); 605 bp++; 606 } 607 608 afs_extract_to_tmp(call); 609 call->unmarshall++; 610 fallthrough; 611 612 case 3: 613 break; 614 } 615 616 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING)) 617 return afs_io_error(call, afs_io_error_cm_reply); 618 return 0; 619}