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