Blame src/components/appio/tests/iozone/libasync.c

Packit 577717
Packit 577717
Packit 577717
/* 
Packit 577717
 * Library for Posix async read operations with hints.
Packit 577717
 * Author: Don Capps
Packit 577717
 * Company: Iozone
Packit 577717
 * Date: 4/24/1998
Packit 577717
 *
Packit 577717
 * Two models are supported.  First model is a replacement for read() where the async
Packit 577717
 * operations are performed and the requested data is bcopy()-ed back into the users 
Packit 577717
 * buffer. The second model is a new version of read() where the caller does not 
Packit 577717
 * supply the address of the buffer but instead is returned an address to the
Packit 577717
 * location of the data. The second model eliminates a bcopy from the path.
Packit 577717
 *
Packit 577717
 * To use model #1:
Packit 577717
 * 1. Call async_init(&pointer_on_stack,fd,direct_flag);
Packit 577717
 *	The fd is the file descriptor for the async operations.
Packit 577717
 *	The direct_flag sets VX_DIRECT 
Packit 577717
 *
Packit 577717
 * 2. Call async_read(gc, fd, ubuffer, offset, size, stride, max, depth)
Packit 577717
 *    	Where:
Packit 577717
 *	gc ............	is the pointer on the stack
Packit 577717
 *	fd ............	is the file descriptor
Packit 577717
 *	ubuffer .......	is the address of the user buffer.
Packit 577717
 *	offset ........	is the offset in the file to begin reading
Packit 577717
 *	size ..........	is the size of the transfer.
Packit 577717
 *	stride ........	is the distance, in size units, to space the async reads.
Packit 577717
 *	max ...........	is the max size of the file to be read.
Packit 577717
 *	depth .........	is the number of async operations to perform.
Packit 577717
 *
Packit 577717
 * 3. Call end_async(gc) when finished.
Packit 577717
 *	Where:
Packit 577717
 *	gc ............ is the pointer on the stack.
Packit 577717
 *
Packit 577717
 * To use model #2:
Packit 577717
 * 1. Call async_init(&pointer_on_stack,fd,direct_flag);
Packit 577717
 *	The fd is the file descriptor for the async operations.
Packit 577717
 *	The direct_flag sets VX_DIRECT 
Packit 577717
 * 2. Call async_read(gc, fd, &ubuffer, offset, size, stride, max, depth)
Packit 577717
 *    	Where:
Packit 577717
 *	gc ............	is the pointer on the stack
Packit 577717
 *	fd ............	is the file descriptor
Packit 577717
 *	ubuffer .......	is the address of a pointer that will be filled in 
Packit 577717
 *                      by the async library.
Packit 577717
 *	offset ........	is the offset in the file to begin reading
Packit 577717
 *	size ..........	is the size of the transfer.
Packit 577717
 *	stride ........	is the distance, in size units, to space the async reads.
Packit 577717
 *	max ...........	is the max size of the file to be read.
Packit 577717
 *	depth .........	is the number of async operations to perform.
Packit 577717
 *
Packit 577717
 * 3. Call async_release(gc) when finished with the data that was returned.
Packit 577717
 *    This allows the async library to reuse the memory that was filled in
Packit 577717
 *    and returned to the user.
Packit 577717
 *
Packit 577717
 * 4. Call end_async(gc) when finished.
Packit 577717
 *	Where:
Packit 577717
 *	gc ............ is the pointer on the stack.
Packit 577717
 *
Packit 577717
 * To use model #1: (WRITES)
Packit 577717
 * 1. Call async_init(&pointer_on_stack,fd,direct_flag);
Packit 577717
 *	The fd is the file descriptor for the async operations.
Packit 577717
 *
Packit 577717
 * 2. Call async_write(gc, fd, ubuffer, size, offset, depth)
Packit 577717
 *    	Where:
Packit 577717
 *	gc ............	is the pointer on the stack
Packit 577717
 *	fd ............	is the file descriptor
Packit 577717
 *	ubuffer .......	is the address of the user buffer.
Packit 577717
 *	size ..........	is the size of the transfer.
Packit 577717
 *	offset ........	is the offset in the file to begin reading
Packit 577717
 *	depth .........	is the number of async operations to perform.
Packit 577717
 *
Packit 577717
 * 4. Call end_async(gc) when finished.
Packit 577717
 *	Where:
Packit 577717
 *	gc ............ is the pointer on the stack.
Packit 577717
 *
Packit 577717
 * Notes:
Packit 577717
 *	The intended use is to replace calls to read() with calls to
Packit 577717
 *	async_read() and allow the user to make suggestions on 
Packit 577717
 *	what kind of async read-ahead would be nice to have.
Packit 577717
 *	The first transfer requested is guarenteed to be complete
Packit 577717
 *	before returning to the caller. The async operations will
Packit 577717
 *	be started and will also be guarenteed to have completed
Packit 577717
 *	if the next call specifies its first request to be one
Packit 577717
 *	that was previously performed with an async operation.
Packit 577717
 *	
Packit 577717
 *	The async_read_no_copy() function allows the async operations
Packit 577717
 *	to return the data to the user and not have to perform 
Packit 577717
 *	a bcopy of the data back into the user specified buffer 
Packit 577717
 *	location. This model is faster but assumes that the user
Packit 577717
 *	application has been modified to work with this model.
Packit 577717
 *
Packit 577717
 * 	The async_write() is intended to enhance the performance of 
Packit 577717
 *	initial writes to a file. This is the slowest case in the write
Packit 577717
 *	path as it must perform meta-data allocations and wait.
Packit 577717
 */
Packit 577717
Packit 577717
#include <sys/types.h>
Packit 577717
#include <aio.h>
Packit 577717
#if defined(solaris) || defined(linux) || defined(SCO_Unixware_gcc)
Packit 577717
#else
Packit 577717
#include <sys/timers.h>
Packit 577717
#endif
Packit 577717
#include <sys/errno.h>
Packit 577717
#include <unistd.h>
Packit 577717
#ifndef bsd4_4
Packit 577717
#include <malloc.h>
Packit 577717
#endif
Packit 577717
#ifdef VXFS
Packit 577717
#include <sys/fs/vx_ioctl.h>
Packit 577717
#endif
Packit 577717
Packit 577717
#if defined(OSFV5) || defined(linux)
Packit 577717
#include <string.h>
Packit 577717
#endif
Packit 577717
Packit 577717
#if defined(linux)
Packit 577717
#include <unistd.h>
Packit 577717
#include <stdio.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#endif
Packit 577717
Packit 577717
#if (defined(solaris) && defined(__LP64__)) || defined(__s390x__) || defined(FreeBSD)
Packit 577717
/* If we are building for 64-bit Solaris, all functions that return pointers
Packit 577717
 * must be declared before they are used; otherwise the compiler will assume
Packit 577717
 * that they return ints and the top 32 bits of the pointer will be lost,
Packit 577717
 * causing segmentation faults.  The following includes take care of this.
Packit 577717
 * It should be safe to add these for all other OSs too, but we're only
Packit 577717
 * doing it for Solaris now in case another OS turns out to be a special case.
Packit 577717
 */
Packit 577717
#include <stdio.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#include <strings.h> /* For the BSD string functions */
Packit 577717
#endif
Packit 577717
Packit 577717
void mbcopy(char *source, char *dest, size_t len);
Packit 577717
Packit 577717
Packit 577717
#if !defined(solaris) && !defined(off64_t) && !defined(_OFF64_T) && !defined(__off64_t_defined) && !defined(SCO_Unixware_gcc)
Packit 577717
typedef long long off64_t;
Packit 577717
#endif
Packit 577717
#if defined(OSFV5)
Packit 577717
#include <string.h>
Packit 577717
#endif
Packit 577717
Packit 577717
Packit 577717
extern long long page_size;
Packit 577717
extern int one;
Packit 577717
/*
Packit 577717
 * Internal cache entrys. Each entry on the global
Packit 577717
 * cache, pointed to by async_init(gc) will be of
Packit 577717
 * this structure type.
Packit 577717
 */
Packit 577717
char version[] = "Libasync Version $Revision$";
Packit 577717
struct cache_ent {
Packit 577717
	struct aiocb myaiocb;			/* For use in small file mode */
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#if defined(__CrayX1__)
Packit 577717
	aiocb64_t myaiocb64;		/* For use in large file mode */
Packit 577717
#else
Packit 577717
	struct aiocb64 myaiocb64;		/* For use in large file mode */
Packit 577717
#endif 
Packit 577717
#endif 
Packit 577717
	long long fd;				/* File descriptor */
Packit 577717
	long long size;				/* Size of the transfer */
Packit 577717
	struct cache_ent *forward;		/* link to next element on cache list */
Packit 577717
	struct cache_ent *back;			/* link to previous element on the cache list */
Packit 577717
	long long direct;			/* flag to indicate if the buffer should be */
Packit 577717
						/* de-allocated by library */
Packit 577717
	char *real_address;			/* Real address to free */
Packit 577717
	
Packit 577717
	volatile void *oldbuf;			/* Used for firewall to prevent in flight */
Packit 577717
						/* accidents */
Packit 577717
	int oldfd;				/* Used for firewall to prevent in flight */
Packit 577717
						/* accidents */
Packit 577717
	size_t oldsize;				/* Used for firewall to prevent in flight */
Packit 577717
						/* accidents */
Packit 577717
};
Packit 577717
Packit 577717
/*
Packit 577717
 * Head of the cache list
Packit 577717
 */
