| 
									
										
										
										
											2007-04-26 15:49:28 -07:00
										 |  |  | /* AFS Volume Location Service client
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  |  * map volume locator abort codes to error codes | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | static int afs_vl_abort_to_error(u32 abort_code) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	_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; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 		return afs_abort_to_error(abort_code); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-04-26 15:49:28 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  |  * deliver reply data to a VL.GetEntryByXXX call | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call, | 
					
						
							|  |  |  | 					   struct sk_buff *skb, bool last) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	struct afs_cache_vlocation *entry; | 
					
						
							|  |  |  | 	__be32 *bp; | 
					
						
							|  |  |  | 	u32 tmp; | 
					
						
							|  |  |  | 	int loop; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	_enter(",,%u", last); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	afs_transfer_reply(call, skb); | 
					
						
							|  |  |  | 	if (!last) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	if (call->reply_size != call->reply_max) | 
					
						
							|  |  |  | 		return -EBADMSG; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	/* unmarshall the reply once we've received all of it */ | 
					
						
							|  |  |  | 	entry = call->reply; | 
					
						
							|  |  |  | 	bp = call->buffer; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (loop = 0; loop < 64; loop++) | 
					
						
							|  |  |  | 		entry->name[loop] = ntohl(*bp++); | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	entry->name[loop] = 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	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++); | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 		entry->srvtmask[loop] = 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		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 */ | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	entry->vidmask = 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	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) | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 		return -EBADMSG; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_leave(" = 0 [done]"); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2007-04-26 15:49:28 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  |  * VL.GetEntryByName operation type | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | static const struct afs_call_type afs_RXVLGetEntryByName = { | 
					
						
							| 
									
										
										
										
											2007-04-26 15:57:07 -07:00
										 |  |  | 	.name		= "VL.GetEntryByName", | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	.deliver	= afs_deliver_vl_get_entry_by_xxx, | 
					
						
							|  |  |  | 	.abort_to_error	= afs_vl_abort_to_error, | 
					
						
							|  |  |  | 	.destructor	= afs_flat_call_destructor, | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * VL.GetEntryById operation type | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static const struct afs_call_type afs_RXVLGetEntryById = { | 
					
						
							| 
									
										
										
										
											2007-04-26 15:57:07 -07:00
										 |  |  | 	.name		= "VL.GetEntryById", | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	.deliver	= afs_deliver_vl_get_entry_by_xxx, | 
					
						
							|  |  |  | 	.abort_to_error	= afs_vl_abort_to_error, | 
					
						
							|  |  |  | 	.destructor	= afs_flat_call_destructor, | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  |  * dispatch a get volume entry by name operation | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | int afs_vl_get_entry_by_name(struct in_addr *addr, | 
					
						
							| 
									
										
										
										
											2007-04-26 15:57:07 -07:00
										 |  |  | 			     struct key *key, | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 			     const char *volname, | 
					
						
							|  |  |  | 			     struct afs_cache_vlocation *entry, | 
					
						
							|  |  |  | 			     const struct afs_wait_mode *wait_mode) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	struct afs_call *call; | 
					
						
							|  |  |  | 	size_t volnamesz, reqsz, padsz; | 
					
						
							|  |  |  | 	__be32 *bp; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	_enter(""); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	volnamesz = strlen(volname); | 
					
						
							|  |  |  | 	padsz = (4 - (volnamesz & 3)) & 3; | 
					
						
							|  |  |  | 	reqsz = 8 + volnamesz + padsz; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	call = afs_alloc_flat_call(&afs_RXVLGetEntryByName, reqsz, 384); | 
					
						
							|  |  |  | 	if (!call) | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:57:07 -07:00
										 |  |  | 	call->key = key; | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	call->reply = entry; | 
					
						
							|  |  |  | 	call->service_id = VL_SERVICE; | 
					
						
							|  |  |  | 	call->port = htons(AFS_VL_PORT); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* marshall the parameters */ | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2007-04-26 15:49:28 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  |  * dispatch a get volume entry by ID operation | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | int afs_vl_get_entry_by_id(struct in_addr *addr, | 
					
						
							| 
									
										
										
										
											2007-04-26 15:57:07 -07:00
										 |  |  | 			   struct key *key, | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 			   afs_volid_t volid, | 
					
						
							|  |  |  | 			   afs_voltype_t voltype, | 
					
						
							|  |  |  | 			   struct afs_cache_vlocation *entry, | 
					
						
							|  |  |  | 			   const struct afs_wait_mode *wait_mode) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	struct afs_call *call; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	__be32 *bp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	_enter(""); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	call = afs_alloc_flat_call(&afs_RXVLGetEntryById, 12, 384); | 
					
						
							|  |  |  | 	if (!call) | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:57:07 -07:00
										 |  |  | 	call->key = key; | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	call->reply = entry; | 
					
						
							|  |  |  | 	call->service_id = VL_SERVICE; | 
					
						
							|  |  |  | 	call->port = htons(AFS_VL_PORT); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	/* marshall the parameters */ | 
					
						
							|  |  |  | 	bp = call->request; | 
					
						
							|  |  |  | 	*bp++ = htonl(VLGETENTRYBYID); | 
					
						
							|  |  |  | 	*bp++ = htonl(volid); | 
					
						
							|  |  |  | 	*bp   = htonl(voltype); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-26 15:55:03 -07:00
										 |  |  | 	/* initiate the call */ | 
					
						
							|  |  |  | 	return afs_make_call(addr, call, GFP_KERNEL, wait_mode); | 
					
						
							| 
									
										
										
										
											2007-04-26 15:49:28 -07:00
										 |  |  | } |