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(array3_size(call->count, 3, 4),
 195                                       GFP_KERNEL);
 196                if (!call->buffer)
 197                        return -ENOMEM;
 198                call->offset = 0;
 199                call->unmarshall++;
 200
 201        case 2:
 202                _debug("extract FID array");
 203                ret = afs_extract_data(call, call->buffer,
 204                                       call->count * 3 * 4, true);
 205                if (ret < 0)
 206                        return ret;
 207
 208                _debug("unmarshall FID array");
 209                call->request = kcalloc(call->count,
 210                                        sizeof(struct afs_callback_break),
 211                                        GFP_KERNEL);
 212                if (!call->request)
 213                        return -ENOMEM;
 214
 215                cb = call->request;
 216                bp = call->buffer;
 217                for (loop = call->count; loop > 0; loop--, cb++) {
 218                        cb->fid.vid     = ntohl(*bp++);
 219                        cb->fid.vnode   = ntohl(*bp++);
 220                        cb->fid.unique  = ntohl(*bp++);
 221                        cb->cb.type     = AFSCM_CB_UNTYPED;
 222                }
 223
 224                call->offset = 0;
 225                call->unmarshall++;
 226
 227                /* extract the callback array and its count in two steps */
 228        case 3:
 229                _debug("extract CB count");
 230                ret = afs_extract_data(call, &call->tmp, 4, true);
 231                if (ret < 0)
 232                        return ret;
 233
 234                call->count2 = ntohl(call->tmp);
 235                _debug("CB count: %u", call->count2);
 236                if (call->count2 != call->count && call->count2 != 0)
 237                        return afs_protocol_error(call, -EBADMSG);
 238                call->offset = 0;
 239                call->unmarshall++;
 240
 241        case 4:
 242                _debug("extract CB array");
 243                ret = afs_extract_data(call, call->buffer,
 244                                       call->count2 * 3 * 4, false);
 245                if (ret < 0)
 246                        return ret;
 247
 248                _debug("unmarshall CB array");
 249                cb = call->request;
 250                bp = call->buffer;
 251                for (loop = call->count2; loop > 0; loop--, cb++) {
 252                        cb->cb.version  = ntohl(*bp++);
 253                        cb->cb.expiry   = ntohl(*bp++);
 254                        cb->cb.type     = ntohl(*bp++);
 255                }
 256
 257                call->offset = 0;
 258                call->unmarshall++;
 259        case 5:
 260                break;
 261        }
 262
 263        if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
 264                return -EIO;
 265
 266        /* we'll need the file server record as that tells us which set of
 267         * vnodes to operate upon */
 268        rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
 269        call->cm_server = afs_find_server(call->net, &srx);
 270        if (!call->cm_server)
 271                trace_afs_cm_no_server(call, &srx);
 272
 273        return afs_queue_call_work(call);
 274}
 275
 276/*
 277 * allow the fileserver to request callback state (re-)initialisation
 278 */
 279static void SRXAFSCB_InitCallBackState(struct work_struct *work)
 280{
 281        struct afs_call *call = container_of(work, struct afs_call, work);
 282
 283        _enter("{%p}", call->cm_server);
 284
 285        if (call->cm_server)
 286                afs_init_callback_state(call->cm_server);
 287        afs_send_empty_reply(call);
 288        afs_put_call(call);
 289        _leave("");
 290}
 291
 292/*
 293 * deliver request data to a CB.InitCallBackState call
 294 */
 295static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
 296{
 297        struct sockaddr_rxrpc srx;
 298        int ret;
 299
 300        _enter("");
 301
 302        rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
 303
 304        ret = afs_extract_data(call, NULL, 0, false);
 305        if (ret < 0)
 306                return ret;
 307
 308        /* we'll need the file server record as that tells us which set of
 309         * vnodes to operate upon */
 310        call->cm_server = afs_find_server(call->net, &srx);
 311        if (!call->cm_server)
 312                trace_afs_cm_no_server(call, &srx);
 313
 314        return afs_queue_call_work(call);
 315}
 316
 317/*
 318 * deliver request data to a CB.InitCallBackState3 call
 319 */
 320static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
 321{
 322        struct afs_uuid *r;
 323        unsigned loop;
 324        __be32 *b;
 325        int ret;
 326
 327        _enter("");
 328
 329        _enter("{%u}", call->unmarshall);
 330
 331        switch (call->unmarshall) {
 332        case 0:
 333                call->offset = 0;
 334                call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
 335                if (!call->buffer)
 336                        return -ENOMEM;
 337                call->unmarshall++;
 338
 339        case 1:
 340                _debug("extract UUID");
 341                ret = afs_extract_data(call, call->buffer,
 342                                       11 * sizeof(__be32), false);
 343                switch (ret) {
 344                case 0:         break;
 345                case -EAGAIN:   return 0;
 346                default:        return ret;
 347                }
 348
 349                _debug("unmarshall UUID");
 350                call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
 351                if (!call->request)
 352                        return -ENOMEM;
 353
 354                b = call->buffer;
 355                r = call->request;
 356                r->time_low                     = b[0];
 357                r->time_mid                     = htons(ntohl(b[1]));
 358                r->time_hi_and_version          = htons(ntohl(b[2]));
 359                r->clock_seq_hi_and_reserved    = ntohl(b[3]);
 360                r->clock_seq_low                = ntohl(b[4]);
 361
 362                for (loop = 0; loop < 6; loop++)
 363                        r->node[loop] = ntohl(b[loop + 5]);
 364
 365                call->offset = 0;
 366                call->unmarshall++;
 367
 368        case 2:
 369                break;
 370        }
 371
 372        if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
 373                return -EIO;
 374
 375        /* we'll need the file server record as that tells us which set of
 376         * vnodes to operate upon */
 377        rcu_read_lock();
 378        call->cm_server = afs_find_server_by_uuid(call->net, call->request);
 379        rcu_read_unlock();
 380        if (!call->cm_server)
 381                trace_afs_cm_no_server_u(call, call->request);
 382
 383        return afs_queue_call_work(call);
 384}
 385
 386/*
 387 * allow the fileserver to see if the cache manager is still alive
 388 */
 389static void SRXAFSCB_Probe(struct work_struct *work)
 390{
 391        struct afs_call *call = container_of(work, struct afs_call, work);
 392
 393        _enter("");
 394        afs_send_empty_reply(call);
 395        afs_put_call(call);
 396        _leave("");
 397}
 398
 399/*
 400 * deliver request data to a CB.Probe call
 401 */
 402static int afs_deliver_cb_probe(struct afs_call *call)
 403{
 404        int ret;
 405
 406        _enter("");
 407
 408        ret = afs_extract_data(call, NULL, 0, false);
 409        if (ret < 0)
 410                return ret;
 411
 412        if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
 413                return -EIO;
 414
 415        return afs_queue_call_work(call);
 416}
 417
 418/*
 419 * allow the fileserver to quickly find out if the fileserver has been rebooted
 420 */
 421static void SRXAFSCB_ProbeUuid(struct work_struct *work)
 422{
 423        struct afs_call *call = container_of(work, struct afs_call, work);
 424        struct afs_uuid *r = call->request;
 425
 426        struct {
 427                __be32  match;
 428        } reply;
 429
 430        _enter("");
 431
 432        if (memcmp(r, &call->net->uuid, sizeof(call->net->uuid)) == 0)
 433                reply.match = htonl(0);
 434        else
 435                reply.match = htonl(1);
 436
 437        afs_send_simple_reply(call, &reply, sizeof(reply));
 438        afs_put_call(call);
 439        _leave("");
 440}
 441
 442/*
 443 * deliver request data to a CB.ProbeUuid call
 444 */
 445static int afs_deliver_cb_probe_uuid(struct afs_call *call)
 446{
 447        struct afs_uuid *r;
 448        unsigned loop;
 449        __be32 *b;
 450        int ret;
 451
 452        _enter("{%u}", call->unmarshall);
 453
 454        switch (call->unmarshall) {
 455        case 0:
 456                call->offset = 0;
 457                call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
 458                if (!call->buffer)
 459                        return -ENOMEM;
 460                call->unmarshall++;
 461
 462        case 1:
 463                _debug("extract UUID");
 464                ret = afs_extract_data(call, call->buffer,
 465                                       11 * sizeof(__be32), false);
 466                switch (ret) {
 467                case 0:         break;
 468                case -EAGAIN:   return 0;
 469                default:        return ret;
 470                }
 471
 472                _debug("unmarshall UUID");
 473                call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
 474                if (!call->request)
 475                        return -ENOMEM;
 476
 477                b = call->buffer;
 478                r = call->request;
 479                r->time_low                     = b[0];
 480                r->time_mid                     = htons(ntohl(b[1]));
 481                r->time_hi_and_version          = htons(ntohl(b[2]));
 482                r->clock_seq_hi_and_reserved    = ntohl(b[3]);
 483                r->clock_seq_low                = ntohl(b[4]);
 484
 485                for (loop = 0; loop < 6; loop++)
 486                        r->node[loop] = ntohl(b[loop + 5]);
 487
 488                call->offset = 0;
 489                call->unmarshall++;
 490
 491        case 2:
 492                break;
 493        }
 494
 495        if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
 496                return -EIO;
 497
 498        return afs_queue_call_work(call);
 499}
 500
 501/*
 502 * allow the fileserver to ask about the cache manager's capabilities
 503 */
 504static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
 505{
 506        struct afs_call *call = container_of(work, struct afs_call, work);
 507        int loop;
 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        memset(&reply, 0, sizeof(reply));
 526
 527        reply.ia.uuid[0] = call->net->uuid.time_low;
 528        reply.ia.uuid[1] = htonl(ntohs(call->net->uuid.time_mid));
 529        reply.ia.uuid[2] = htonl(ntohs(call->net->uuid.time_hi_and_version));
 530        reply.ia.uuid[3] = htonl((s8) call->net->uuid.clock_seq_hi_and_reserved);
 531        reply.ia.uuid[4] = htonl((s8) call->net->uuid.clock_seq_low);
 532        for (loop = 0; loop < 6; loop++)
 533                reply.ia.uuid[loop + 5] = htonl((s8) call->net->uuid.node[loop]);
 534
 535        reply.cap.capcount = htonl(1);
 536        reply.cap.caps[0] = htonl(AFS_CAP_ERROR_TRANSLATION);
 537        afs_send_simple_reply(call, &reply, sizeof(reply));
 538        afs_put_call(call);
 539        _leave("");
 540}
 541
 542/*
 543 * deliver request data to a CB.TellMeAboutYourself call
 544 */
 545static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
 546{
 547        int ret;
 548
 549        _enter("");
 550
 551        ret = afs_extract_data(call, NULL, 0, false);
 552        if (ret < 0)
 553                return ret;
 554
 555        if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
 556                return -EIO;
 557
 558        return afs_queue_call_work(call);
 559}
 560