Packit 577717
struct cache {
Packit 577717
	struct cache_ent *head;		/* Head of cache list */
Packit 577717
	struct cache_ent *tail;		/* tail of cache list */
Packit 577717
	struct cache_ent *inuse_head;	/* head of in-use list */
Packit 577717
	long long count;		/* How many elements on the cache list */
Packit 577717
	struct cache_ent *w_head;		/* Head of cache list */
Packit 577717
	struct cache_ent *w_tail;		/* tail of cache list */
Packit 577717
	long long w_count;		/* How many elements on the write list */
Packit 577717
	};
Packit 577717
Packit 577717
long long max_depth;
Packit 577717
extern int errno;
Packit 577717
struct cache_ent *alloc_cache();
Packit 577717
struct cache_ent *incache();
Packit 577717
void async_init();
Packit 577717
void end_async();
Packit 577717
int async_suspend();
Packit 577717
int async_read();
Packit 577717
void takeoff_cache();
Packit 577717
void del_cache();
Packit 577717
void async_release();
Packit 577717
void putoninuse();
Packit 577717
void takeoffinuse();
Packit 577717
struct cache_ent *allocate_write_buffer();
Packit 577717
size_t async_write();
Packit 577717
void async_wait_for_write();
Packit 577717
void async_put_on_write_queue();
Packit 577717
void async_write_finish();
Packit 577717
Packit 577717
/* On Solaris _LP64 will be defined by <sys/types.h> if we're compiling
Packit 577717
 * as a 64-bit binary.  Make sure that __LP64__ gets defined in this case,
Packit 577717
 * too -- it should be defined on the compiler command line, but let's
Packit 577717
 * not rely on this.
Packit 577717
 */
Packit 577717
#if defined(_LP64)
Packit 577717
#if !defined(__LP64__)
Packit 577717
#define __LP64__
Packit 577717
#endif
Packit 577717
#endif
Packit 577717
Packit 577717
Packit 577717
/***********************************************/
Packit 577717
/* Initialization routine to setup the library */
Packit 577717
/***********************************************/
Packit 577717
void
Packit 577717
async_init(gc,fd,flag)
Packit 577717
struct cache **gc;
Packit 577717
int fd;
Packit 577717
int flag;
Packit 577717
{
Packit 577717
#ifdef VXFS
Packit 577717
	if(flag)
Packit 577717
		ioctl(fd,VX_SETCACHE,VX_DIRECT);
Packit 577717
#endif
Packit 577717
	if(*gc)
Packit 577717
	{
Packit 577717
		printf("Warning calling async_init two times ?\n");
Packit 577717
		return;
Packit 577717
	}
Packit 577717
	*gc=(struct cache *)malloc((size_t)sizeof(struct cache));
Packit 577717
	if(*gc == 0)
Packit 577717
	{
Packit 577717
		printf("Malloc failed\n");
Packit 577717
		exit(174);
Packit 577717
	}
Packit 577717
	bzero(*gc,sizeof(struct cache));
Packit 577717
#if defined(__AIX__) || defined(SCO_Unixware_gcc)
Packit 577717
	max_depth=500;
Packit 577717
#else
Packit 577717
	max_depth=sysconf(_SC_AIO_MAX);
Packit 577717
#endif
Packit 577717
}
Packit 577717
Packit 577717
/***********************************************/
Packit 577717
/* Tear down routine to shutdown the library   */
Packit 577717
/***********************************************/
Packit 577717
void
Packit 577717
end_async(gc)
Packit 577717
struct cache *gc;
Packit 577717
{
Packit 577717
	del_cache(gc);
Packit 577717
	async_write_finish(gc);
Packit 577717
	free((void *)gc);
Packit 577717
}
Packit 577717
Packit 577717
/***********************************************/
Packit 577717
/* Wait for a request to finish                */
Packit 577717
/***********************************************/
Packit 577717
int
Packit 577717
async_suspend(struct cache_ent *ce)
Packit 577717
{
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	const struct aiocb * const cblist[1] = {&ce->myaiocb};
Packit 577717
#else
Packit 577717
	const struct aiocb64 * const cblist[1] = {&ce->myaiocb64};
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	const struct aiocb * const cblist[1] = {&ce->myaiocb};
Packit 577717
#endif
Packit 577717
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	return aio_suspend(cblist, 1, NULL);
Packit 577717
#else
Packit 577717
	return aio_suspend64(cblist, 1, NULL);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	return aio_suspend(cblist, 1, NULL);
Packit 577717
#endif
Packit 577717
}
Packit 577717
Packit 577717
/*************************************************************************
Packit 577717
 * This routine is a generic async reader assist funtion. It takes
Packit 577717
 * the same calling parameters as read() but also extends the
Packit 577717
 * interface to include:
Packit 577717
 * stride ..... For the async reads, what is the distance, in size units, 
Packit 577717
 * 		to space the reads. Note: Stride of 0 indicates that
Packit 577717
 *		you do not want any read-ahead.
Packit 577717
 * max    ..... What is the maximum file offset for this operation.
Packit 577717
 * depth  ..... How much read-ahead do you want.
Packit 577717
 * 
Packit 577717
 * The calls to this will guarentee to complete the read() operation
Packit 577717
 * before returning to the caller. The completion may occur in two
Packit 577717
 * ways. First the operation may be completed by calling aio_read()
Packit 577717
 * and then waiting for it to complete. Second  the operation may be 
Packit 577717
 * completed by copying the data from a cache of previously completed 
Packit 577717
 * async operations. 
Packit 577717
 * In the event the read to be satisfied is not in the cache then a 
Packit 577717
 * series of async operations will be scheduled and then the first 
Packit 577717
 * async read will be completed. In the event that the read() can be 
Packit 577717
 * satisfied from the cache then the data is copied back to the 
Packit 577717
 * user buffer and a series of async reads will be initiated.  If a 
Packit 577717
 * read is issued and the cache contains data and the read can not 
Packit 577717
 * be satisfied from the cache, then the cache is discarded, and 
Packit 577717
 * a new cache is constructed.
Packit 577717
 * Note: All operations are aio_read(). The series will be issued
Packit 577717
 * as asyncs in the order requested. After all are in flight
Packit 577717
 * then the code will wait for the manditory first read.
Packit 577717
 *************************************************************************/
