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