[funini.com] -> [kei@sodan] -> Kernel Reading

root/fs/afs/vlclient.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. afs_vl_abort_to_error
  2. afs_deliver_vl_get_entry_by_xxx
  3. afs_vl_get_entry_by_name
  4. afs_vl_get_entry_by_id

/* AFS Volume Location Service client
 *
 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#include <linux/init.h>
#include <linux/sched.h>
#include "internal.h"

/*
 * map volume locator abort codes to error codes
 */
static int afs_vl_abort_to_error(u32 abort_code)
{
        _enter("%u", abort_code);

        switch (abort_code) {
        case AFSVL_IDEXIST:             return -EEXIST;
        case AFSVL_IO:                  return -EREMOTEIO;
        case AFSVL_NAMEEXIST:           return -EEXIST;
        case AFSVL_CREATEFAIL:          return -EREMOTEIO;
        case AFSVL_NOENT:               return -ENOMEDIUM;
        case AFSVL_EMPTY:               return -ENOMEDIUM;
        case AFSVL_ENTDELETED:          return -ENOMEDIUM;
        case AFSVL_BADNAME:             return -EINVAL;
        case AFSVL_BADINDEX:            return -EINVAL;
        case AFSVL_BADVOLTYPE:          return -EINVAL;
        case AFSVL_BADSERVER:           return -EINVAL;
        case AFSVL_BADPARTITION:        return -EINVAL;
        case AFSVL_REPSFULL:            return -EFBIG;
        case AFSVL_NOREPSERVER:         return -ENOENT;
        case AFSVL_DUPREPSERVER:        return -EEXIST;
        case AFSVL_RWNOTFOUND:          return -ENOENT;
        case AFSVL_BADREFCOUNT:         return -EINVAL;
        case AFSVL_SIZEEXCEEDED:        return -EINVAL;
        case AFSVL_BADENTRY:            return -EINVAL;
        case AFSVL_BADVOLIDBUMP:        return -EINVAL;
        case AFSVL_IDALREADYHASHED:     return -EINVAL;
        case AFSVL_ENTRYLOCKED:         return -EBUSY;
        case AFSVL_BADVOLOPER:          return -EBADRQC;
        case AFSVL_BADRELLOCKTYPE:      return -EINVAL;
        case AFSVL_RERELEASE:           return -EREMOTEIO;
        case AFSVL_BADSERVERFLAG:       return -EINVAL;
        case AFSVL_PERM:                return -EACCES;
        case AFSVL_NOMEM:               return -EREMOTEIO;
        default:
                return afs_abort_to_error(abort_code);
        }
}

/*
 * deliver reply data to a VL.GetEntryByXXX call
 */
static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call,
                                           struct sk_buff *skb, bool last)
{
        struct afs_cache_vlocation *entry;
        __be32 *bp;
        u32 tmp;
        int loop;

        _enter(",,%u", last);

        afs_transfer_reply(call, skb);
        if (!last)
                return 0;

        if (call->reply_size != call->reply_max)
                return -EBADMSG;

        /* unmarshall the reply once we've received all of it */
        entry = call->reply;
        bp = call->buffer;

        for (loop = 0; loop < 64; loop++)
                entry->name[loop] = ntohl(*bp++);
        entry->name[loop] = 0;
        bp++; /* final NUL */

        bp++; /* type */
        entry->nservers = ntohl(*bp++);

        for (loop = 0; loop < 8; loop++)
                entry->servers[loop].s_addr = *bp++;

        bp += 8; /* partition IDs */

        for (loop = 0; loop < 8; loop++) {
                tmp = ntohl(*bp++);
                entry->srvtmask[loop] = 0;
                if (tmp & AFS_VLSF_RWVOL)
                        entry->srvtmask[loop] |= AFS_VOL_VTM_RW;
                if (tmp & AFS_VLSF_ROVOL)
                        entry->srvtmask[loop] |= AFS_VOL_VTM_RO;
                if (tmp & AFS_VLSF_BACKVOL)
                        entry->srvtmask[loop] |= AFS_VOL_VTM_BAK;
        }

