vlclient.c 5.6 KB
Newer Older
D
David Howells 已提交
1
/* AFS Volume Location Service client
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9 10 11
 *
 * 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.
 */

12
#include <linux/gfp.h>
L
Linus Torvalds 已提交
13 14
#include <linux/init.h>
#include <linux/sched.h>
15
#include "afs_fs.h"
L
Linus Torvalds 已提交
16 17 18
#include "internal.h"

/*
19
 * map volume locator abort codes to error codes
L
Linus Torvalds 已提交
20
 */
21
static int afs_vl_abort_to_error(u32 abort_code)
L
Linus Torvalds 已提交
22
{
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
	_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;
L
Linus Torvalds 已提交
54
	default:
55
		return afs_abort_to_error(abort_code);
L
Linus Torvalds 已提交
56
	}
D
David Howells 已提交
57
}
L
Linus Torvalds 已提交
58 59

/*
60
 * deliver reply data to a VL.GetEntryByXXX call
L
Linus Torvalds 已提交
61
 */
62
static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call)
L
Linus Torvalds 已提交
63
{
64 65 66
	struct afs_cache_vlocation *entry;
	__be32 *bp;
	u32 tmp;
67
	int loop, ret;
L
Linus Torvalds 已提交
68

69
	_enter("");
L
Linus Torvalds 已提交
70

71
	ret = afs_transfer_reply(call);
72 73
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
74

75 76 77
	/* unmarshall the reply once we've received all of it */
	entry = call->reply;
	bp = call->buffer;
L
Linus Torvalds 已提交
78 79 80

	for (loop = 0; loop < 64; loop++)
		entry->name[loop] = ntohl(*bp++);
81
	entry->name[loop] = 0;
L
Linus Torvalds 已提交
82 83 84 85 86
	bp++; /* final NUL */

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

87 88 89 90 91 92 93 94 95
	for (loop = 0; loop < 8; loop++) {
		entry->servers[loop].srx_family = AF_RXRPC;
		entry->servers[loop].srx_service = FS_SERVICE;
		entry->servers[loop].transport_type = SOCK_DGRAM;
		entry->servers[loop].transport_len = sizeof(entry->servers[loop].transport.sin);
		entry->servers[loop].transport.sin.sin_family = AF_INET;
		entry->servers[loop].transport.sin.sin_port = htons(AFS_FS_PORT);
		entry->servers[loop].transport.sin.sin_addr.s_addr = *bp++;
	}
L
Linus Torvalds 已提交
96 97 98 99 100

	bp += 8; /* partition IDs */

	for (loop = 0; loop < 8; loop++) {
		tmp = ntohl(*bp++);
101
		entry->srvtmask[loop] = 0;
L
Linus Torvalds 已提交
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
		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 */
117
	entry->vidmask = 0;
L
Linus Torvalds 已提交
118 119 120 121 122 123 124
	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)
125 126 127 128
		return -EBADMSG;

	_leave(" = 0 [done]");
	return 0;
D
David Howells 已提交
129
}
L
Linus Torvalds 已提交
130 131

/*
132
 * VL.GetEntryByName operation type
L
Linus Torvalds 已提交
133
 */
134
static const struct afs_call_type afs_RXVLGetEntryByName = {
D
David Howells 已提交
135
	.name		= "VL.GetEntryByName",
136 137 138 139
	.deliver	= afs_deliver_vl_get_entry_by_xxx,
	.abort_to_error	= afs_vl_abort_to_error,
	.destructor	= afs_flat_call_destructor,
};
L
Linus Torvalds 已提交
140

141 142 143 144
/*
 * VL.GetEntryById operation type
 */
static const struct afs_call_type afs_RXVLGetEntryById = {
D
David Howells 已提交
145
	.name		= "VL.GetEntryById",
146 147 148 149
	.deliver	= afs_deliver_vl_get_entry_by_xxx,
	.abort_to_error	= afs_vl_abort_to_error,
	.destructor	= afs_flat_call_destructor,
};
L
Linus Torvalds 已提交
150 151

/*
152
 * dispatch a get volume entry by name operation
L
Linus Torvalds 已提交
153
 */
154
int afs_vl_get_entry_by_name(struct afs_net *net,
155
			     struct sockaddr_rxrpc *addr,
D
David Howells 已提交
156
			     struct key *key,
157 158
			     const char *volname,
			     struct afs_cache_vlocation *entry,
D
David Howells 已提交
159
			     bool async)
L
Linus Torvalds 已提交
160
{
161 162 163
	struct afs_call *call;
	size_t volnamesz, reqsz, padsz;
	__be32 *bp;
L
Linus Torvalds 已提交
164

165
	_enter("");
L
Linus Torvalds 已提交
166

167 168 169
	volnamesz = strlen(volname);
	padsz = (4 - (volnamesz & 3)) & 3;
	reqsz = 8 + volnamesz + padsz;
L
Linus Torvalds 已提交
170

171
	call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByName, reqsz, 384);
172 173
	if (!call)
		return -ENOMEM;
L
Linus Torvalds 已提交
174

D
David Howells 已提交
175
	call->key = key;
176
	call->reply = entry;
L
Linus Torvalds 已提交
177 178

	/* marshall the parameters */
179 180 181 182 183 184 185 186
	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 */
D
David Howells 已提交
187
	return afs_make_call(addr, call, GFP_KERNEL, async);
D
David Howells 已提交
188
}
L
Linus Torvalds 已提交
189 190

/*
191
 * dispatch a get volume entry by ID operation
L
Linus Torvalds 已提交
192
 */
193
int afs_vl_get_entry_by_id(struct afs_net *net,
194
			   struct sockaddr_rxrpc *addr,
D
David Howells 已提交
195
			   struct key *key,
196 197 198
			   afs_volid_t volid,
			   afs_voltype_t voltype,
			   struct afs_cache_vlocation *entry,
D
David Howells 已提交
199
			   bool async)
L
Linus Torvalds 已提交
200
{
201
	struct afs_call *call;
L
Linus Torvalds 已提交
202 203
	__be32 *bp;

204
	_enter("");
L
Linus Torvalds 已提交
205

206
	call = afs_alloc_flat_call(net, &afs_RXVLGetEntryById, 12, 384);
207 208
	if (!call)
		return -ENOMEM;
L
Linus Torvalds 已提交
209

D
David Howells 已提交
210
	call->key = key;
211
	call->reply = entry;
L
Linus Torvalds 已提交
212

213 214 215 216 217
	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(VLGETENTRYBYID);
	*bp++ = htonl(volid);
	*bp   = htonl(voltype);
L
Linus Torvalds 已提交
218

219
	/* initiate the call */
D
David Howells 已提交
220
	return afs_make_call(addr, call, GFP_KERNEL, async);
D
David Howells 已提交
221
}