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