⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gnbdd.c

📁 openGFS , a kind of file system.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *    Copyright 1999 Regents of the University of Minnesota *    Portions Copyright 1999-2001 Sistina Software, Inc. *    Portions Copyright 2001 The OpenGFS Project * *    This is free software released under the GNU General Public License. *    There is no warranty for this software.  See the file COPYING for *    details. * *    See the file AUTHORS for a list of contributors. *  */#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <netinet/in.h>#include <fcntl.h>#include <sys/ioctl.h>#include <signal.h>#include <sys/mount.h>#include <sys/mman.h>#include <errno.h>#include "trans.h"/* placeholder */#define printff(fmt,args...)/* some private data structures. */typedef struct {	int fd;	pthread_mutex_t mux;	pthread_mutex_t sender;	/* other info? */} clients_t;/* Table of clients that are logged in */clients_t *Clients = NULL;int client_cnt = 0;/* This is so there will only ever be one thread looking at accepts. */pthread_mutex_t AcceptMux;/* This global keeps the server running. */static int Server_Runs = 1;/* This file descriptor is the data we're serving. */static int data_fd = -1;static uint64_t datasize = 0;	/*bytes */static char *datamap = NULL;static int readonly = 0;/* ripped out of nbd code base*/uint64_t ntohll(uint64_t a){#if (BYTE_ORDER == LITTLE_ENDIAN)	uint32_t lo, hi;	lo = ntohl(a & 0xffffffff);	hi = ntohl(a >> 32U);	return (uint64_t)lo << 32U | hi;#else	return a;#endif}#define htonll ntohll/****************************************************************************** * dump_buffer() * prints out the contents of a buffer for inspection.  ignores formats. * * Need to get all zero lines absorbed. */voiddump_buffer(void *buf, int len){	int i;	uint8_t *c = buf;	for (i = 0; i < len; i++) {		if (i % 16 == 0)			printf("\n%4u: ", i);		printf("%2x ", c[i]);	}	printf("\n");}/****************************************************************************** * heh, simple recv/send wrappers to get all of the beffer sent over the * net.  Had forgotten I needed this.... */intcpt_recv(int s, void *buf, size_t len, int flags){	int res;	do {		res = recv(s, buf, len, flags);		if (res < 0)			return res;		len -= res;		buf += res;	} while (len > 0);	return res;}intcpt_send(int s, void *buf, size_t len, int flags){	int res;	do {		res = send(s, buf, len, flags);		if (res < 0)			return res;		len -= res;		buf += res;	} while (len > 0);	return res;}/****************************************************************************** * client_alloc() * expands the size of the clients table. */#define NALLOC 10voidclient_alloc(void){	/* FIXME: There is NO upperbound on the number of active connections!  */	int i;	if (Clients == NULL)		Clients = malloc(NALLOC * sizeof(clients_t));	else		Clients =		    realloc(Clients, (client_cnt + NALLOC) * sizeof(clients_t));	if (Clients == NULL) {		perror("Can't alloc memory for client array");		exit(1);	}	for (i = client_cnt; i < client_cnt + NALLOC; i++) {		Clients[i].fd = -1;		pthread_mutex_init(&Clients[i].mux, NULL);		pthread_mutex_init(&Clients[i].sender, NULL);	}	client_cnt += NALLOC;	printf("realloced clients\n");}/****************************************************************************** * client_add() */intclient_add(int fd){	int i;	if (Clients == NULL)		client_alloc();      CAagain:	for (i = 0; i < client_cnt; i++) {		if (Clients[i].fd == -1) {	/* FIXME: RACE */			Clients[i].fd = fd;			pthread_mutex_init(&Clients[i].mux, NULL);			pthread_mutex_init(&Clients[i].sender, NULL);			return i;		}	}	/* client array must be full, expand it. */	client_alloc();	goto CAagain;		/* now go add it. */}/****************************************************************************** * client_del() * resetting the mutexes here may not be a good idea. do some checking. */voidclient_del(int fd){	int i;	for (i = 0; i < client_cnt; i++) {		if (Clients[i].fd == fd) {			Clients[i].fd = -1;			pthread_mutex_destroy(&Clients[i].mux);			pthread_mutex_destroy(&Clients[i].sender);			return;		}	}	/* pop an error? */}/****************************************************************************** * handleRequest() * * See if we can't get mmapping done instead of lseek&(read|write) */inthandleRequest(clients_t * Client, theader_t * ioHdr){	unsigned long len;	unsigned long long offset;	int n;	int clifd = Client->fd;	pthread_mutex_t *sender = &Client->sender;	char buf[20480];	len = ntohl(ioHdr->len);	offset = ntohll(ioHdr->offset);#if 0	printf("ioHdr: type=0x%x, key=0x%" FMT_64 "x, len=0x%lx, offset=0x%"	       FMT_64 "x\n", ioHdr->type, ioHdr->key, len, offset);#endif	if (len > 10240) {		perror("Request too large");		return -1;	}	if (len + offset > datasize) {		perror("Out of bounds.");		return -1;	}	switch (ioHdr->type) {	case tioReadReq:		printff("Doing a Read\n");		/* Need to get len bytes from offset out of data_fd */		if (datamap) {			ioHdr->type = tioReadRpl;			pthread_mutex_lock(sender);			n = cpt_send(clifd, ioHdr, theader_len, 0);			n = cpt_send(clifd, (datamap + offset), len, 0);			pthread_mutex_unlock(sender);		} else {			if (lseek(data_fd, offset, SEEK_SET) < 0)				perror("Read: llseek");			printff("Done seek\n");			if (read(data_fd, buf, len) < 0)				perror("Read: read");			printff("Done read\n");			ioHdr->type = tioReadRpl;			pthread_mutex_lock(sender);			n = cpt_send(clifd, ioHdr, theader_len, 0);			n = cpt_send(clifd, buf, len, 0);			pthread_mutex_unlock(sender);		}		printff("Done send\n");		break;	case tioWriteReq:		printff("Doing a Write\n");		/* need a readonly check.... */		/* we have len bytes that we want to write at offset in data_fd */		if (datamap) {			n = cpt_recv(clifd, (datamap + offset), len, 0);		} else {			n = cpt_recv(clifd, buf, len, 0);			if (n == 0)				return -1;			if (lseek(data_fd, offset, SEEK_SET) < 0)				perror("Write: lseek");			if (write(data_fd, buf, len) < 0)				perror("Write: write");		}		ioHdr->type = tioWriteRpl;		ioHdr->len = 0;		ioHdr->err = 0;		ioHdr->offset = 0;		/*expects an ack.. */		pthread_mutex_lock(sender);		n = cpt_send(clifd, ioHdr, theader_len, 0);		pthread_mutex_unlock(sender);		printff("Done send\n");		break;	case tioShutdown:		/* Gotta close the connection, after replying. */		/* ioHdr should be exactly what we waht to send back, so we'll		 * just dump it right back.		 */		pthread_mutex_lock(sender);		n = cpt_send(clifd, &ioHdr, theader_len, 0);		pthread_mutex_unlock(sender);		/* now close shop. */		return -1;		break;	default:		printf("Unrecognised header.\n");		printf("ioHdr: type=0x%x, key=0x%llx,"		       "len=0x%lx, offset=0x%llx\n", ioHdr->type,		       ioHdr->key, len, offset);		break;	}	return 0;}/****************************************************************************** * setkeepalive * quicky wrapper for setting the keepalive bit on a socket. * * This works, BUT if you take a look at the defaults for linux: *   cat /proc/sys/net/ipv4/tcp_keepalive_probes *   cat /proc/sys/net/ipv4/tcp_keepalive_time * you look at those. 9 probes, and 7200 somthings. I think seconds. That's * damn long. I reset the timeout on the server machine to 60, and it * actually works. if you wait for it. *   echo "60" > /proc/sys/net/ipv4/tcp_keepalive_time * So I'll leave this here, but we may need a faster method of detecting * client death. */intsetkeepalive(int sk){	int iopt = 1;

⌨️ 快捷键说明

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