vlclient.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 696 行 · 第 1/2 页

C
696
字号
/* vlclient.c: 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 <rxrpc/rxrpc.h>#include <rxrpc/transport.h>#include <rxrpc/connection.h>#include <rxrpc/call.h>#include "server.h"#include "volume.h"#include "vlclient.h"#include "kafsasyncd.h"#include "kafstimod.h"#include "errors.h"#include "internal.h"#define VLGETENTRYBYID		503	/* AFS Get Cache Entry By ID operation ID */#define VLGETENTRYBYNAME	504	/* AFS Get Cache Entry By Name operation ID */#define VLPROBE			514	/* AFS Probe Volume Location Service operation ID */static void afs_rxvl_get_entry_by_id_attn(struct rxrpc_call *call);static void afs_rxvl_get_entry_by_id_error(struct rxrpc_call *call);/*****************************************************************************//* * map afs VL abort codes to/from Linux error codes * - called with call->lock held */static void afs_rxvl_aemap(struct rxrpc_call *call){	int err;	_enter("{%u,%u,%d}",	       call->app_err_state, call->app_abort_code, call->app_errno);	switch (call->app_err_state) {	case RXRPC_ESTATE_LOCAL_ABORT:		call->app_abort_code = -call->app_errno;		return;	case RXRPC_ESTATE_PEER_ABORT:		switch (call->app_abort_code) {		case AFSVL_IDEXIST:		err = -EEXIST;		break;		case AFSVL_IO:			err = -EREMOTEIO;	break;		case AFSVL_NAMEEXIST:		err = -EEXIST;		break;		case AFSVL_CREATEFAIL:		err = -EREMOTEIO;	break;		case AFSVL_NOENT:		err = -ENOMEDIUM;	break;		case AFSVL_EMPTY:		err = -ENOMEDIUM;	break;		case AFSVL_ENTDELETED:		err = -ENOMEDIUM;	break;		case AFSVL_BADNAME:		err = -EINVAL;		break;		case AFSVL_BADINDEX:		err = -EINVAL;		break;		case AFSVL_BADVOLTYPE:		err = -EINVAL;		break;		case AFSVL_BADSERVER:		err = -EINVAL;		break;		case AFSVL_BADPARTITION:	err = -EINVAL;		break;		case AFSVL_REPSFULL:		err = -EFBIG;		break;		case AFSVL_NOREPSERVER:		err = -ENOENT;		break;		case AFSVL_DUPREPSERVER:	err = -EEXIST;		break;		case AFSVL_RWNOTFOUND:		err = -ENOENT;		break;		case AFSVL_BADREFCOUNT:		err = -EINVAL;		break;		case AFSVL_SIZEEXCEEDED:	err = -EINVAL;		break;		case AFSVL_BADENTRY:		err = -EINVAL;		break;		case AFSVL_BADVOLIDBUMP:	err = -EINVAL;		break;		case AFSVL_IDALREADYHASHED:	err = -EINVAL;		break;		case AFSVL_ENTRYLOCKED:		err = -EBUSY;		break;		case AFSVL_BADVOLOPER:		err = -EBADRQC;		break;		case AFSVL_BADRELLOCKTYPE:	err = -EINVAL;		break;		case AFSVL_RERELEASE:		err = -EREMOTEIO;	break;		case AFSVL_BADSERVERFLAG:	err = -EINVAL;		break;		case AFSVL_PERM:		err = -EACCES;		break;		case AFSVL_NOMEM:		err = -EREMOTEIO;	break;		default:			err = afs_abort_to_error(call->app_abort_code);			break;		}		call->app_errno = err;		return;	default:		return;	}} /* end afs_rxvl_aemap() */#if 0/*****************************************************************************//* * probe a volume location server to see if it is still alive -- unused */static int afs_rxvl_probe(struct afs_server *server, int alloc_flags){	struct rxrpc_connection *conn;	struct rxrpc_call *call;	struct kvec piov[1];	size_t sent;	int ret;	__be32 param[1];	DECLARE_WAITQUEUE(myself, current);	/* get hold of the vlserver connection */	ret = afs_server_get_vlconn(server, &conn);	if (ret < 0)		goto out;	/* create a call through that connection */	ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call);	if (ret < 0) {		printk("kAFS: Unable to create call: %d\n", ret);		goto out_put_conn;	}	call->app_opcode = VLPROBE;	/* we want to get event notifications from the call */	add_wait_queue(&call->waitq, &myself);	/* marshall the parameters */	param[0] = htonl(VLPROBE);	piov[0].iov_len = sizeof(param);	piov[0].iov_base = param;	/* send the parameters to the server */	ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET,				    alloc_flags, 0, &sent);	if (ret < 0)		goto abort;	/* wait for the reply to completely arrive */	for (;;) {		set_current_state(TASK_INTERRUPTIBLE);		if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||		    signal_pending(current))			break;		schedule();	}	set_current_state(TASK_RUNNING);	ret = -EINTR;	if (signal_pending(current))		goto abort;	switch (call->app_call_state) {	case RXRPC_CSTATE_ERROR:		ret = call->app_errno;		goto out_unwait;	case RXRPC_CSTATE_CLNT_GOT_REPLY:		ret = 0;		goto out_unwait;	default:		BUG();	} abort:	set_current_state(TASK_UNINTERRUPTIBLE);	rxrpc_call_abort(call, ret);	schedule(); out_unwait:	set_current_state(TASK_RUNNING);	remove_wait_queue(&call->waitq, &myself);	rxrpc_put_call(call); out_put_conn:	rxrpc_put_connection(conn); out:	return ret;} /* end afs_rxvl_probe() */#endif/*****************************************************************************//* * look up a volume location database entry by name */int afs_rxvl_get_entry_by_name(struct afs_server *server,			       const char *volname,			       unsigned volnamesz,			       struct afs_cache_vlocation *entry){	DECLARE_WAITQUEUE(myself, current);	struct rxrpc_connection *conn;	struct rxrpc_call *call;	struct kvec piov[3];	unsigned tmp;	size_t sent;	int ret, loop;	__be32 *bp, param[2], zero;	_enter(",%*.*s,%u,", volnamesz, volnamesz, volname, volnamesz);	memset(entry, 0, sizeof(*entry));	/* get hold of the vlserver connection */	ret = afs_server_get_vlconn(server, &conn);	if (ret < 0)		goto out;	/* create a call through that connection */	ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call);	if (ret < 0) {		printk("kAFS: Unable to create call: %d\n", ret);		goto out_put_conn;	}	call->app_opcode = VLGETENTRYBYNAME;	/* we want to get event notifications from the call */	add_wait_queue(&call->waitq, &myself);	/* marshall the parameters */	piov[1].iov_len = volnamesz;	piov[1].iov_base = (char *) volname;	zero = 0;	piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;	piov[2].iov_base = &zero;	param[0] = htonl(VLGETENTRYBYNAME);	param[1] = htonl(piov[1].iov_len);	piov[0].iov_len = sizeof(param);	piov[0].iov_base = param;	/* send the parameters to the server */	ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,				    0, &sent);	if (ret < 0)		goto abort;	/* wait for the reply to completely arrive */	bp = rxrpc_call_alloc_scratch(call, 384);	ret = rxrpc_call_read_data(call, bp, 384,				   RXRPC_CALL_READ_BLOCK |				   RXRPC_CALL_READ_ALL);	if (ret < 0) {		if (ret == -ECONNABORTED) {			ret = call->app_errno;			goto out_unwait;		}		goto abort;	}	/* unmarshall the reply */	for (loop = 0; loop < 64; loop++)		entry->name[loop] = ntohl(*bp++);	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++);		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 */	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;	ret = -ENOMEDIUM;	if (!entry->vidmask)		goto abort;	/* success */	entry->rtime = get_seconds();	ret = 0; out_unwait:	set_current_state(TASK_RUNNING);	remove_wait_queue(&call->waitq, &myself);	rxrpc_put_call(call); out_put_conn:	rxrpc_put_connection(conn); out:	_leave(" = %d", ret);	return ret; abort:	set_current_state(TASK_UNINTERRUPTIBLE);	rxrpc_call_abort(call, ret);	schedule();	goto out_unwait;} /* end afs_rxvl_get_entry_by_name() *//*****************************************************************************//* * look up a volume location database entry by ID */int afs_rxvl_get_entry_by_id(struct afs_server *server,			     afs_volid_t volid,			     afs_voltype_t voltype,			     struct afs_cache_vlocation *entry){	DECLARE_WAITQUEUE(myself, current);	struct rxrpc_connection *conn;	struct rxrpc_call *call;	struct kvec piov[1];	unsigned tmp;	size_t sent;	int ret, loop;	__be32 *bp, param[3];	_enter(",%x,%d,", volid, voltype);	memset(entry, 0, sizeof(*entry));	/* get hold of the vlserver connection */	ret = afs_server_get_vlconn(server, &conn);	if (ret < 0)		goto out;	/* create a call through that connection */	ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call);	if (ret < 0) {		printk("kAFS: Unable to create call: %d\n", ret);		goto out_put_conn;	}	call->app_opcode = VLGETENTRYBYID;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?