Exemple #1
0
/*
 * _mr_locsw_set(mr_info, usersw, count) finds an unused entry in the
 *	structure describing outstanding asynchronous I/O
 *	requests, and initializes its values.
 * Parameters:  usersw - address of the status word passed in from the
 *			upper level. 
 *		count - number of BITS already completed for this request.
 * 
 * Returns: pointer to the _lociosw structure to be used.
 *          NULL if error occurred
 */
_lociosw *
_mr_locsw_set(
	struct mr_f *mr_info, 
	struct ffsw *usersw, 
	int count)
{
_lociosw *locptr;
int i;
struct _loclink *loclink;

	MEM_LOCK(&(mr_info->locsw_lock)); 
	if (mr_info->loclist == NULL) {
		mr_info->loclist = (struct _loclink *)calloc(1, sizeof(struct _loclink)); 
		if (mr_info->loclist == NULL)   {
			goto nomem;
		} 
	} 
	loclink = mr_info->loclist;
	locptr = loclink->loc_first;
	for (;;) {
		for (i = 0; i < _FSSASYNUM ; i++) {
       			if (locptr->user_sw == NULL) {
				goto found ;
			}
			else
				locptr++;
		}
		if (loclink->loc_nxt == NULL) {
			loclink->loc_nxt =  (struct _loclink *)calloc(1, sizeof(struct _loclink));
			if (loclink->loc_nxt == NULL)   {
				goto nomem;
			}
		}
		loclink = loclink->loc_nxt;
		locptr = loclink->loc_first;
	}
found:
	locptr->user_sw = usersw;
	locptr->sw_count = count;
	CLRFFSTAT(*usersw);
	memset(&locptr->local_sw , 0, sizeof(struct ffsw));
#if     defined(_ADDR64) || defined(__mips)
	usersw->sw_sptr = (void *)locptr;
#else
	usersw->sw_sptr = (int)locptr;
#endif
	MEM_UNLOCK(&(mr_info->locsw_lock));
	return(locptr);
nomem:
	MEM_UNLOCK(&(mr_info->locsw_lock));
	return(NULL);
}
Exemple #2
0
int
_er90b_writea(struct fdinfo *fio, bitptr bufptr, int nbytes, 
	struct ffsw *retstat, int fulp, int *ubc)
{
int ret = 0;
char *buf;
ER90BYT *f;
int zero = 0;
struct ffsw dumstat;

	buf = BPTR2CP(bufptr);
	if ((BPBITOFF(bufptr) & 7) != 0 || *ubc != 0)
		ERETURN(retstat, FDC_ERR_UBC, 0);

	if (fio->rwflag == POSITIN) {
		f = (ER90BYT *)fio->lyr_info;
		if (f->tpos) {
			ret = _tape_tpwait(f->fd, &(f->tpos));
			if (ret < 0)
				ERETURN(retstat, errno, 0);
		}		
	}
	else if (fio->rwflag == READIN) {
		/* write after read requires position to zero */
		ret = _er90b_pos(fio, FP_RSEEK, &zero, 1,
			&dumstat);
		if (ret < 0) {
			*retstat = dumstat;
			return(ERR);
		}
	}

	if (nbytes > 0) {
		CLRFFSTAT(*retstat);	/* flag async in progress */
		ret=   writea(fio->realfd, buf, nbytes,
			(struct iosw *)retstat, 0);
		if (ret < 0)
			ERETURN(retstat, errno, 0);
	}
	else if (nbytes < 0) {
		ERETURN(retstat, FDC_ERR_REQ, 0);
	}
	else {	/* nbytes == 0 */
		retstat->sw_flag = 1;
		FFSTAT(*retstat) = FFCNT; /* I/O is done, and other stat */
					/* fields are already set. */
	}
	fio->rwflag = WRITIN;
	return (ret);
}
Exemple #3
0
/*
 * _cch_wrabuf
 *
 * Flushes to the underlying ffio layer one or more cache page buffers.  
 * The ffsw structure pointed to by stat receives the synchronous or
 * asynchronous completion status.
 * If the lastdata or firstdata fields in the buffer control block
 * are non-zero, then nblk had better be 1. In this case, we write only
 * the part of the buffer between firstdata and lastdata.
 *
 * When nblk > 1, _cch_wrabuf assumes that all page buffers get written to
 * contiguous parts of the file.
 *
 * Return value:
 *
 *	On normal completion 0 is returned. -1 is returned if an error is
 *	encountered, with the status set in stat.
 *
 * Side effects:
 *
 *	The CCH_DIRTY bit is cleared for all affected buffers.  If called
 *	in asynchronous mode, the buffers are placed in CCH_WRITING state.
 */
