1/* AFS Cache Manager Service 2 * 3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 4 * 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 */ 11 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/slab.h> 15#include <linux/sched.h> 16#include <linux/ip.h> 17#include "internal.h" 18#include "afs_cm.h" 19 20#if 0 21struct workqueue_struct *afs_cm_workqueue; 22#endif /* 0 */ 23 24static int afs_deliver_cb_init_call_back_state(struct afs_call *, 25 struct sk_buff *, bool); 26static int afs_deliver_cb_init_call_back_state3(struct afs_call *, 27 struct sk_buff *, bool); 28static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool); 29static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool); 30static int afs_deliver_cb_probe_uuid(struct afs_call *, struct sk_buff *, bool); 31static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *, 32 struct sk_buff *, bool); 33static void afs_cm_destructor(struct afs_call *); 34 35/* 36 * CB.CallBack operation type 37 */ 38static const struct afs_call_type afs_SRXCBCallBack = { 39 .name = "CB.CallBack", 40 .deliver = afs_deliver_cb_callback, 41 .abort_to_error = afs_abort_to_error, 42 .destructor = afs_cm_destructor, 43}; 44 45/* 46 * CB.InitCallBackState operation type 47 */ 48static const struct afs_call_type afs_SRXCBInitCallBackState = { 49 .name = "CB.InitCallBackState", 50 .deliver = afs_deliver_cb_init_call_back_state, 51 .abort_to_error = afs_abort_to_error, 52 .destructor = afs_cm_destructor, 53}; 54 55/* 56 * CB.InitCallBackState3 operation type 57 */ 58static const struct afs_call_type afs_SRXCBInitCallBackState3 = { 59 .name = "CB.InitCallBackState3", 60 .deliver = afs_deliver_cb_init_call_back_state3, 61 .abort_to_error = afs_abort_to_error, 62 .destructor = afs_cm_destructor, 63}; 64 65/* 66 * CB.Probe operation type 67 */ 68static const struct afs_call_type afs_SRXCBProbe = { 69 .name = "CB.Probe", 70 .deliver = afs_deliver_cb_probe, 71 .abort_to_error = afs_abort_to_error, 72 .destructor = afs_cm_destructor, 73}; 74 75/* 76 * CB.ProbeUuid operation type 77 */ 78static const struct afs_call_type afs_SRXCBProbeUuid = { 79 .name = "CB.ProbeUuid", 80 .deliver = afs_deliver_cb_probe_uuid, 81 .abort_to_error = afs_abort_to_error, 82 .destructor = afs_cm_destructor, 83}; 84 85/* 86 * CB.TellMeAboutYourself operation type 87 */ 88static const struct afs_call_type afs_SRXCBTellMeAboutYourself = { 89 .name = "CB.TellMeAboutYourself", 90 .deliver = afs_deliver_cb_tell_me_about_yourself, 91 .abort_to_error = afs_abort_to_error, 92 .destructor = afs_cm_destructor, 93}; 94 95/* 96 * route an incoming cache manager call 97 * - return T if supported, F if not 98 */ 99bool afs_cm_incoming_call(struct afs_call *call) 100{ 101 u32 operation_id = ntohl(call->operation_ID); 102 103 _enter("{CB.OP %u}", operation_id); 104 105 switch (operation_id) { 106 case CBCallBack: 107 call->type = &afs_SRXCBCallBack; 108 return true; 109 case CBInitCallBackState: 110 call->type = &afs_SRXCBInitCallBackState; 111 return true; 112 case CBInitCallBackState3: 113 call->type = &afs_SRXCBInitCallBackState3; 114 return true; 115 case CBProbe: 116 call->type = &afs_SRXCBProbe; 117 return true; 118 case CBTellMeAboutYourself: 119 call->type = &afs_SRXCBTellMeAboutYourself; 120 return true; 121 default: 122 return false; 123 } 124} 125 126/* 127 * clean up a cache manager call 128 */ 129static void afs_cm_destructor(struct afs_call *call) 130{ 131 _enter(""); 132 133 /* Break the callbacks here so that we do it after the final ACK is 134 * received. The step number here must match the final number in 135 * afs_deliver_cb_callback(). 136 */ 137 if (call->unmarshall == 6) { 138 ASSERT(call->server && call->count && call->request); 139 afs_break_callbacks(call->server, call->count, call->request); 140 } 141 142 afs_put_server(call->server); 143 call->server = NULL; 144 kfree(call->buffer); 145 call->buffer = NULL; 146} 147 148/* 149 * allow the fileserver to see if the cache manager is still alive 150 */ 151static void SRXAFSCB_CallBack(struct work_struct *work) 152{ 153 struct afs_call *call = container_of(work, struct afs_call, work); 154 155 _enter(""); 156 157 /* be sure to send the reply *before* attempting to spam the AFS server 158 * with FSFetchStatus requests on the vnodes with broken callbacks lest 159 * the AFS server get into a vicious cycle of trying to break further 160 * callbacks because it hadn't received completion of the CBCallBack op 161 * yet */ 162 afs_send_empty_reply(call); 163 164 afs_break_callbacks(call->server, call->count, call->request); 165 _leave(""); 166} 167 168/* 169 * deliver request data to a CB.CallBack call 170 */ 171static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb, 172 bool last) 173{ 174 struct afs_callback *cb; 175 struct afs_server *server; 176 struct in_addr addr; 177 __be32 *bp; 178 u32 tmp; 179 int ret, loop; 180 181 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 182 183 switch (call->unmarshall) { 184 case 0: 185 call->offset = 0; 186 call->unmarshall++; 187 188 /* extract the FID array and its count in two steps */ 189 case 1: 190 _debug("extract FID count"); 191 ret = afs_extract_data(call, skb, last, &call->tmp, 4); 192 switch (ret) { 193 case 0: break; 194 case -EAGAIN: return 0; 195 default: return ret; 196 } 197 198 call->count = ntohl(call->tmp); 199 _debug("FID count: %u", call->count); 200 if (call->count > AFSCBMAX) 201 return -EBADMSG; 202 203 call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL); 204 if (!call->buffer) 205 return -ENOMEM; 206 call->offset = 0; 207 call->unmarshall++; 208 209 case 2: 210 _debug("extract FID array"); 211 ret = afs_extract_data(call, skb, last, call->buffer, 212 call->count * 3 * 4); 213 switch (ret) { 214 case 0: break; 215 case -EAGAIN: return 0; 216 default: return ret; 217 } 218 219 _debug("unmarshall FID array"); 220 call->request = kcalloc(call->count, 221 sizeof(struct afs_callback), 222 GFP_KERNEL); 223 if (!call->request) 224 return -ENOMEM; 225 226 cb = call->request; 227 bp = call->buffer; 228 for (loop = call->count; loop > 0; loop--, cb++) { 229 cb->fid.vid = ntohl(*bp++); 230 cb->fid.vnode = ntohl(*bp++); 231 cb->fid.unique = ntohl(*bp++); 232 cb->type = AFSCM_CB_UNTYPED; 233 } 234 235 call->offset = 0; 236 call->unmarshall++; 237 238 /* extract the callback array and its count in two steps */ 239 case 3: 240 _debug("extract CB count"); 241 ret = afs_extract_data(call, skb, last, &call->tmp, 4); 242 switch (ret) { 243 case 0: break; 244 case -EAGAIN: return 0; 245 default: return ret; 246 } 247 248 tmp = ntohl(call->tmp); 249 _debug("CB count: %u", tmp); 250 if (tmp != call->count && tmp != 0) 251 return -EBADMSG; 252 call->offset = 0; 253 call->unmarshall++; 254 if (tmp == 0) 255 goto empty_cb_array; 256 257 case 4: 258 _debug("extract CB array"); 259 ret = afs_extract_data(call, skb, last, call->request, 260 call->count * 3 * 4); 261 switch (ret) { 262 case 0: break; 263 case -EAGAIN: return 0; 264 default: return ret; 265 } 266 267 _debug("unmarshall CB array"); 268 cb = call->request; 269 bp = call->buffer; 270 for (loop = call->count; loop > 0; loop--, cb++) { 271 cb->version = ntohl(*bp++); 272 cb->expiry = ntohl(*bp++); 273 cb->type = ntohl(*bp++); 274 } 275 276 empty_cb_array: 277 call->offset = 0; 278 call->unmarshall++; 279 280 case 5: 281 _debug("trailer"); 282 if (skb->len != 0) 283 return -EBADMSG; 284 285 /* Record that the message was unmarshalled successfully so 286 * that the call destructor can know do the callback breaking 287 * work, even if the final ACK isn't received. 288 * 289 * If the step number changes, then afs_cm_destructor() must be 290 * updated also. 291 */ 292 call->unmarshall++; 293 case 6: 294 break; 295 } 296 297 if (!last) 298 return 0; 299 300 call->state = AFS_CALL_REPLYING; 301 302 /* we'll need the file server record as that tells us which set of 303 * vnodes to operate upon */ 304 memcpy(&addr, &ip_hdr(skb)->saddr, 4); 305 server = afs_find_server(&addr); 306 if (!server) 307 return -ENOTCONN; 308 call->server = server; 309 310 INIT_WORK(&call->work, SRXAFSCB_CallBack); 311 queue_work(afs_wq, &call->work); 312 return 0; 313} 314 315/* 316 * allow the fileserver to request callback state (re-)initialisation 317 */ 318static void SRXAFSCB_InitCallBackState(struct work_struct *work) 319{ 320 struct afs_call *call = container_of(work, struct afs_call, work); 321 322 _enter("{%p}", call->server); 323 324 afs_init_callback_state(call->server); 325 afs_send_empty_reply(call); 326 _leave(""); 327} 328 329/* 330 * deliver request data to a CB.InitCallBackState call 331 */ 332static int afs_deliver_cb_init_call_back_state(struct afs_call *call, 333 struct sk_buff *skb, 334 bool last) 335{ 336 struct afs_server *server; 337 struct in_addr addr; 338 339 _enter(",{%u},%d", skb->len, last); 340 341 if (skb->len > 0) 342 return -EBADMSG; 343 if (!last) 344 return 0; 345 346 /* no unmarshalling required */ 347 call->state = AFS_CALL_REPLYING; 348 349 /* we'll need the file server record as that tells us which set of 350 * vnodes to operate upon */ 351 memcpy(&addr, &ip_hdr(skb)->saddr, 4); 352 server = afs_find_server(&addr); 353 if (!server) 354 return -ENOTCONN; 355 call->server = server; 356 357 INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); 358 queue_work(afs_wq, &call->work); 359 return 0; 360} 361 362/* 363 * deliver request data to a CB.InitCallBackState3 call 364 */ 365static int afs_deliver_cb_init_call_back_state3(struct afs_call *call, 366 struct sk_buff *skb, 367 bool last) 368{ 369 struct afs_server *server; 370 struct in_addr addr; 371 372 _enter(",{%u},%d", skb->len, last); 373 374 if (!last) 375 return 0; 376 377 /* no unmarshalling required */ 378 call->state = AFS_CALL_REPLYING; 379 380 /* we'll need the file server record as that tells us which set of 381 * vnodes to operate upon */ 382 memcpy(&addr, &ip_hdr(skb)->saddr, 4); 383 server = afs_find_server(&addr); 384 if (!server) 385 return -ENOTCONN; 386 call->server = server; 387 388 INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); 389 queue_work(afs_wq, &call->work); 390 return 0; 391} 392 393/* 394 * allow the fileserver to see if the cache manager is still alive 395 */ 396static void SRXAFSCB_Probe(struct work_struct *work) 397{ 398 struct afs_call *call = container_of(work, struct afs_call, work); 399 400 _enter(""); 401 afs_send_empty_reply(call); 402 _leave(""); 403} 404 405/* 406 * deliver request data to a CB.Probe call 407 */ 408static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb, 409 bool last) 410{ 411 _enter(",{%u},%d", skb->len, last); 412 413 if (skb->len > 0) 414 return -EBADMSG; 415 if (!last) 416 return 0; 417 418 /* no unmarshalling required */ 419 call->state = AFS_CALL_REPLYING; 420 421 INIT_WORK(&call->work, SRXAFSCB_Probe); 422 queue_work(afs_wq, &call->work); 423 return 0; 424} 425 426/* 427 * allow the fileserver to quickly find out if the fileserver has been rebooted 428 */ 429static void SRXAFSCB_ProbeUuid(struct work_struct *work) 430{ 431 struct afs_call *call = container_of(work, struct afs_call, work); 432 struct afs_uuid *r = call->request; 433 434 struct { 435 __be32 match; 436 } reply; 437 438 _enter(""); 439 440 441 if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0) 442 reply.match = htonl(0); 443 else 444 reply.match = htonl(1); 445 446 afs_send_simple_reply(call, &reply, sizeof(reply)); 447 _leave(""); 448} 449 450/* 451 * deliver request data to a CB.ProbeUuid call 452 */ 453static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb, 454 bool last) 455{ 456 struct afs_uuid *r; 457 unsigned loop; 458 __be32 *b; 459 int ret; 460 461 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 462 463 if (skb->len > 0) 464 return -EBADMSG; 465 if (!last) 466 return 0; 467 468 switch (call->unmarshall) { 469 case 0: 470 call->offset = 0; 471 call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL); 472 if (!call->buffer) 473 return -ENOMEM; 474 call->unmarshall++; 475 476 case 1: 477 _debug("extract UUID"); 478 ret = afs_extract_data(call, skb, last, call->buffer, 479 11 * sizeof(__be32)); 480 switch (ret) { 481 case 0: break; 482 case -EAGAIN: return 0; 483 default: return ret; 484 } 485 486 _debug("unmarshall UUID"); 487 call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL); 488 if (!call->request) 489 return -ENOMEM; 490 491 b = call->buffer; 492 r = call->request; 493 r->time_low = ntohl(b[0]); 494 r->time_mid = ntohl(b[1]); 495 r->time_hi_and_version = ntohl(b[2]); 496 r->clock_seq_hi_and_reserved = ntohl(b[3]); 497 r->clock_seq_low = ntohl(b[4]); 498 499 for (loop = 0; loop < 6; loop++) 500 r->node[loop] = ntohl(b[loop + 5]); 501 502 call->offset = 0; 503 call->unmarshall++; 504 505 case 2: 506 _debug("trailer"); 507 if (skb->len != 0) 508 return -EBADMSG; 509 break; 510 } 511 512 if (!last) 513 return 0; 514 515 call->state = AFS_CALL_REPLYING; 516 517 INIT_WORK(&call->work, SRXAFSCB_ProbeUuid); 518 queue_work(afs_wq, &call->work); 519 return 0; 520} 521 522/* 523 * allow the fileserver to ask about the cache manager's capabilities 524 */ 525static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work) 526{ 527 struct afs_interface *ifs; 528 struct afs_call *call = container_of(work, struct afs_call, work); 529 int loop, nifs; 530 531 struct { 532 struct /* InterfaceAddr */ { 533 __be32 nifs; 534 __be32 uuid[11]; 535 __be32 ifaddr[32]; 536 __be32 netmask[32]; 537 __be32 mtu[32]; 538 } ia; 539 struct /* Capabilities */ { 540 __be32 capcount; 541 __be32 caps[1]; 542 } cap; 543 } reply; 544 545 _enter(""); 546 547 nifs = 0; 548 ifs = kcalloc(32, sizeof(*ifs), GFP_KERNEL); 549 if (ifs) { 550 nifs = afs_get_ipv4_interfaces(ifs, 32, false); 551 if (nifs < 0) { 552 kfree(ifs); 553 ifs = NULL; 554 nifs = 0; 555 } 556 } 557 558 memset(&reply, 0, sizeof(reply)); 559 reply.ia.nifs = htonl(nifs); 560 561 reply.ia.uuid[0] = htonl(afs_uuid.time_low); 562 reply.ia.uuid[1] = htonl(afs_uuid.time_mid); 563 reply.ia.uuid[2] = htonl(afs_uuid.time_hi_and_version); 564 reply.ia.uuid[3] = htonl((s8) afs_uuid.clock_seq_hi_and_reserved); 565 reply.ia.uuid[4] = htonl((s8) afs_uuid.clock_seq_low); 566 for (loop = 0; loop < 6; loop++) 567 reply.ia.uuid[loop + 5] = htonl((s8) afs_uuid.node[loop]); 568 569 if (ifs) { 570 for (loop = 0; loop < nifs; loop++) { 571 reply.ia.ifaddr[loop] = ifs[loop].address.s_addr; 572 reply.ia.netmask[loop] = ifs[loop].netmask.s_addr; 573 reply.ia.mtu[loop] = htonl(ifs[loop].mtu); 574 } 575 kfree(ifs); 576 } 577 578 reply.cap.capcount = htonl(1); 579 reply.cap.caps[0] = htonl(AFS_CAP_ERROR_TRANSLATION); 580 afs_send_simple_reply(call, &reply, sizeof(reply)); 581 582 _leave(""); 583} 584 585/* 586 * deliver request data to a CB.TellMeAboutYourself call 587 */ 588static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call, 589 struct sk_buff *skb, bool last) 590{ 591 _enter(",{%u},%d", skb->len, last); 592 593 if (skb->len > 0) 594 return -EBADMSG; 595 if (!last) 596 return 0; 597 598 /* no unmarshalling required */ 599 call->state = AFS_CALL_REPLYING; 600 601 INIT_WORK(&call->work, SRXAFSCB_TellMeAboutYourself); 602 queue_work(afs_wq, &call->work); 603 return 0; 604} 605