        entry->vid[0] = ntohl(*bp++);
        entry->vid[1] = ntohl(*bp++);
        entry->vid[2] = ntohl(*bp++);

        bp++; /* clone ID */

        tmp = ntohl(*bp++); /* flags */
        entry->vidmask = 0;
        if (tmp & AFS_VLF_RWEXISTS)
                entry->vidmask |= AFS_VOL_VTM_RW;
        if (tmp & AFS_VLF_ROEXISTS)
                entry->vidmask |= AFS_VOL_VTM_RO;
        if (tmp & AFS_VLF_BACKEXISTS)
                entry->vidmask |= AFS_VOL_VTM_BAK;
        if (!entry->vidmask)
                return -EBADMSG;

        _leave(" = 0 [done]");
        return 0;
}

/*
 * VL.GetEntryByName operation type
 */
static const struct afs_call_type afs_RXVLGetEntryByName = {
        .name           = "VL.GetEntryByName",
        .deliver        = afs_deliver_vl_get_entry_by_xxx,
        .abort_to_error = afs_vl_abort_to_error,
        .destructor     = afs_flat_call_destructor,
};

/*
 * VL.GetEntryById operation type
 */
static const struct afs_call_type afs_RXVLGetEntryById = {
        .name           = "VL.GetEntryById",
        .deliver        = afs_deliver_vl_get_entry_by_xxx,
        .abort_to_error = afs_vl_abort_to_error,
        .destructor     = afs_flat_call_destructor,
};

/*
 * dispatch a get volume entry by name operation
 */
int afs_vl_get_entry_by_name(struct in_addr *addr,
                             struct key *key,
                             const char *volname,
                             struct afs_cache_vlocation *entry,
                             const struct afs_wait_mode *wait_mode)
{
        struct afs_call *call;
        size_t volnamesz, reqsz, padsz;
        __be32 *bp;

        _enter("");

        volnamesz = strlen(volname);
        padsz = (4 - (volnamesz & 3)) & 3;
        reqsz = 8 + volnamesz + padsz;

        call = afs_alloc_flat_call(&afs_RXVLGetEntryByName, reqsz, 384);
        if (!call)
                return -ENOMEM;

        call->key = key;
        call->reply = entry;
        call->service_id = VL_SERVICE;
        call->port = htons(AFS_VL_PORT);

        /* marshall the parameters */
        bp = call->request;
        *bp++ = htonl(VLGETENTRYBYNAME);
        *bp++ = htonl(volnamesz);
        memcpy(bp, volname, volnamesz);
        if (padsz > 0)
                memset((void *) bp + volnamesz, 0, padsz);

        /* initiate the call */
        return afs_make_call(addr, call, GFP_KERNEL, wait_mode);
}

/*
 * dispatch a get volume entry by ID operation
 */
int afs_vl_get_entry_by_id(struct in_addr *addr,
                           struct key *key,
                           afs_volid_t volid,
                           afs_voltype_t voltype,
                           struct afs_cache_vlocation *entry,
                           const struct afs_wait_mode *wait_mode)
{
        struct afs_call *call;
        __be32 *bp;

        _enter("");

        call = afs_alloc_flat_call(&afs_RXVLGetEntryById, 12, 384);
        if (!call)
                return -ENOMEM;

        call->key = key;
        call->reply = entry;
        call->service_id = VL_SERVICE;
        call->port = htons(AFS_VL_PORT);

        /* marshall the parameters */
        bp = call->request;
        *bp++ = htonl(VLGETENTRYBYID);
        *bp++ = htonl(volid);
        *bp   = htonl(voltype);

        /* initiate the call */
        return afs_make_call(addr, call, GFP_KERNEL, wait_mode);
}

/* [<][>][^][v][top][bottom][index][help] */

[funini.com] -> [kei@sodan] -> Kernel Reading