Пример #1
0
/*------------------------------------------------------------------------
 * rdswrite  -  Write a block to a remote disk
 *------------------------------------------------------------------------
 */
devcall	rdswrite (
	  struct dentry	*devptr,	/* Entry in device switch table	*/
	  char	*buff,			/* Buffer that holds a disk blk	*/
	  int32	blk			/* Block number to write	*/
	)
{
	struct	rdscblk	*rdptr;		/* Pointer to control block	*/
	struct	rdbuff	*bptr;		/* Pointer to buffer on a list	*/
	struct	rdbuff	*pptr;		/* Ptr to previous buff on list	*/
	struct	rdbuff	*nptr;		/* Ptr to next buffer on list	*/
	bool8	found;			/* Was buff found during search?*/

	/* If device not currently in use, report an error */

	rdptr = &rdstab[devptr->dvminor];
	if (rdptr->rd_state != RD_OPEN) {
		return SYSERR;
	}

	/* Ensure rdsprocess is runnning */

	if ( ! rdptr->rd_comruns ) {
		rdptr->rd_comruns = TRUE;
		resume(rdptr->rd_comproc);
	}

	/* If request queue already contains a write request */
	/*    for the block, replace the contents	     */

	bptr = rdptr->rd_rhnext;
	while (bptr != (struct rdbuff *)&rdptr->rd_rtnext) {
		if ( (bptr->rd_blknum == blk) &&
			(bptr->rd_op == RD_OP_WRITE) ) {
			memcpy(bptr->rd_block, buff, RD_BLKSIZ);
			return OK;
		}
		bptr = bptr->rd_next;
	}

	/* Search cache for cached copy of block */

	bptr = rdptr->rd_chnext;
	found = FALSE;
	while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) {
		if (bptr->rd_blknum == blk) {
			if (bptr->rd_refcnt <= 0) {
				pptr = bptr->rd_prev;
				nptr = bptr->rd_next;

				/* Unlink node from cache list and reset*/
				/*   the available semaphore accordingly*/

				pptr->rd_next = bptr->rd_next;
				nptr->rd_prev = bptr->rd_prev;
				semreset(rdptr->rd_availsem,
					semcount(rdptr->rd_availsem) - 1);
				found = TRUE;
			}
			break;
		}
		bptr = bptr->rd_next;
	}

	if ( !found ) {
		bptr = rdsbufalloc(rdptr);
	}

	/* Create a write request */

	memcpy(bptr->rd_block, buff, RD_BLKSIZ);
	bptr->rd_op = RD_OP_WRITE;
	bptr->rd_refcnt = 0;
	bptr->rd_blknum = blk;
	bptr->rd_status = RD_VALID;
	bptr->rd_pid = getpid();

	/* Insert new request into list just before tail */

	pptr = rdptr->rd_rtprev;
	rdptr->rd_rtprev = bptr;
	bptr->rd_next = pptr->rd_next;
	bptr->rd_prev = pptr;
	pptr->rd_next = bptr;

	/* Signal semaphore to start communication process */

	signal(rdptr->rd_reqsem);
	return OK;
}
Пример #2
0
/*------------------------------------------------------------------------
 * rdsRead - Read a block from a remote disk
 *------------------------------------------------------------------------
 */
devcall	rdsRead (
	  struct dentry	*devptr,	/* entry in device switch table	*/
	  char	*buff,			/* buffer to hold disk block	*/
	  int32	blk			/* block number of block to read*/
	)
{
	struct	rdscblk	*rdptr;		/* pointer to control block	*/
	struct	rdbuff	*bptr;		/* ptr to buffer possibly on	*/
					/*  the request list		*/
	struct	rdbuff	*nptr;		/* ptr to "next" node on a	*/
					/*  list			*/
	struct	rdbuff	*pptr;		/* ptr to "previous" node on	*/
					/*  a list			*/
	struct	rdbuff	*cptr;		/* ptr used to walk the cache	*/

	/* If device not currently in use, report an error */

	rdptr = &rdstab[devptr->dvminor];
	if (rdptr->rd_state != RD_OPEN) {
		return SYSERR;
	}

	/* Search the cache for specified block */

	bptr = rdptr->rd_chnext;
	while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) {
		if (bptr->rd_blknum == blk) {
			if (bptr->rd_status == RD_INVALID) {
				break;
			}
			memcpy(buff, bptr->rd_block, RD_BLKSIZ);
			return OK;
		}
		bptr = bptr->rd_next;
	}

	/* Search the request list for most recent occurrence of block */

	bptr = rdptr->rd_rtprev;	/* start at tail of list */

	while (bptr != (struct rdbuff *)&rdptr->rd_rhnext) {
	    if (bptr->rd_blknum == blk)  {

		/* If most recent request for block is write, copy data */

		if (bptr->rd_op == RD_OP_WRITE) {
			memcpy(buff, bptr->rd_block, RD_BLKSIZ);
			return OK;
		}
		break;
	    }
	    bptr = bptr->rd_prev;
	}

	/* Allocate a buffer and add read request to tail of req. queue */

	bptr = rdsbufalloc(rdptr);	
	bptr->rd_op = RD_OP_READ;
	bptr->rd_refcnt = 1;
	bptr->rd_blknum = blk;
	bptr->rd_status = RD_INVALID;
	bptr->rd_pid = getpid();

	/* Insert new request into list just before tail */

	pptr = rdptr->rd_rtprev;
	rdptr->rd_rtprev = bptr;
	bptr->rd_next = pptr->rd_next;
	bptr->rd_prev = pptr;
	pptr->rd_next = bptr;

	/* Prepare to receive message when read completes */

	recvclr();

	/* Signal semaphore to start communication process */

	signal(rdptr->rd_reqsem);

	/* Block to wait for message */

	bptr = (struct rdbuff *)receive();
	if (bptr == (struct rdbuff *)SYSERR) {	
		return SYSERR;
	}
	memcpy(buff, bptr->rd_block, RD_BLKSIZ);
	bptr->rd_refcnt--;
	if (bptr->rd_refcnt <= 0) {

		/* Look for previous item in cache with the same block	*/
		/*    number to see if this item was only being kept	*/
		/*    until pending read completed			*/
				
		cptr = rdptr->rd_chnext;
		while (cptr != bptr) {
			if (cptr->rd_blknum == blk) {

				/* Unlink from cache */

				pptr = bptr->rd_prev;
				nptr = bptr->rd_next;
				pptr->rd_next = nptr;
				nptr->rd_prev = pptr;

				/* Add to the free list */

				bptr->rd_next = rdptr->rd_free;
				rdptr->rd_free = bptr;
			}
		}
	}
	return OK;
}