_cch_wrabuf(
struct cch_f	*cch_info,	/* cache info */
struct fdinfo	*llfio,		/* fdinfo pointer for underlying layer */
struct cch_buf	*bc,		/* buffer control block */
int		bytes,		/* number of bytes per page buffer */
off_t		bytoff,		/* byte offset within file */
int64		nblk,		/* number of contiguous buffers to flush */
off_t		*eof,		/* on input, contains the bit size of the 
				 * underlying file layer.  On output, this 
				 * size is updated if the file is extended. */
char		syncasync,	/* 's' for sync request, 'a' for async */
struct ffsw	*stat		/* io completion status structure */
)
{
	int i;
	ssize_t ret;
	int ubc;
	size_t tbytes, bytleft;
	size_t saveamt = 0;
	off_t end_of_data;	
	struct fflistreq list_array[1];
	char *bufptr;

	CCH_DEBUG(("_cch_wrabuf EN: bytes=%d (0%o)  bytoff=%d (0%o) \n",
		bytes,bytes,bytoff,bytoff));
	if (bc->firstdata || bc->lastdata) {
		assert(nblk <= 1);
		tbytes = (size_t)((bc->lastdata - bc->firstdata)/8);
		bytoff = bytoff + bc->firstdata/8;
		bufptr = BPTR2CP(bc->buf) + bc->firstdata/8;
	}
	else {
		tbytes = bytes * nblk;
		bufptr = BPTR2CP(bc->buf);
	}

#ifdef __mips
	if (cch_info->odirect && tbytes > cch_info->maxiosize){
		syncasync = 's';
	}
#endif
	ubc = 0;
	if (syncasync == 'a') {
		/*
		 * Seek to proper location
		 */
		if (XRCALL(llfio,seekrtn) llfio, bytoff, SEEK_SET, stat) == ERR)
			return(ERR);
		/*
		 * Start an asynchronous write.
		 */
		CLRFFSTAT(bc->sw);
		ret = XRCALL(llfio,writeartn) llfio, CPTR2BP(bufptr), tbytes,
					      &bc->sw, PARTIAL, &ubc);
		if (ret == ERR) {
			ERETURN(stat,bc->sw.sw_error,0);
		}
	
		bc[0].lnkcnt = nblk;			/* cnt of linked bufs */
		for (i=0; i<nblk; i++) {
			bc[i].flags |= CCH_WRITING;	/* update buffer stat */
			bc[i].flags &= ~CCH_DIRTY;	/* clear dirty flag */
			bc[i].lnk    = i;		/* chain several bufs */
		}
	}
	else {
Exemple #4
0
/*
 * _cca_listio
 *
 *	Issue a listio request for the cachea layer.
 *
 * Return Value:
 *
 *	On success, nreq is returned, and the contents of the stat structure are
 *	unspecified.
 *
 *	If an error in setup is encountered, stat is set as follows:
 *
 *		stat->sw_error	= error code
 *		stat->sw_stat	= FFERR
 *		stat->sw_flag	= 1
 *		stat->sw_count	= 0
 *
 *	If an error in I/O request I is detected, the list[I].li_stat
 *	structure will be set as follows:
 *
 *		list[I].li_stat->sw_error	= error code
 *		list[I].li_stat->sw_flag	= 1
 */
_cca_listio( 
int			cmd,		/* LC_START or LC_START */
struct fflistreq	*list,		/* list of requests (see fflistio) */
int			nreq,		/* number of requests */
struct ffsw		*stat)		/* status structure */
{
	int	ret;
	int	i;
	int	n_handled;
	int	status;
	int	zero;
	int	pos;
	bitptr buf;
	struct ffsw	loc_stat;
	struct fdinfo	*fio;
	struct fdinfo	*oldfio;
	struct cca_f *cca_info;

	n_handled = 0;

	oldfio = GETIOB(list[0].li_fildes);
	cca_info = (struct cca_f *)oldfio->lyr_info;
	for (i = 0; i < nreq; i++) {

		fio = GETIOB(list[i].li_fildes);
		if (fio != oldfio) {
			_SETERROR(list[i].li_status, FDC_ERR_LSTIO, 0);
			continue;
		}
		if ( list[i].li_signo != 0 ) {
			_SETERROR(list[i].li_status, FDC_ERR_REQ, 0);
			continue;
		}

		cca_info = (struct cca_f *)fio->lyr_info;
		CLRFFSTAT(*(list[i].li_status));

		SET_BPTR(buf, CPTR2BP(list[i].li_buf));
		if ( list[i].li_nstride > 1 ) {

			status = _ffcompound(&list[i]);
			if (status == 0)
				n_handled++;
			continue;
		}
		if ( list[i].li_flags == LF_LSEEK ) {
			pos = _cca_seek(fio, list[i].li_offset, SEEK_SET,
					   &loc_stat);
			if (pos == -1) {
				*list[i].li_status = loc_stat;
				continue;
			}
		}
		else if (list[i].li_flags != 0) {
			_SETERROR(list[i].li_status, FDC_ERR_REQ, 0);
		}

		zero = 0;
		status = 0;
		if ( cmd == LC_START ) {
			if ( list[i].li_opcode == LO_READ ) {
				status = _cca_reada(fio, buf, list[i].li_nbyte,
				    		    list[i].li_status, FULL,
						    &zero );
			}
			else if (list[i].li_opcode == LO_WRITE ) {
				status = _cca_writea(fio, buf, list[i].li_nbyte,
				    		     list[i].li_status, FULL,
						     &zero );
			}
			else {
				_SETERROR(list[i].li_status, FDC_ERR_REQ, 0);
			}
		}
		else if ( cmd == LC_WAIT ) {
			if ( list[i].li_opcode == LO_READ ) {
				status = _cca_read(fio, buf, list[i].li_nbyte,
				    		   list[i].li_status, FULL,
						   &zero );
			}
			else if (list[i].li_opcode == LO_WRITE ) {
				status = _cca_write(fio, buf, list[i].li_nbyte,
				    		    list[i].li_status, FULL,
						    &zero );
			}
			else {
				_SETERROR(list[i].li_status, FDC_ERR_REQ, 0);
			}
		}
		else {
			_SETERROR(list[i].li_status, FDC_ERR_REQ, 0);
		}
		if (status == ERR) {
			continue;
		}

		n_handled++;
	}

	return( n_handled );
}
Exemple #5
0
/*
 *
 * Description:
 *	writes nbytes bytes, with *ubc unused bits, from bufptr to
 *	the next lower layer.
 * Parameters:
 *      fio     - Pointer to fdinfo block
 *	bufptr	- bit pointer to user's data
 *	nbytes	- Number of bytes to be written
 *	stat	- pointer to status return word
 *	fulp	- full or partial write mode flag
 *	ubc	- pointer to unused bit count
 * Returns:
 *	number of bytes written
 *	-1 if error
 */
ssize_t
_sqb_write(
struct fdinfo *fio,
bitptr bufptr,
size_t nbytes,
struct ffsw *stat,
int fulp,
int *ubc)
{
	int ret;
	int bs,  btomove;
	uint64 nbits;
	ssize_t moved;
	struct sqb_f *sqb_info;
	struct fdinfo *llfio;
	struct ffsw locstat;
	struct sqbio *sqbptr;
	int zero = 0;

	nbits = ((uint64)nbytes << 3) - *ubc;

	sqb_info = (struct sqb_f *)fio->lyr_info;
	llfio = fio->fioptr;

	moved = 0;

	if (fio->rwflag == READIN || fio->rwflag == POSITIN) {
		/* synchronize physical position with logical position */
		if (_sqb_sync(fio, &locstat, 1) < 0) {
			goto erret;
		}
	}

	fio->rwflag = WRITIN;
	bs = sqb_info->bufsiz>>3;
	sqbptr = sqb_info->sqbio_cur;
	while (nbits != 0) {
		if (sqbptr->status == IOACTIVE) {
			/* wait for the outstanding asynch i/o to complete */
			while (sqbptr->iostat.sw_flag == 0 || 
				sqbptr->iostat.sw_stat == 0) {
				ret = XRCALL(llfio,fcntlrtn) llfio, FC_RECALL, 
					&(sqbptr->iostat), &locstat);
				if (ret < 0) {
					goto erret;
				}
			}
			if (sqbptr->iostat.sw_error != 0) {
				ERETURN(stat, sqbptr->iostat.sw_error, 0);
			}
			if (sqbptr->iostat.sw_count != sqbptr->_iowritten) {
				ERETURN(stat, FDC_ERR_WRTERR, 0);
			}
			sqbptr->status = EMPTY;
			sqbptr->_cnt = sqb_info->bufsiz;
			CLRFFSTAT(sqbptr->iostat);
		}
		if (sqbptr->status == EMPTY) {
			sqbptr->_cnt = sqb_info->bufsiz;
		}
	
/*
 *		Move data from user to buffer
 */
		btomove = MIN(nbits, sqbptr->_cnt);
		MOV_BITS(sqb_info->_ptr, bufptr, btomove);
		SET_BPTR(bufptr, INC_BPTR(bufptr, btomove));
		nbits -= btomove;
		sqbptr->_cnt -= btomove;
		sqbptr->status = IODATA;
		if (sqbptr->_cnt == 0) {
			/* no room left in this buffer; start I/O on it */
			CLRFFSTAT(sqbptr->iostat);
			sqbptr->_iowritten = bs;
			if( XRCALL(llfio, writeartn) llfio,
				sqbptr->_base,(size_t) bs, &(sqbptr->iostat),
				FULL, &zero) < 0) {
				ERETURN(stat, sqbptr->iostat.sw_error,
				 (moved +7) >> 3);
			}
			sqbptr->status = IOACTIVE;
			sqb_info->sqbio_cur = sqb_info->sqbio_cur->nxt;
			sqbptr = sqb_info->sqbio_cur;
			sqb_info->_ptr = sqb_info->sqbio_cur->_base;
		}
		else {
Exemple #6
0
int
_sqb_pos(struct fdinfo *fio, int cmd, long *arg, int len, struct ffsw *stat)
{
int ret = 0;
struct sqb_f *sqb_info;
struct sqbio *sqbptr;
struct sqbio *sqborig;
struct sqbio *s;
struct fdinfo *llfio;
int found = 0;
int nbits;
int sync = -1;

	llfio = fio->fioptr;
	sqb_info = (struct sqb_f *)fio->lyr_info;

	if (fio->rwflag == WRITIN) {
		/* flush buffers and wait for outstanding I/O to finish. */
		if (_sqb_flush(fio, stat) < 0) {
			return(ERR);
		}
	}

	switch(cmd) {
/* For now, this is not supported on SGI systems. */
/* We need to work out what "arg" should be. */
#if	!defined(__mips) && !defined(_LITTLE_ENDIAN)
		case FP_RSEEK:
			if ((fio->rwflag == READIN) || 
			   (fio->rwflag == POSITIN)) {
			   if (*arg < 0) {
				/* Seeking backwards */
				/* Are we seeking within the current */
				/* buffer? */
				sqbptr = sqb_info->sqbio_cur;
				if (sqbptr->status == IOACTIVE) {
				   while (sqbptr->iostat.sw_flag == 0 ||
					sqbptr->iostat.sw_stat == 0) {
					ret = XRCALL(llfio,fcntlrtn) llfio,
					FC_RECALL, &(sqbptr->iostat), stat);
					if (ret < 0) {
						return(ERR);
					}
				   }
				   if (FFSTAT(sqbptr->iostat) == FFERR) {
					ERETURN(stat, sqbptr->iostat.sw_error,0);
				   }
				   sqbptr->_cnt = sqbptr->iostat.sw_count<<3;
				   sqbptr->status = IODATA;
				}
				if (sqbptr->status == IODATA) {
					nbits = -(*arg); /* convert to positive */
					nbits = nbits<<3;
					if (nbits <=
					 SUBT_BPTR(sqb_info->_ptr,sqbptr->_base)){
						SET_BPTR(sqb_info->_ptr,
						 INC_BPTR(sqb_info->_ptr,-nbits));
						sqbptr->_cnt += nbits;
						break;
					  }
				}
			   }
			   else {
				/* seeking forward */
				/* Any chance that the position would be in */
				/* our buffers? */
				nbits = *arg << 3;
				if (nbits > sqb_info->nbuf * sqb_info->bufsiz){
					/* won't be in any of the buffers */
					goto a1;
				}
				sqbptr = sqb_info->sqbio_cur;
				sqborig = sqbptr;
				do {
				   if (sqbptr->status == IOACTIVE) {
				      while (sqbptr->iostat.sw_flag == 0 ||
					sqbptr->iostat.sw_stat == 0) {
				   	   ret = XRCALL(llfio,fcntlrtn) llfio,
					   FC_RECALL, &(sqbptr->iostat), stat);
					   if (ret < 0) {
						return(ERR);
					   }
				      }
				      if (FFSTAT(sqbptr->iostat) == FFERR) {
					ERETURN(stat, sqbptr->iostat.sw_error,0);
				      }
				      sqbptr->_cnt = sqbptr->iostat.sw_count<<3;
				      sqbptr->status = IODATA;
				   }
				   if (sqbptr->status == IODATA) {
					if (nbits <= sqbptr->_cnt) {
						/* Desired position is in this buffer */
						sqbptr->_cnt -= nbits;
						/* Clear out buffers that preceeded this */
						s = sqborig;
						for (; s != sqbptr; s= s->nxt) {
							s->status = EMPTY;
							CLRFFSTAT(s->iostat);
						}
						sqb_info->sqbio_cur = sqbptr;
						if (sqbptr != sqborig)
							sqb_info->_ptr = sqbptr->_base;
						SET_BPTR(sqb_info->_ptr,
						 INC_BPTR(sqb_info->_ptr,nbits));
						found = 1;
						break;
					}
					else {
						nbits -= sqbptr->_cnt;
					}
				   }
				   else
					goto a1;	/* all out of data */
				   sqbptr = sqbptr->nxt;
				} while (sqbptr != sqborig);
			   }
			   }