linux/fs/afs/vlclient.c
<<
>>
Prefs
   1/* AFS Volume Location Service client
   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/gfp.h>
  13#include <linux/init.h>
  14#include <linux/sched.h>
  15#include "internal.h"
  16
  17/*
  18 * map volume locator abort codes to error codes
  19 */
  20static int afs_vl_abort_to_error(u32 abort_code)
  21{
  22        _enter("%u", abort_code);
  23
  24        switch (abort_code) {
  25        case AFSVL_IDEXIST:             return -EEXIST;
  26        case AFSVL_IO:                  return -EREMOTEIO;
  27        case AFSVL_NAMEEXIST:           return -EEXIST;
  28        case AFSVL_CREATEFAIL:          return -EREMOTEIO;
  29        case AFSVL_NOENT:               return -ENOMEDIUM;
  30        case AFSVL_EMPTY:               return -ENOMEDIUM;
  31        case AFSVL_ENTDELETED:          return -ENOMEDIUM;
  32        case AFSVL_BADNAME:             return -EINVAL;
  33        case AFSVL_BADINDEX:            return -EINVAL;
  34        case AFSVL_BADVOLTYPE:          return -EINVAL;
  35        case AFSVL_BADSERVER:           return -EINVAL;
  36        case AFSVL_BADPARTITION:        return -EINVAL;
  37        case AFSVL_REPSFULL:            return -EFBIG;
  38        case AFSVL_NOREPSERVER:         return -ENOENT;
  39        case AFSVL_DUPREPSERVER:        return -EEXIST;
  40        case AFSVL_RWNOTFOUND:          return -ENOENT;
  41        case AFSVL_BADREFCOUNT:         return -EINVAL;
  42        case AFSVL_SIZEEXCEEDED:        return -EINVAL;
  43        case AFSVL_BADENTRY:            return -EINVAL;
  44        case AFSVL_BADVOLIDBUMP:        return -EINVAL;
  45        case AFSVL_IDALREADYHASHED:     return -EINVAL;
  46        case AFSVL_ENTRYLOCKED:         return -EBUSY;
  47        case AFSVL_BADVOLOPER:          return -EBADRQC;
  48        case AFSVL_BADRELLOCKTYPE:      return -EINVAL;
  49        case AFSVL_RERELEASE:           return -EREMOTEIO;
  50        case AFSVL_BADSERVERFLAG:       return -EINVAL;
  51        case AFSVL_PERM:                return -EACCES;
  52        case AFSVL_NOMEM:               return -EREMOTEIO;
  53        default:
  54                return afs_abort_to_error(abort_code);
  55        }
  56}
  57
  58/*
  59 * deliver reply data to a VL.GetEntryByXXX call
  60 */
  61static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call,
  62                                           struct sk_buff *skb, bool last)
  63{
  64        struct afs_cache_vlocation *entry;
  65        __be32 *bp;
  66        u32 tmp;
  67        int loop;
  68
  69        _enter(",,%u", last);
  70
  71        afs_transfer_reply(call, skb);
  72        if (!last)
  73                return 0;
  74
  75        if (call->reply_size != call->reply_max)
  76                return -EBADMSG;
  77
  78        /* unmarshall the reply once we've received all of it */
  79        entry = call->reply;
  80        bp = call->buffer;
  81
  82        for (loop = 0; loop < 64; loop++)
  83                entry->name[loop] = ntohl(*bp++);
  84        entry->name[loop] = 0;
  85        bp++; /* final NUL */
  86
  87        bp++; /* type */
  88        entry->nservers = ntohl(*bp++);
  89
  90        for (loop = 0; loop < 8; loop++)
  91                entry->servers[loop].s_addr = *bp++;
  92
  93        bp += 8; /* partition IDs */
  94
  95        for (loop = 0; loop < 8; loop++) {
  96                tmp = ntohl(*bp++);
  97                entry->srvtmask[loop] = 0;
  98                if (tmp & AFS_VLSF_RWVOL)
  99                        entry->srvtmask[loop] |= AFS_VOL_VTM_RW;
 100                if (tmp & AFS_VLSF_ROVOL)
 101                        entry->srvtmask[loop] |= AFS_VOL_VTM_RO;
 102                if (tmp & AFS_VLSF_BACKVOL)
 103                        entry->srvtmask[loop] |= AFS_VOL_VTM_BAK;
 104        }
 105
 106        entry->vid[0] = ntohl(*bp++);
 107        entry->vid[1] = ntohl(*bp++);
 108        entry->vid[2] = ntohl(*bp++);
 109
 110        bp++; /* clone ID */
 111
 112        tmp = ntohl(*bp++); /* flags */
 113        entry->vidmask = 0;
 114        if (tmp & AFS_VLF_RWEXISTS)
 115                entry->vidmask |= AFS_VOL_VTM_RW;
 116        if (tmp & AFS_VLF_ROEXISTS)
 117                entry->vidmask |= AFS_VOL_VTM_RO;
 118        if (tmp & AFS_VLF_BACKEXISTS)
 119                entry->vidmask |= AFS_VOL_VTM_BAK;
 120        if (!entry->vidmask)
 121                return -EBADMSG;
 122
 123        _leave(" = 0 [done]");
 124        return 0;
 125}
 126
 127/*
 128 * VL.GetEntryByName operation type
 129 */
 130static const struct afs_call_type afs_RXVLGetEntryByName = {
 131        .name           = "VL.GetEntryByName",
 132        .deliver        = afs_deliver_vl_get_entry_by_xxx,
 133        .abort_to_error = afs_vl_abort_to_error,
 134        .destructor     = afs_flat_call_destructor,
 135};
 136
 137/*
 138 * VL.GetEntryById operation type
 139 */
 140static const struct afs_call_type afs_RXVLGetEntryById = {
 141        .name           = "VL.GetEntryById",
 142        .deliver        = afs_deliver_vl_get_entry_by_xxx,
 143        .abort_to_error = afs_vl_abort_to_error,
 144        .destructor     = afs_flat_call_destructor,
 145};
 146
 147/*
 148 * dispatch a get volume entry by name operation
 149 */
 150int afs_vl_get_entry_by_name(struct in_addr *addr,
 151                             struct key *key,
 152                             const char *volname,
 153                             struct afs_cache_vlocation *entry,
 154                             const struct afs_wait_mode *wait_mode)
 155{
 156        struct afs_call *call;
 157        size_t volnamesz, reqsz, padsz;
 158        __be32 *bp;
 159
 160        _enter("");
 161
 162        volnamesz = strlen(volname);
 163        padsz = (4 - (volnamesz & 3)) & 3;
 164        reqsz = 8 + volnamesz + padsz;
 165
 166        call = afs_alloc_flat_call(&afs_RXVLGetEntryByName, reqsz, 384);
 167        if (!call)
 168                return -ENOMEM;
 169
 170        call->key = key;
 171        call->reply = entry;
 172        call->service_id = VL_SERVICE;
 173        call->port = htons(AFS_VL_PORT);
 174
 175        /* marshall the parameters */
 176        bp = call->request;
 177        *bp++ = htonl(VLGETENTRYBYNAME);
 178        *bp++ = htonl(volnamesz);
 179        memcpy(bp, volname, volnamesz);
 180        if (padsz > 0)
 181                memset((void *) bp + volnamesz, 0, padsz);
 182
 183        /* initiate the call */
 184        return afs_make_call(addr, call, GFP_KERNEL, wait_mode);
 185}
 186
 187/*
 188 * dispatch a get volume entry by ID operation
 189 */
 190int afs_vl_get_entry_by_id(struct in_addr *addr,
 191                           struct key *key,
 192                           afs_volid_t volid,
 193                           afs_voltype_t voltype,
 194                           struct afs_cache_vlocation *entry,
 195                           const struct afs_wait_mode *wait_mode)
 196{
 197        struct afs_call *call;
 198        __be32 *bp;
 199
 200        _enter("");
 201
 202        call = afs_alloc_flat_call(&afs_RXVLGetEntryById, 12, 384);
 203        if (!call)
 204                return -ENOMEM;
 205
 206        call->key = key;
 207        call->reply = entry;
 208        call->service_id = VL_SERVICE;
 209        call->port = htons(AFS_VL_PORT);
 210
 211        /* marshall the parameters */
 212        bp = call->request;
 213        *bp++ = htonl(VLGETENTRYBYID);
 214        *bp++ = htonl(volid);
 215        *bp   = htonl(voltype);
 216
 217        /* initiate the call */
 218        return afs_make_call(addr, call, GFP_KERNEL, wait_mode);
 219}
 220