Packit 577717
Packit 577717
int 
Packit 577717
async_read(gc, fd, ubuffer, offset, size, stride, max, depth)
Packit 577717
struct cache *gc;
Packit 577717
long long fd;
Packit 577717
char *ubuffer;
Packit 577717
off64_t offset;
Packit 577717
long long size;
Packit 577717
long long stride;
Packit 577717
off64_t max;
Packit 577717
long long depth;
Packit 577717
{
Packit 577717
	off64_t a_offset,r_offset;
Packit 577717
	long long a_size;
Packit 577717
	struct cache_ent *ce,*first_ce=0;
Packit 577717
	long long i;
Packit 577717
	ssize_t retval=0;
Packit 577717
	ssize_t ret;
Packit 577717
	long long start = 0;
Packit 577717
	long long del_read=0;
Packit 577717
Packit 577717
	a_offset=offset;
Packit 577717
	a_size = size;
Packit 577717
	/*
Packit 577717
	 * Check to see if it can be completed from the cache
Packit 577717
	 */
Packit 577717
	if((ce=(struct cache_ent *)incache(gc,fd,offset,size)))
Packit 577717
	{
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		while((ret=aio_error(&ce->myaiocb))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(ce);
Packit 577717
		}
Packit 577717
#else
Packit 577717
		while((ret=aio_error64(&ce->myaiocb64))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(ce);
Packit 577717
		}
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		while((ret=aio_error(&ce->myaiocb))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(ce);
Packit 577717
		}
Packit 577717
#endif
Packit 577717
		if(ret)
Packit 577717
		{
Packit 577717
			printf("aio_error 1: ret %d %d\n",ret,errno);
Packit 577717
		}
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		retval=aio_return(&ce->myaiocb);
Packit 577717
#else
Packit 577717
#if defined(__CrayX1__)
Packit 577717
		retval=aio_return64((aiocb64_t *)&ce->myaiocb64);
Packit 577717
#else
Packit 577717
		retval=aio_return64((struct aiocb64 *)&ce->myaiocb64);
Packit 577717
#endif
Packit 577717
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		retval=aio_return(&ce->myaiocb);
Packit 577717
#endif
Packit 577717
		if(retval > 0)
Packit 577717
		{
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
			mbcopy((char *)ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval);
Packit 577717
#else
Packit 577717
			mbcopy((char *)ce->myaiocb64.aio_buf,(char *)ubuffer,(size_t)retval);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
			mbcopy((char *)ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval);
Packit 577717
#endif
Packit 577717
		}
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		if(retval < ce->myaiocb.aio_nbytes)
Packit 577717
#else
Packit 577717
		if(retval < ce->myaiocb64.aio_nbytes)
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		if(retval < ce->myaiocb.aio_nbytes)
Packit 577717
#endif
Packit 577717
		{
Packit 577717
			printf("aio_return error1: ret %d %d\n",retval,errno);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
			printf("aio_return error1: fd %d offset %ld buffer %lx size %d Opcode %d\n",
Packit 577717
				ce->myaiocb.aio_fildes,
Packit 577717
				ce->myaiocb.aio_offset,
Packit 577717
				(long)(ce->myaiocb.aio_buf),
Packit 577717
				ce->myaiocb.aio_nbytes,
Packit 577717
				ce->myaiocb.aio_lio_opcode
Packit 577717
#else
Packit 577717
			printf("aio_return error1: fd %d offset %lld buffer %lx size %d Opcode %d\n",
Packit 577717
				ce->myaiocb64.aio_fildes,
Packit 577717
				ce->myaiocb64.aio_offset,
Packit 577717
				(long)(ce->myaiocb64.aio_buf),
Packit 577717
				ce->myaiocb64.aio_nbytes,
Packit 577717
				ce->myaiocb64.aio_lio_opcode
Packit 577717
#endif
Packit 577717
#else
Packit 577717
			printf("aio_return error1: fd %d offset %d buffer %lx size %d Opcode %d\n",
Packit 577717
				ce->myaiocb.aio_fildes,
Packit 577717
				ce->myaiocb.aio_offset,
Packit 577717
				(long)(ce->myaiocb.aio_buf),
Packit 577717
				ce->myaiocb.aio_nbytes,
Packit 577717
				ce->myaiocb.aio_lio_opcode
Packit 577717
#endif
Packit 577717
				);
Packit 577717
		}
Packit 577717
		ce->direct=0;
Packit 577717
		takeoff_cache(gc,ce);
Packit 577717
	}else
Packit 577717
	{
Packit 577717
		/*
Packit 577717
		 * Clear the cache and issue the first request async()
Packit 577717
		 */
Packit 577717
		del_cache(gc);
Packit 577717
		del_read++;
Packit 577717
		first_ce=alloc_cache(gc,fd,offset,size,(long long)LIO_READ);
Packit 577717
again:
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		ret=aio_read(&first_ce->myaiocb);
Packit 577717
#else
Packit 577717
		ret=aio_read64(&first_ce->myaiocb64);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		ret=aio_read(&first_ce->myaiocb);
Packit 577717
#endif
Packit 577717
		if(ret!=0)
Packit 577717
		{
Packit 577717
			if(errno==EAGAIN)
Packit 577717
				goto again;
Packit 577717
			else
Packit 577717
				printf("error returned from aio_read(). Ret %d errno %d\n",ret,errno);
Packit 577717
		}
Packit 577717
	}
Packit 577717
	if(stride==0)	 /* User does not want read-ahead */
Packit 577717
		goto out;
Packit 577717
	if(a_offset<0)	/* Before beginning of file */
Packit 577717
		goto out;
Packit 577717
	if(a_offset+size>max)	/* After end of file */
Packit 577717
		goto out;
Packit 577717
	if(depth >=(max_depth-1))
Packit 577717
		depth=max_depth-1;
Packit 577717
	if(depth==0)
Packit 577717
		goto out;
Packit 577717
	if(gc->count > 1)
Packit 577717
		start=depth-1;
Packit 577717
	for(i=start;i
Packit 577717
	{
Packit 577717
		r_offset=a_offset+((i+1)*(stride*a_size));
Packit 577717
		if(r_offset<0)
Packit 577717
			continue;
Packit 577717
		if(r_offset+size > max)
Packit 577717
			continue;
Packit 577717
		if((ce=incache(gc,fd,r_offset,a_size)))
Packit 577717
			continue;
Packit 577717
		ce=alloc_cache(gc,fd,r_offset,a_size,(long long)LIO_READ);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		ret=aio_read(&ce->myaiocb);
Packit 577717
#else
Packit 577717
		ret=aio_read64(&ce->myaiocb64);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		ret=aio_read(&ce->myaiocb);
Packit 577717
#endif
Packit 577717
		if(ret!=0)
Packit 577717
		{
Packit 577717
			takeoff_cache(gc,ce);
Packit 577717
			break;
Packit 577717
		}
Packit 577717
	}			
Packit 577717
out:
Packit 577717
	if(del_read)	/* Wait for the first read to complete */
Packit 577717
	{
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(first_ce);
Packit 577717
		}
Packit 577717
#else
Packit 577717
		while((ret=aio_error64(&first_ce->myaiocb64))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(first_ce);
Packit 577717
		}
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(first_ce);
Packit 577717
		}
Packit 577717
#endif
Packit 577717
		if(ret)
Packit 577717
			printf("aio_error 2: ret %d %d\n",ret,errno);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		retval=aio_return(&first_ce->myaiocb);
Packit 577717
#else
Packit 577717
		retval=aio_return64(&first_ce->myaiocb64);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		retval=aio_return(&first_ce->myaiocb);
Packit 577717
#endif
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		if(retval < first_ce->myaiocb.aio_nbytes)
Packit 577717
#else
Packit 577717
		if(retval < first_ce->myaiocb64.aio_nbytes)
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		if(retval < first_ce->myaiocb.aio_nbytes)
Packit 577717
#endif
Packit 577717
		{
Packit 577717
			printf("aio_return error2: ret %d %d\n",retval,errno);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
			printf("aio_return error2: fd %d offset %lld buffer %lx size %d Opcode %d\n",
Packit 577717
				first_ce->myaiocb.aio_fildes,
Packit 577717
				first_ce->myaiocb.aio_offset,
Packit 577717
				(long)(first_ce->myaiocb.aio_buf),
Packit 577717
				first_ce->myaiocb.aio_nbytes,
Packit 577717
				first_ce->myaiocb.aio_lio_opcode
Packit 577717
#else
Packit 577717
			printf("aio_return error2: fd %d offset %lld buffer %lx size %d Opcode %d\n",
Packit 577717
				first_ce->myaiocb64.aio_fildes,
Packit 577717
				first_ce->myaiocb64.aio_offset,
Packit 577717
				(long)(first_ce->myaiocb64.aio_buf),
Packit 577717
				first_ce->myaiocb64.aio_nbytes,
Packit 577717
				first_ce->myaiocb64.aio_lio_opcode
Packit 577717
#endif
Packit 577717
#else
Packit 577717
			printf("aio_return error2: fd %d offset %d buffer %lx size %d Opcode %d\n",
Packit 577717
				first_ce->myaiocb.aio_fildes,
Packit 577717
				first_ce->myaiocb.aio_offset,
Packit 577717
				(long)(first_ce->myaiocb.aio_buf),
Packit 577717
				first_ce->myaiocb.aio_nbytes,
Packit 577717
				first_ce->myaiocb.aio_lio_opcode
Packit 577717
#endif
Packit 577717
				);
Packit 577717
		}
Packit 577717
		if(retval > 0)
Packit 577717
		{
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
			mbcopy((char *)first_ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval);
Packit 577717
#else
Packit 577717
			mbcopy((char *)first_ce->myaiocb64.aio_buf,(char *)ubuffer,(size_t)retval);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
			mbcopy((char *)first_ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval);
Packit 577717
#endif
Packit 577717
		}
Packit 577717
		first_ce->direct=0;
Packit 577717
		takeoff_cache(gc,first_ce);
Packit 577717
	}
Packit 577717
	return((int)retval);	
Packit 577717
}
Packit 577717
Packit 577717
/************************************************************************
Packit 577717
 * This routine allocates a cache_entry. It contains the 
Packit 577717
 * aiocb block as well as linkage for use in the cache mechanism.
Packit 577717
 * The space allocated here will be released after the cache entry
Packit 577717
 * has been consumed. The routine takeoff_cache() will be called
Packit 577717
 * after the data has been copied to user buffer or when the
Packit 577717
 * cache is purged. The routine takeoff_cache() will also release
Packit 577717
 * all memory associated with this cache entry.
Packit 577717
 ************************************************************************/
Packit 577717
Packit 577717
struct cache_ent *
Packit 577717
alloc_cache(gc,fd,offset,size,op)
Packit 577717
struct cache *gc;
Packit 577717
long long fd,size,op;
Packit 577717
off64_t offset;
Packit 577717
{
Packit 577717
	struct cache_ent *ce;
Packit 577717
	long temp;
Packit 577717
	ce=(struct cache_ent *)malloc((size_t)sizeof(struct cache_ent));
Packit 577717
	if(ce == (struct cache_ent *)0)
Packit 577717
	{
Packit 577717
		printf("Malloc failed\n");
Packit 577717
		exit(175);
Packit 577717
	}
Packit 577717
	bzero(ce,sizeof(struct cache_ent));
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	ce->myaiocb.aio_fildes=(int)fd;
Packit 577717
	ce->myaiocb.aio_offset=(off64_t)offset;
Packit 577717
	ce->real_address = (char *)malloc((size_t)(size+page_size));
Packit 577717
	temp=(long)ce->real_address;
Packit 577717
	temp = (temp+page_size) & ~(page_size-1);
Packit 577717
	ce->myaiocb.aio_buf=(volatile void *)temp;
Packit 577717
	if(ce->myaiocb.aio_buf == 0)
Packit 577717
#else
Packit 577717
	ce->myaiocb64.aio_fildes=(int)fd;
Packit 577717
	ce->myaiocb64.aio_offset=(off64_t)offset;
Packit 577717
	ce->real_address = (char *)malloc((size_t)(size+page_size));
Packit 577717
	temp=(long)ce->real_address;
Packit 577717
	temp = (temp+page_size) & ~(page_size-1);
Packit 577717
	ce->myaiocb64.aio_buf=(volatile void *)temp;
Packit 577717
	if(ce->myaiocb64.aio_buf == 0)
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	ce->myaiocb.aio_fildes=(int)fd;
Packit 577717
	ce->myaiocb.aio_offset=(off_t)offset;
Packit 577717
	ce->real_address = (char *)malloc((size_t)(size+page_size));
Packit 577717
	temp=(long)ce->real_address;
Packit 577717
	temp = (temp+page_size) & ~(page_size-1);
Packit 577717
	ce->myaiocb.aio_buf=(volatile void *)temp;
Packit 577717
	if(ce->myaiocb.aio_buf == 0)
Packit 577717
#endif
Packit 577717
	{
Packit 577717
		printf("Malloc failed\n");
Packit 577717
		exit(176);
Packit 577717
	}
Packit 577717
	/*bzero(ce->myaiocb.aio_buf,(size_t)size);*/
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	ce->myaiocb.aio_reqprio=0;
Packit 577717
	ce->myaiocb.aio_nbytes=(size_t)size;
Packit 577717
	ce->myaiocb.aio_sigevent.sigev_notify=SIGEV_NONE;
Packit 577717
	ce->myaiocb.aio_lio_opcode=(int)op;
Packit 577717
#else
Packit 577717
	ce->myaiocb64.aio_reqprio=0;
Packit 577717
	ce->myaiocb64.aio_nbytes=(size_t)size;
Packit 577717
	ce->myaiocb64.aio_sigevent.sigev_notify=SIGEV_NONE;
Packit 577717
	ce->myaiocb64.aio_lio_opcode=(int)op;
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	ce->myaiocb.aio_reqprio=0;
Packit 577717
	ce->myaiocb.aio_nbytes=(size_t)size;
Packit 577717
	ce->myaiocb.aio_sigevent.sigev_notify=SIGEV_NONE;
Packit 577717
	ce->myaiocb.aio_lio_opcode=(int)op;
Packit 577717
#endif
Packit 577717
	ce->fd=(int)fd;
Packit 577717
	ce->forward=0;
Packit 577717
	ce->back=gc->tail;
Packit 577717
	if(gc->tail)
Packit 577717
		gc->tail->forward = ce;
Packit 577717
	gc->tail= ce;
Packit 577717
	if(!gc->head)
Packit 577717
		gc->head=ce;
Packit 577717
	gc->count++;
Packit 577717
	return(ce);
Packit 577717
}
Packit 577717
Packit 577717
/************************************************************************
Packit 577717
 * This routine checks to see if the requested data is in the
Packit 577717
 * cache. 
Packit 577717
*************************************************************************/
Packit 577717
struct cache_ent *
Packit 577717
incache(gc,fd,offset,size)
Packit 577717
struct cache *gc;
Packit 577717
long long fd,size;
Packit 577717
off64_t offset;
Packit 577717
{
Packit 577717
	struct cache_ent *move;
Packit 577717
	if(gc->head==0)
Packit 577717
	{
Packit 577717
		return(0);
Packit 577717
	}
Packit 577717
	move=gc->head;
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	while(move)
Packit 577717
	{
Packit 577717
		if((move->fd == fd) && (move->myaiocb.aio_offset==(off64_t)offset) &&
Packit 577717
			((size_t)size==move->myaiocb.aio_nbytes))
Packit 577717
			{
Packit 577717
				return(move);
Packit 577717
			}
Packit 577717
		move=move->forward;
Packit 577717
	}
Packit 577717
#else
Packit 577717
	while(move)
Packit 577717
	{
Packit 577717
		if((move->fd == fd) && (move->myaiocb64.aio_offset==(off64_t)offset) &&
Packit 577717
			((size_t)size==move->myaiocb64.aio_nbytes))
Packit 577717
			{
Packit 577717
				return(move);
Packit 577717
			}
Packit 577717
		move=move->forward;
Packit 577717
	}
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	while(move)
Packit 577717
	{
Packit 577717
		if((move->fd == fd) && (move->myaiocb.aio_offset==(off_t)offset) &&
Packit 577717
			((size_t)size==move->myaiocb.aio_nbytes))
Packit 577717
			{
Packit 577717
				return(move);
Packit 577717
			}
Packit 577717
		move=move->forward;
Packit 577717
	}
Packit 577717
#endif
Packit 577717
	return(0);
Packit 577717
}
Packit 577717
Packit 577717
/************************************************************************
Packit 577717
 * This routine removes a specific cache entry from the cache, and
Packit 577717
 * releases all memory associated witht the cache entry (if not direct).
Packit 577717
*************************************************************************/
Packit 577717
Packit 577717
void
Packit 577717
takeoff_cache(gc,ce)
Packit 577717
struct cache *gc;
Packit 577717
struct cache_ent *ce;
Packit 577717
{
Packit 577717
	struct cache_ent *move;
Packit 577717
	long long found;
Packit 577717
	move=gc->head;
Packit 577717
	if(move==ce) /* Head of list */
Packit 577717
	{
Packit 577717
Packit 577717
		gc->head=ce->forward;
Packit 577717
		if(gc->head)
Packit 577717
			gc->head->back=0;
Packit 577717
		else
Packit 577717
			gc->tail = 0;
Packit 577717
		if(!ce->direct)
Packit 577717
		{
Packit 577717
			free((void *)(ce->real_address));
Packit 577717
			free((void *)ce);
Packit 577717
		}
Packit 577717
		gc->count--;
Packit 577717
		return;
Packit 577717
	}
Packit 577717
	found=0;
Packit 577717
	while(move)
Packit 577717
	{
Packit 577717
		if(move==ce)
Packit 577717
		{
Packit 577717
			if(move->forward)
Packit 577717
			{
Packit 577717
				move->forward->back=move->back;
Packit 577717
			}
Packit 577717
			if(move->back)
Packit 577717
			{
Packit 577717
				move->back->forward=move->forward;
Packit 577717
			}
Packit 577717
			found=1;
Packit 577717
			break;
Packit 577717
		}
Packit 577717
		else
Packit 577717
		{
Packit 577717
			move=move->forward;
Packit 577717
		}
Packit 577717
	}
Packit 577717
	if(gc->head == ce)
Packit 577717
		gc->tail = ce;
Packit 577717
	if(!found)
Packit 577717
		printf("Internal Error in takeoff cache\n");
Packit 577717
	move=gc->head;
Packit 577717
	if(!ce->direct)
Packit 577717
	{
Packit 577717
		free((void *)(ce->real_address));
Packit 577717
		free((void *)ce);
Packit 577717
	}
Packit 577717
	gc->count--;
Packit 577717
}
Packit 577717
Packit 577717
/************************************************************************
Packit 577717
 * This routine is used to purge the entire cache. This is called when
Packit 577717
 * the cache contains data but the incomming read was not able to 
Packit 577717
 * be satisfied from the cache. This indicates that the previous
Packit 577717
 * async read-ahead was not correct and a new pattern is emerging. 
Packit 577717
 ************************************************************************/
Packit 577717
void
Packit 577717
del_cache(gc)
Packit 577717
struct cache *gc;
Packit 577717
{
Packit 577717
	struct cache_ent *ce;
Packit 577717
	ssize_t ret;
Packit 577717
	ce=gc->head;
Packit 577717
	while(1)
Packit 577717
	{
Packit 577717
		ce=gc->head;
Packit 577717
		if(ce==0)
Packit 577717
			return;
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		while((ret = aio_cancel(0,&ce->myaiocb))==AIO_NOTCANCELED)
Packit 577717
#else
Packit 577717
		while((ret = aio_cancel64(0,&ce->myaiocb64))==AIO_NOTCANCELED)
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		while((ret = aio_cancel(0,&ce->myaiocb))==AIO_NOTCANCELED)
Packit 577717
#endif
Packit 577717
			; 
Packit 577717
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		ret = aio_return(&ce->myaiocb);
Packit 577717
#else
Packit 577717
		ret = aio_return64(&ce->myaiocb64);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		ret = aio_return(&ce->myaiocb);
Packit 577717
#endif
Packit 577717
		ce->direct=0;
Packit 577717
		takeoff_cache(gc,ce);	  /* remove from cache */
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
/************************************************************************
Packit 577717
 * Like its sister async_read() this function performs async I/O for 
Packit 577717
 * all buffers but it differs in that it expects the caller to 
Packit 577717
 * request a pointer to the data to be returned instead of handing
Packit 577717
 * the function a location to put the data. This will allow the
Packit 577717
 * async I/O to be performed and does not require any bcopy to be
Packit 577717
 * done to put the data back into the location specified by the caller.
Packit 577717
 ************************************************************************/
Packit 577717
int
Packit 577717
async_read_no_copy(gc, fd, ubuffer, offset, size, stride, max, depth)
Packit 577717
struct cache *gc;
Packit 577717
long long fd;
Packit 577717
char **ubuffer;
Packit 577717
off64_t offset;
Packit 577717
long long size;
Packit 577717
long long stride;
Packit 577717
off64_t max;
Packit 577717
long long depth;
Packit 577717
{
Packit 577717
	off64_t a_offset,r_offset;
Packit 577717
	long long a_size;
Packit 577717
	struct cache_ent *ce,*first_ce=0;
Packit 577717
	long long i;
Packit 577717
	ssize_t retval=0;
Packit 577717
	ssize_t ret;
Packit 577717
	long long del_read=0;
Packit 577717
	long long start=0;
Packit 577717
Packit 577717
	a_offset=offset;
Packit 577717
	a_size = size;
Packit 577717
	/*
Packit 577717
	 * Check to see if it can be completed from the cache
Packit 577717
	 */
Packit 577717
	if((ce=(struct cache_ent *)incache(gc,fd,offset,size)))
Packit 577717
	{
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		while((ret=aio_error(&ce->myaiocb))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(ce);
Packit 577717
		}
Packit 577717
#else
Packit 577717
		while((ret=aio_error64(&ce->myaiocb64))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(ce);
Packit 577717
		}
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		while((ret=aio_error(&ce->myaiocb))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(ce);
Packit 577717
		}
Packit 577717
#endif
Packit 577717
		if(ret)
Packit 577717
			printf("aio_error 3: ret %d %d\n",ret,errno);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		if(ce->oldbuf != ce->myaiocb.aio_buf ||
Packit 577717
			ce->oldfd != ce->myaiocb.aio_fildes ||
Packit 577717
			ce->oldsize != ce->myaiocb.aio_nbytes) 
Packit 577717
#else
Packit 577717
		if(ce->oldbuf != ce->myaiocb64.aio_buf ||
Packit 577717
			ce->oldfd != ce->myaiocb64.aio_fildes ||
Packit 577717
			ce->oldsize != ce->myaiocb64.aio_nbytes) 
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		if(ce->oldbuf != ce->myaiocb.aio_buf ||
Packit 577717
			ce->oldfd != ce->myaiocb.aio_fildes ||
Packit 577717
			ce->oldsize != ce->myaiocb.aio_nbytes) 
Packit 577717
#endif
Packit 577717
			printf("It changed in flight\n");
Packit 577717
			
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		retval=aio_return(&ce->myaiocb);
Packit 577717
#else
Packit 577717
		retval=aio_return64(&ce->myaiocb64);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		retval=aio_return(&ce->myaiocb);
Packit 577717
#endif
Packit 577717
		if(retval > 0)
Packit 577717
		{
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
			*ubuffer=(char *)ce->myaiocb.aio_buf;
Packit 577717
#else
Packit 577717
			*ubuffer=(char *)ce->myaiocb64.aio_buf;
Packit 577717
#endif
Packit 577717
#else
Packit 577717
			*ubuffer=(char *)ce->myaiocb.aio_buf;
Packit 577717
#endif
Packit 577717
		}else
Packit 577717
			*ubuffer=0;
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		if(retval < ce->myaiocb.aio_nbytes)
Packit 577717
#else
Packit 577717
		if(retval < ce->myaiocb64.aio_nbytes)
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		if(retval < ce->myaiocb.aio_nbytes)
Packit 577717
#endif
Packit 577717
		{
Packit 577717
			printf("aio_return error4: ret %d %d\n",retval,errno);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
			printf("aio_return error4: fd %d offset %lld buffer %lx size %d Opcode %d\n",
Packit 577717
				ce->myaiocb.aio_fildes,
Packit 577717
				ce->myaiocb.aio_offset,
Packit 577717
				(long)(ce->myaiocb.aio_buf),
Packit 577717
				ce->myaiocb.aio_nbytes,
Packit 577717
				ce->myaiocb.aio_lio_opcode
Packit 577717
#else
Packit 577717
			printf("aio_return error4: fd %d offset %lld buffer %lx size %d Opcode %d\n",
Packit 577717
				ce->myaiocb64.aio_fildes,
Packit 577717
				ce->myaiocb64.aio_offset,
Packit 577717
				(long)(ce->myaiocb64.aio_buf),
Packit 577717
				ce->myaiocb64.aio_nbytes,
Packit 577717
				ce->myaiocb64.aio_lio_opcode
Packit 577717
#endif
Packit 577717
#else
Packit 577717
			printf("aio_return error4: fd %d offset %d buffer %lx size %d Opcode %d\n",
Packit 577717
				ce->myaiocb.aio_fildes,
Packit 577717
				ce->myaiocb.aio_offset,
Packit 577717
				(long)(ce->myaiocb.aio_buf),
Packit 577717
				ce->myaiocb.aio_nbytes,
Packit 577717
				ce->myaiocb.aio_lio_opcode
Packit 577717
#endif
Packit 577717
				);
Packit 577717
		}
Packit 577717
		ce->direct=1;
Packit 577717
		takeoff_cache(gc,ce); /* do not delete buffer*/
Packit 577717
		putoninuse(gc,ce);
Packit 577717
	}else
Packit 577717
	{
Packit 577717
		/*
Packit 577717
		 * Clear the cache and issue the first request async()
Packit 577717
		 */
Packit 577717
		del_cache(gc);
Packit 577717
		del_read++;
Packit 577717
		first_ce=alloc_cache(gc,fd,offset,size,(long long)LIO_READ); /* allocate buffer */
Packit 577717
		/*printf("allocated buffer/read %x offset %d\n",first_ce->myaiocb.aio_buf,offset);*/
Packit 577717
again:
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		first_ce->oldbuf=first_ce->myaiocb.aio_buf;
Packit 577717
		first_ce->oldfd=first_ce->myaiocb.aio_fildes;
Packit 577717
		first_ce->oldsize=first_ce->myaiocb.aio_nbytes;
Packit 577717
		ret=aio_read(&first_ce->myaiocb);
Packit 577717
#else
Packit 577717
		first_ce->oldbuf=first_ce->myaiocb64.aio_buf;
Packit 577717
		first_ce->oldfd=first_ce->myaiocb64.aio_fildes;
Packit 577717
		first_ce->oldsize=first_ce->myaiocb64.aio_nbytes;
Packit 577717
		ret=aio_read64(&first_ce->myaiocb64);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		first_ce->oldbuf=first_ce->myaiocb.aio_buf;
Packit 577717
		first_ce->oldfd=first_ce->myaiocb.aio_fildes;
Packit 577717
		first_ce->oldsize=first_ce->myaiocb.aio_nbytes;
Packit 577717
		ret=aio_read(&first_ce->myaiocb);
Packit 577717
#endif
Packit 577717
		if(ret!=0)
Packit 577717
		{
Packit 577717
			if(errno==EAGAIN)
Packit 577717
				goto again;
Packit 577717
			else
Packit 577717
				printf("error returned from aio_read(). Ret %d errno %d\n",ret,errno);
Packit 577717
		}
Packit 577717
	}
Packit 577717
	if(stride==0)	 /* User does not want read-ahead */
Packit 577717
		goto out;
Packit 577717
	if(a_offset<0)	/* Before beginning of file */
Packit 577717
		goto out;
Packit 577717
	if(a_offset+size>max)	/* After end of file */
Packit 577717
		goto out;
Packit 577717
	if(depth >=(max_depth-1))
Packit 577717
		depth=max_depth-1;
Packit 577717
	if(depth==0)
Packit 577717
		goto out;
Packit 577717
	if(gc->count > 1)
Packit 577717
		start=depth-1;
Packit 577717
	for(i=start;i
Packit 577717
	{
Packit 577717
		r_offset=a_offset+((i+1)*(stride*a_size));
Packit 577717
		if(r_offset<0)
Packit 577717
			continue;
Packit 577717
		if(r_offset+size > max)
Packit 577717
			continue;
Packit 577717
		if((ce=incache(gc,fd,r_offset,a_size)))
Packit 577717
			continue;
Packit 577717
		ce=alloc_cache(gc,fd,r_offset,a_size,(long long)LIO_READ);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		ce->oldbuf=ce->myaiocb.aio_buf;
Packit 577717
		ce->oldfd=ce->myaiocb.aio_fildes;
Packit 577717
		ce->oldsize=ce->myaiocb.aio_nbytes;
Packit 577717
		ret=aio_read(&ce->myaiocb);
Packit 577717
#else
Packit 577717
		ce->oldbuf=ce->myaiocb64.aio_buf;
Packit 577717
		ce->oldfd=ce->myaiocb64.aio_fildes;
Packit 577717
		ce->oldsize=ce->myaiocb64.aio_nbytes;
Packit 577717
		ret=aio_read64(&ce->myaiocb64);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		ce->oldbuf=ce->myaiocb.aio_buf;
Packit 577717
		ce->oldfd=ce->myaiocb.aio_fildes;
Packit 577717
		ce->oldsize=ce->myaiocb.aio_nbytes;
Packit 577717
		ret=aio_read(&ce->myaiocb);
Packit 577717
#endif
Packit 577717
		if(ret!=0)
Packit 577717
		{
Packit 577717
			takeoff_cache(gc,ce);
Packit 577717
			break;
Packit 577717
		}
Packit 577717
	}			
Packit 577717
out:
Packit 577717
	if(del_read)	/* Wait for the first read to complete */
Packit 577717
	{
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(first_ce);
Packit 577717
		}
Packit 577717
#else
Packit 577717
		while((ret=aio_error64(&first_ce->myaiocb64))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(first_ce);
Packit 577717
		}
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS)
Packit 577717
		{
Packit 577717
			async_suspend(first_ce);
Packit 577717
		}
Packit 577717
#endif
Packit 577717
		if(ret)
Packit 577717
			printf("aio_error 4: ret %d %d\n",ret,errno);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		if(first_ce->oldbuf != first_ce->myaiocb.aio_buf ||
Packit 577717
			first_ce->oldfd != first_ce->myaiocb.aio_fildes ||
Packit 577717
			first_ce->oldsize != first_ce->myaiocb.aio_nbytes) 
Packit 577717
			printf("It changed in flight2\n");
Packit 577717
		retval=aio_return(&first_ce->myaiocb);
Packit 577717
#else
Packit 577717
		if(first_ce->oldbuf != first_ce->myaiocb64.aio_buf ||
Packit 577717
			first_ce->oldfd != first_ce->myaiocb64.aio_fildes ||
Packit 577717
			first_ce->oldsize != first_ce->myaiocb64.aio_nbytes) 
Packit 577717
			printf("It changed in flight2\n");
Packit 577717
		retval=aio_return64(&first_ce->myaiocb64);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		if(first_ce->oldbuf != first_ce->myaiocb.aio_buf ||
Packit 577717
			first_ce->oldfd != first_ce->myaiocb.aio_fildes ||
Packit 577717
			first_ce->oldsize != first_ce->myaiocb.aio_nbytes) 
Packit 577717
			printf("It changed in flight2\n");
Packit 577717
		retval=aio_return(&first_ce->myaiocb);
Packit 577717
#endif
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		if(retval < first_ce->myaiocb.aio_nbytes)
Packit 577717
#else
Packit 577717
		if(retval < first_ce->myaiocb64.aio_nbytes)
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		if(retval < first_ce->myaiocb.aio_nbytes)
Packit 577717
#endif
Packit 577717
		{
Packit 577717
			printf("aio_return error5: ret %d %d\n",retval,errno);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
			printf("aio_return error5: fd %d offset %lld buffer %lx size %d Opcode %d\n",
Packit 577717
				first_ce->myaiocb.aio_fildes,
Packit 577717
				first_ce->myaiocb.aio_offset,
Packit 577717
				(long)(first_ce->myaiocb.aio_buf),
Packit 577717
				first_ce->myaiocb.aio_nbytes,
Packit 577717
				first_ce->myaiocb.aio_lio_opcode
Packit 577717
#else
Packit 577717
			printf("aio_return error5: fd %d offset %lld buffer %lx size %d Opcode %d\n",
Packit 577717
				first_ce->myaiocb64.aio_fildes,
Packit 577717
				first_ce->myaiocb64.aio_offset,
Packit 577717
				(long)(first_ce->myaiocb64.aio_buf),
Packit 577717
				first_ce->myaiocb64.aio_nbytes,
Packit 577717
				first_ce->myaiocb64.aio_lio_opcode
Packit 577717
#endif
Packit 577717
#else
Packit 577717
			printf("aio_return error5: fd %d offset %ld buffer %lx size %d Opcode %d\n",
Packit 577717
				first_ce->myaiocb.aio_fildes,
Packit 577717
				first_ce->myaiocb.aio_offset,
Packit 577717
				(long)(first_ce->myaiocb.aio_buf),
Packit 577717
				first_ce->myaiocb.aio_nbytes,
Packit 577717
				first_ce->myaiocb.aio_lio_opcode
Packit 577717
#endif
Packit 577717
				);
Packit 577717
		}
Packit 577717
		if(retval > 0)
Packit 577717
		{
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
			*ubuffer=(char *)first_ce->myaiocb.aio_buf;
Packit 577717
#else
Packit 577717
			*ubuffer=(char *)first_ce->myaiocb64.aio_buf;
Packit 577717
#endif
Packit 577717
#else
Packit 577717
			*ubuffer=(char *)first_ce->myaiocb.aio_buf;
Packit 577717
#endif
Packit 577717
		}else
Packit 577717
			*ubuffer=(char *)0;
Packit 577717
		first_ce->direct=1;	 /* do not delete the buffer */
Packit 577717
		takeoff_cache(gc,first_ce);
Packit 577717
		putoninuse(gc,first_ce);
Packit 577717
	}
Packit 577717
	return((int)retval);	
Packit 577717
}
Packit 577717
Packit 577717
/************************************************************************
Packit 577717
 * The caller is now finished with the data that was provided so
Packit 577717
 * the library is now free to return the memory to the pool for later
Packit 577717
 * reuse.
Packit 577717
 ************************************************************************/
Packit 577717
void
Packit 577717
async_release(gc)
Packit 577717
struct cache *gc;
Packit 577717
{
Packit 577717
	takeoffinuse(gc);
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/************************************************************************
Packit 577717
 * Put the buffer on the inuse list. When the user is finished with 
Packit 577717
 * the buffer it will call back into async_release and the items on the 
Packit 577717
 * inuse list will be deallocated.
Packit 577717
 ************************************************************************/
Packit 577717
void
Packit 577717
putoninuse(gc,entry)
Packit 577717
struct cache *gc;
Packit 577717
struct cache_ent *entry;
Packit 577717
{
Packit 577717
	if(gc->inuse_head)
Packit 577717
		entry->forward=gc->inuse_head;
Packit 577717
	else
Packit 577717
		entry->forward=0;
Packit 577717
	gc->inuse_head=entry;
Packit 577717
}
Packit 577717
Packit 577717
/************************************************************************
Packit 577717
 * This is called when the application is finished with the data that
Packit 577717
 * was provided. The memory may now be returned to the pool.
Packit 577717
 ************************************************************************/
Packit 577717
void
Packit 577717
takeoffinuse(gc)
Packit 577717
struct cache *gc;
Packit 577717
{
Packit 577717
	struct cache_ent *ce;
Packit 577717
	if(gc->inuse_head==0)
Packit 577717
		printf("Takeoffinuse error\n");
Packit 577717
	ce=gc->inuse_head;
Packit 577717
	gc->inuse_head=gc->inuse_head->forward;
Packit 577717
	
Packit 577717
	if(gc->inuse_head !=0)
Packit 577717
		printf("Error in take off inuse\n");
Packit 577717
	free((void*)(ce->real_address));
Packit 577717
	free(ce);
Packit 577717
}
Packit 577717
Packit 577717
/*************************************************************************
Packit 577717
 * This routine is a generic async writer assist funtion. It takes
Packit 577717
 * the same calling parameters as write() but also extends the
Packit 577717
 * interface to include:
Packit 577717
 * 
Packit 577717
 * offset ..... offset in the file.
Packit 577717
 * depth  ..... How much read-ahead do you want.
Packit 577717
 * 
Packit 577717
 *************************************************************************/
Packit 577717
size_t
Packit 577717
async_write(gc,fd,buffer,size,offset,depth)
Packit 577717
struct cache *gc;
Packit 577717
long long fd,size;
Packit 577717
char *buffer;
Packit 577717
off64_t offset;
Packit 577717
long long depth;
Packit 577717
{
Packit 577717
	struct cache_ent *ce;
Packit 577717
	size_t ret;
Packit 577717
	ce=allocate_write_buffer(gc,fd,offset,size,(long long)LIO_WRITE,depth,0LL,(char *)0,(char *)0);
Packit 577717
	ce->direct=0;	 /* not direct. Lib supplies buffer and must free it */
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	mbcopy(buffer,(char *)(ce->myaiocb.aio_buf),(size_t)size);
Packit 577717
#else
Packit 577717
	mbcopy(buffer,(char *)(ce->myaiocb64.aio_buf),(size_t)size);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	mbcopy(buffer,(char *)(ce->myaiocb.aio_buf),(size_t)size);
Packit 577717
#endif
Packit 577717
	async_put_on_write_queue(gc,ce);
Packit 577717
	/*
Packit 577717
	printf("asw: fd %d offset %lld, size %d\n",ce->myaiocb64.aio_fildes,
Packit 577717
		ce->myaiocb64.aio_offset,
Packit 577717
		ce->myaiocb64.aio_nbytes);
Packit 577717
	*/	
Packit 577717
Packit 577717
again:
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	ret=aio_write(&ce->myaiocb);
Packit 577717
#else
Packit 577717
	ret=aio_write64(&ce->myaiocb64);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	ret=aio_write(&ce->myaiocb);
Packit 577717
#endif
Packit 577717
	if(ret==-1)
Packit 577717
	{
Packit 577717
		if(errno==EAGAIN)
Packit 577717
		{
Packit 577717
			async_wait_for_write(gc);
Packit 577717
			goto again;
Packit 577717
		}
Packit 577717
		if(errno==0)
Packit 577717
		{
Packit 577717
			/* Compensate for bug in async library */
Packit 577717
			async_wait_for_write(gc);
Packit 577717
			goto again;
Packit 577717
		}
Packit 577717
		else
Packit 577717
		{
Packit 577717
			printf("Error in aio_write: ret %d errno %d count %lld\n",ret,errno,gc->w_count);
Packit 577717
			/*
Packit 577717
			printf("aio_write_no_copy: fd %d buffer %x offset %lld size %d\n",
Packit 577717
				ce->myaiocb64.aio_fildes,
Packit 577717
				ce->myaiocb64.aio_buf,
Packit 577717
				ce->myaiocb64.aio_offset,
Packit 577717
				ce->myaiocb64.aio_nbytes);
Packit 577717
			*/
Packit 577717
			exit(177);
Packit 577717
		}
Packit 577717
	} 
Packit 577717
	return((ssize_t)size);
Packit 577717
}
Packit 577717
Packit 577717
/*************************************************************************
Packit 577717
 * Allocate a write aiocb and write buffer of the size specified. Also 
Packit 577717
 * put some extra buffer padding so that VX_DIRECT can do its job when
Packit 577717
 * needed.
Packit 577717
 *************************************************************************/
Packit 577717
Packit 577717
struct cache_ent *
Packit 577717
allocate_write_buffer(gc,fd,offset,size,op,w_depth,direct,buffer,free_addr)
Packit 577717
struct cache *gc;
Packit 577717
long long fd,size,op;
Packit 577717
off64_t offset;
Packit 577717
long long w_depth;
Packit 577717
long long direct;
Packit 577717
char *buffer,*free_addr;
Packit 577717
{
Packit 577717
	struct cache_ent *ce;
Packit 577717
	long temp;
Packit 577717
	if(fd==0LL)
Packit 577717
	{
Packit 577717
		printf("Setting up write buffer insane\n");
Packit 577717
		exit(178);
Packit 577717
	}
Packit 577717
	if(gc->w_count > w_depth)
Packit 577717
		async_wait_for_write(gc);
Packit 577717
	ce=(struct cache_ent *)malloc((size_t)sizeof(struct cache_ent));
Packit 577717
	if(ce == (struct cache_ent *)0)
Packit 577717
	{
Packit 577717
		printf("Malloc failed 1\n");
Packit 577717
		exit(179);
Packit 577717
	}
Packit 577717
	bzero(ce,sizeof(struct cache_ent));
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	ce->myaiocb.aio_fildes=(int)fd;
Packit 577717
	ce->myaiocb.aio_offset=(off64_t)offset;
Packit 577717
	if(!direct)
Packit 577717
	{
Packit 577717
		ce->real_address = (char *)malloc((size_t)(size+page_size));
Packit 577717
		temp=(long)ce->real_address;
Packit 577717
		temp = (temp+page_size) & ~(page_size-1);
Packit 577717
		ce->myaiocb.aio_buf=(volatile void *)temp;
Packit 577717
	}else
Packit 577717
	{
Packit 577717
		ce->myaiocb.aio_buf=(volatile void *)buffer;
Packit 577717
		ce->real_address=(char *)free_addr;
Packit 577717
	}
Packit 577717
	if(ce->myaiocb.aio_buf == 0)
Packit 577717
#else
Packit 577717
	ce->myaiocb64.aio_fildes=(int)fd;
Packit 577717
	ce->myaiocb64.aio_offset=(off64_t)offset;
Packit 577717
	if(!direct)
Packit 577717
	{
Packit 577717
		ce->real_address = (char *)malloc((size_t)(size+page_size));
Packit 577717
		temp=(long)ce->real_address;
Packit 577717
		temp = (temp+page_size) & ~(page_size-1);
Packit 577717
		ce->myaiocb64.aio_buf=(volatile void *)temp;
Packit 577717
	}
Packit 577717
	else
Packit 577717
	{
Packit 577717
		ce->myaiocb64.aio_buf=(volatile void *)buffer;
Packit 577717
		ce->real_address=(char *)free_addr;
Packit 577717
	}
Packit 577717
	if(ce->myaiocb64.aio_buf == 0)
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	ce->myaiocb.aio_fildes=(int)fd;
Packit 577717
	ce->myaiocb.aio_offset=(off_t)offset;
Packit 577717
	if(!direct)
Packit 577717
	{
Packit 577717
		ce->real_address = (char *)malloc((size_t)(size+page_size));
Packit 577717
		temp=(long)ce->real_address;
Packit 577717
		temp = (temp+page_size) & ~(page_size-1);
Packit 577717
		ce->myaiocb.aio_buf=(volatile void *)temp;
Packit 577717
	}
Packit 577717
	else
Packit 577717
	{
Packit 577717
		ce->myaiocb.aio_buf=(volatile void *)buffer;
Packit 577717
		ce->real_address=(char *)free_addr;
Packit 577717
	}
Packit 577717
	if(ce->myaiocb.aio_buf == 0)
Packit 577717
#endif
Packit 577717
	{
Packit 577717
		printf("Malloc failed 2\n");
Packit 577717
		exit(180);
Packit 577717
	}
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	ce->myaiocb.aio_reqprio=0;
Packit 577717
	ce->myaiocb.aio_nbytes=(size_t)size;
Packit 577717
	ce->myaiocb.aio_sigevent.sigev_notify=SIGEV_NONE;
Packit 577717
	ce->myaiocb.aio_lio_opcode=(int)op;
Packit 577717
#else
Packit 577717
	ce->myaiocb64.aio_reqprio=0;
Packit 577717
	ce->myaiocb64.aio_nbytes=(size_t)size;
Packit 577717
	ce->myaiocb64.aio_sigevent.sigev_notify=SIGEV_NONE;
Packit 577717
	ce->myaiocb64.aio_lio_opcode=(int)op;
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	ce->myaiocb.aio_reqprio=0;
Packit 577717
	ce->myaiocb.aio_nbytes=(size_t)size;
Packit 577717
	ce->myaiocb.aio_sigevent.sigev_notify=SIGEV_NONE;
Packit 577717
	ce->myaiocb.aio_lio_opcode=(int)op;
Packit 577717
#endif
Packit 577717
	ce->fd=(int)fd;
Packit 577717
	return(ce);
Packit 577717
}
Packit 577717
Packit 577717
/*************************************************************************
Packit 577717
 * Put it on the outbound queue.
Packit 577717
 *************************************************************************/
Packit 577717
Packit 577717
void
Packit 577717
async_put_on_write_queue(gc,ce)
Packit 577717
struct cache *gc;
Packit 577717
struct cache_ent *ce;
Packit 577717
{
Packit 577717
	ce->forward=0;
Packit 577717
	ce->back=gc->w_tail;
Packit 577717
	if(gc->w_tail)
Packit 577717
		gc->w_tail->forward = ce;
Packit 577717
	gc->w_tail= ce;
Packit 577717
	if(!gc->w_head)
Packit 577717
		gc->w_head=ce;
Packit 577717
	gc->w_count++;
Packit 577717
	return;
Packit 577717
}
Packit 577717
Packit 577717
/*************************************************************************
Packit 577717
 * Cleanup all outstanding writes
Packit 577717
 *************************************************************************/
Packit 577717
void
Packit 577717
async_write_finish(gc)
Packit 577717
struct cache *gc;
Packit 577717
{
Packit 577717
	while(gc->w_head)
Packit 577717
	{
Packit 577717
		/*printf("async_write_finish: Waiting for buffer %x to finish\n",gc->w_head->myaiocb64.aio_buf);*/
Packit 577717
		async_wait_for_write(gc);
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
/*************************************************************************
Packit 577717
 * Wait for an I/O to finish
Packit 577717
 *************************************************************************/
Packit 577717
Packit 577717
void
Packit 577717
async_wait_for_write(gc)
Packit 577717
struct cache *gc;
Packit 577717
{
Packit 577717
	struct cache_ent *ce;
Packit 577717
	size_t ret,retval;
Packit 577717
	if(gc->w_head==0)
Packit 577717
		return;
Packit 577717
	ce=gc->w_head;
Packit 577717
	gc->w_head=ce->forward;
Packit 577717
	gc->w_count--;
Packit 577717
	ce->forward=0;
Packit 577717
	if(ce==gc->w_tail)
Packit 577717
		gc->w_tail=0;
Packit 577717
	/*printf("Wait for buffer %x  offset %lld  size %d to finish\n",
Packit 577717
		ce->myaiocb64.aio_buf,
Packit 577717
		ce->myaiocb64.aio_offset,
Packit 577717
		ce->myaiocb64.aio_nbytes);
Packit 577717
	printf("write count %lld \n",gc->w_count);
Packit 577717
	*/
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	while((ret=aio_error(&ce->myaiocb))== EINPROGRESS)
Packit 577717
	{
Packit 577717
		async_suspend(ce);
Packit 577717
	}
Packit 577717
#else
Packit 577717
	while((ret=aio_error64(&ce->myaiocb64))== EINPROGRESS)
Packit 577717
	{
Packit 577717
		async_suspend(ce);
Packit 577717
	}
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	while((ret=aio_error(&ce->myaiocb))== EINPROGRESS)
Packit 577717
	{
Packit 577717
		async_suspend(ce);
Packit 577717
	}
Packit 577717
#endif
Packit 577717
	if(ret)
Packit 577717
	{
Packit 577717
		printf("aio_error 5: ret %d %d\n",ret,errno);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
		printf("fd %d offset %lld size %d\n",
Packit 577717
			ce->myaiocb.aio_fildes,
Packit 577717
			ce->myaiocb.aio_offset,
Packit 577717
			ce->myaiocb.aio_nbytes);
Packit 577717
#else
Packit 577717
		printf("fd %d offset %lld size %d\n",
Packit 577717
			ce->myaiocb64.aio_fildes,
Packit 577717
			ce->myaiocb64.aio_offset,
Packit 577717
			ce->myaiocb64.aio_nbytes);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
		printf("fd %d offset %lld size %d\n",
Packit 577717
			ce->myaiocb.aio_fildes,
Packit 577717
			ce->myaiocb.aio_offset,
Packit 577717
			ce->myaiocb.aio_nbytes);
Packit 577717
#endif
Packit 577717
		exit(181);
Packit 577717
	}
Packit 577717
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	retval=aio_return(&ce->myaiocb);
Packit 577717
#else
Packit 577717
#if defined(__CrayX1__)
Packit 577717
	retval=aio_return64((aiocb64_t *)&ce->myaiocb64);
Packit 577717
#else
Packit 577717
	retval=aio_return64((struct aiocb64 *)&ce->myaiocb64);
Packit 577717
#endif
Packit 577717
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	retval=aio_return(&ce->myaiocb);
Packit 577717
#endif
Packit 577717
	if((int)retval < 0)
Packit 577717
	{
Packit 577717
		printf("aio_return error: %d\n",errno);
Packit 577717
	}
Packit 577717
Packit 577717
	if(!ce->direct)
Packit 577717
	{
Packit 577717
		/* printf("Freeing buffer %x\n",ce->real_address);*/
Packit 577717
		free((void *)(ce->real_address));
Packit 577717
		free((void *)ce);
Packit 577717
	}
Packit 577717
Packit 577717
}
Packit 577717
Packit 577717
/*************************************************************************
Packit 577717
 * This routine is a generic async writer assist funtion. It takes
Packit 577717
 * the same calling parameters as write() but also extends the
Packit 577717
 * interface to include:
Packit 577717
 * 
Packit 577717
 * offset ..... offset in the file.
Packit 577717
 * depth  ..... How much read-ahead do you want.
Packit 577717
 * free_addr .. address of memory to free after write is completed.
Packit 577717
 * 
Packit 577717
 *************************************************************************/
Packit 577717
size_t
Packit 577717
async_write_no_copy(gc,fd,buffer,size,offset,depth,free_addr)
Packit 577717
struct cache *gc;
Packit 577717
long long fd,size;
Packit 577717
char *buffer;
Packit 577717
off64_t offset;
Packit 577717
long long depth;
Packit 577717
char *free_addr;
Packit 577717
{
Packit 577717
	struct cache_ent *ce;
Packit 577717
	size_t ret;
Packit 577717
	long long direct = 1;
Packit 577717
	ce=allocate_write_buffer(gc,fd,offset,size,(long long)LIO_WRITE,depth,direct,buffer,free_addr);
Packit 577717
	ce->direct=0;	/* have library de-allocate the buffer */
Packit 577717
	async_put_on_write_queue(gc,ce);
Packit 577717
	/*
Packit 577717
	printf("awnc: fd %d offset %lld, size %d\n",ce->myaiocb64.aio_fildes,
Packit 577717
		ce->myaiocb64.aio_offset,
Packit 577717
		ce->myaiocb64.aio_nbytes);
Packit 577717
	*/
Packit 577717
Packit 577717
again:
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
	ret=aio_write(&ce->myaiocb);
Packit 577717
#else
Packit 577717
	ret=aio_write64(&ce->myaiocb64);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
	ret=aio_write(&ce->myaiocb);
Packit 577717
#endif
Packit 577717
	if(ret==-1)
Packit 577717
	{
Packit 577717
		if(errno==EAGAIN)
Packit 577717
		{
Packit 577717
			async_wait_for_write(gc);
Packit 577717
			goto again;
Packit 577717
		}
Packit 577717
		if(errno==0)
Packit 577717
		{
Packit 577717
			/* Compensate for bug in async library */
Packit 577717
			async_wait_for_write(gc);
Packit 577717
			goto again;
Packit 577717
		}
Packit 577717
		else
Packit 577717
		{
Packit 577717
			printf("Error in aio_write: ret %d errno %d\n",ret,errno);
Packit 577717
#ifdef _LARGEFILE64_SOURCE 
Packit 577717
#ifdef __LP64__
Packit 577717
			printf("aio_write_no_copy: fd %d buffer %lx offset %lld size %d\n",
Packit 577717
				ce->myaiocb.aio_fildes,
Packit 577717
				(long)(ce->myaiocb.aio_buf),
Packit 577717
				ce->myaiocb.aio_offset,
Packit 577717
				ce->myaiocb.aio_nbytes);
Packit 577717
#else
Packit 577717
			printf("aio_write_no_copy: fd %d buffer %lx offset %lld size %d\n",
Packit 577717
				ce->myaiocb64.aio_fildes,
Packit 577717
				(long)(ce->myaiocb64.aio_buf),
Packit 577717
				ce->myaiocb64.aio_offset,
Packit 577717
				ce->myaiocb64.aio_nbytes);
Packit 577717
#endif
Packit 577717
#else
Packit 577717
			printf("aio_write_no_copy: fd %d buffer %lx offset %ld size %d\n",
Packit 577717
				ce->myaiocb.aio_fildes,
Packit 577717
				(long)(ce->myaiocb.aio_buf),
Packit 577717
				ce->myaiocb.aio_offset,
Packit 577717
				ce->myaiocb.aio_nbytes);
Packit 577717
#endif
Packit 577717
			exit(182);
Packit 577717
		}
Packit 577717
	} 
Packit 577717
	else	
Packit 577717
	{
Packit 577717
		return((ssize_t)size);
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
void mbcopy(source, dest, len)
Packit 577717
char *source,*dest;
Packit 577717
size_t len;
Packit 577717
{
Packit 577717
	int i;
Packit 577717
	for(i=0;i
Packit 577717
		*dest++=*source++;
Packit 577717
}