Example #1
0
/*------------------------------------------------------------------------
 * rdsprocess - high-priority background process that repeatedly extracts
 *		an item from the request queue and sends the request to
 *		the remote disk server
 *------------------------------------------------------------------------
 */
void	rdsprocess (
	  struct rdscblk    *rdptr	/* ptr to device control block	*/
	)
{
	struct	rd_msg_wreq msg;	/* message to be sent		*/
					/*  (includes data area)	*/
	struct	rd_msg_rres resp;	/* buffer to hold response	*/
					/*  (includes data area)	*/
	int32	retval;			/* return value from rdscomm	*/
	char	*idto;			/* ptr to ID string copy	*/
	char	*idfrom;		/* ptr into ID string		*/
	struct	rdbuff	*bptr;		/* ptr to buffer at the head of	*/
					/*   the request queue		*/
	struct	rdbuff	*nptr;		/* ptr to next buffer on the	*/
					/*   request queue		*/
	struct	rdbuff	*pptr;		/* ptr to previous buffer	*/
	struct	rdbuff	*qptr;		/* ptr that runs along the	*/
					/*   request queue		*/
	int32	i;			/* loop index			*/

	while (TRUE) {			/* do forever */

	    /* Wait until the request queue contains a node */
	    wait(rdptr->rd_reqsem);
	    bptr = rdptr->rd_rhnext;

	    /* Use operation in request to determine action */

	   switch (bptr->rd_op) {

	   case RD_OP_READ:

		/* Build a read request message for the server */

		msg.rd_type = htons(RD_MSG_RREQ);	/* read request	*/
		msg.rd_status = htons(0);
		msg.rd_seq = 0;		/* rdscomm fills in an entry	*/
		idto = msg.rd_id;
		memset(idto, NULLCH, RD_IDLEN);/* initialize ID to zero	*/
		idfrom = rdptr->rd_id;
		while ( (*idto++ = *idfrom++) != NULLCH ) { /* copy ID	*/
			;
		}

		/* Send the message and receive a response */

		retval = rdscomm((struct rd_msg_hdr *)&msg,
					sizeof(struct rd_msg_rreq),
				 (struct rd_msg_hdr *)&resp,
					sizeof(struct rd_msg_rres),
				  rdptr );

		/* Check response */

		if ( (retval == SYSERR) || (retval == TIMEOUT) ||
				(ntohs(resp.rd_status) != 0) ) {
			panic("Failed to contact remote disk server");
		}

		/* Copy data from the reply into the buffer */

		for (i=0; i<RD_BLKSIZ; i++) {
			bptr->rd_block[i] = resp.rd_data[i];
		}

		/* Unlink buffer from the request queue */

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

		/* Insert buffer in the cache */

		pptr = (struct rdbuff *) &rdptr->rd_chnext;
		nptr = pptr->rd_next;
		bptr->rd_next = nptr;
		bptr->rd_prev = pptr;
		pptr->rd_next = bptr;
		nptr->rd_prev = bptr;

		/* Initialize reference count */

		bptr->rd_refcnt = 1;

		/* Signal the available semaphore */

		signal(rdptr->rd_availsem);

		/* Send a message to waiting process */

		send(bptr->rd_pid, (uint32)bptr);

		/* If other processes are waiting to read the  */
		/*   block, notify them and remove the request */

		qptr = rdptr->rd_rhnext;
		while (qptr != (struct rdbuff *)&rdptr->rd_rtnext) {
			if (qptr->rd_blknum == bptr->rd_blknum) {
				bptr->rd_refcnt++;
				send(qptr->rd_pid,(uint32)bptr);

				/* Unlink request from queue	*/

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

				/* Move buffer to the free list	*/

				qptr->rd_next = rdptr->rd_free;
				rdptr->rd_free = qptr;
				signal(rdptr->rd_availsem);
				break;
			}
			qptr = qptr->rd_next;
		}
		break;

	    case RD_OP_WRITE:

		/* Build a write request message for the server */

		msg.rd_type = htons(RD_MSG_WREQ);	/* write request*/
		msg.rd_blk = bptr->rd_blknum;
		msg.rd_status = htons(0);
		msg.rd_seq = 0;		/* rdscomm fills in an entry	*/
		idto = msg.rd_id;
		memset(idto, NULLCH, RD_IDLEN);/* initialize ID to zero	*/
		idfrom = rdptr->rd_id;
		while ( (*idto++ = *idfrom++) != NULLCH ) { /* copy ID	*/
			;
		}
		for (i=0; i<RD_BLKSIZ; i++) {
			msg.rd_data[i] = bptr->rd_block[i];
		}

		/* Unlink buffer from request queue */

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

		/* Insert buffer in the cache */

		pptr = (struct rdbuff *) &rdptr->rd_chnext;
		nptr = pptr->rd_next;
		bptr->rd_next = nptr;
		bptr->rd_prev = pptr;
		pptr->rd_next = bptr;
		nptr->rd_prev = bptr;

		/* Declare that buffer is eligible for reuse */

		bptr->rd_refcnt = 0;
		signal(rdptr->rd_availsem);

		/* Send the message and receive a response */

		retval = rdscomm((struct rd_msg_hdr *)&msg,
					sizeof(struct rd_msg_wreq),
				 (struct rd_msg_hdr *)&resp,
					sizeof(struct rd_msg_wres),
				  rdptr );

		/* Check response */

		if ( (retval == SYSERR) || (retval == TIMEOUT) ||
				(ntohs(resp.rd_status) != 0) ) {
			panic("failed to contact remote disk server");
		}
		break;

	    case RD_OP_SYNC:

		/* Send a message to the waiting process */

		send(bptr->rd_pid, OK);

		/* Unlink buffer from the request queue */

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

		/* Insert buffer into the free list */

		bptr->rd_next = rdptr->rd_free;
		rdptr->rd_free = bptr;
		signal(rdptr->rd_availsem);
		break;
	   }
	}
}
Example #2
0
/*------------------------------------------------------------------------
 * rdsClose - Close a remote disk device
 *------------------------------------------------------------------------
 */
devcall	rdsClose (
	  struct dentry	*devptr		/* entry in device switch table	*/
	)
{
	struct	rdscblk	*rdptr;		/* ptr to control block entry	*/
	struct	rdbuff	*bptr;		/* ptr to buffer on a list	*/
	struct	rdbuff	*nptr;		/* ptr to next buff on the list	*/
	int32	nmoved;			/* number of buffers moved	*/
	struct	rd_msg_oreq msg;	/* message to be sent		*/
	struct	rd_msg_ores resp;	/* buffer to hold response	*/
	int32	retval;			/* return value from rdscomm	*/
	char	*idto;			/* ptr to ID string copy	*/
	char	*idfrom;		/* pointer into ID string	*/

	/* Device must be open */

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

	/* Request queue must be empty */

	if (rdptr->rd_rhnext != (struct rdbuff *)&rdptr->rd_rtnext) {
		return SYSERR;
	}

	/* Move all buffers from the cache to the free list */

	bptr = rdptr->rd_chnext;
	nmoved = 0;
	while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) {
		nmoved++;

		/* Unlink buffer from cache */

		nptr = bptr->rd_next;
		(bptr->rd_prev)->rd_next = nptr;
		nptr->rd_prev = bptr->rd_prev;

		/* Insert buffer into free list */

		bptr->rd_next = rdptr->rd_free;
	
		rdptr->rd_free = bptr;
		bptr->rd_status = RD_INVALID;

		/* Move to next buffer in the cache */

		bptr = nptr;
	}

	/* Hand-craft an close request message to be sent to the server */

	msg.rd_type = htons(RD_MSG_CREQ);/* Request an open		*/
	msg.rd_status = htons(0);
	msg.rd_seq = 0;			/* rdscomm fills in an entry	*/
	idto = msg.rd_id;
	memset(idto, NULLCH, RD_IDLEN);/* initialize ID to zero bytes	*/
	idfrom = rdptr->rd_id;
	while ( (*idto++ = *idfrom++) != NULLCH ) { /* copy ID to req.	*/
		;
	}

	/* Send message and receive response */

	retval = rdscomm((struct rd_msg_hdr *)&msg,
					sizeof(struct rd_msg_oreq),
			 (struct rd_msg_hdr *)&resp,
					sizeof(struct rd_msg_ores),
				rdptr );

	/* Check response */

	if (retval == SYSERR) {
		return SYSERR;
	} else if (retval == TIMEOUT) {
		kprintf("Timeout during remote file open\n\r");
		return SYSERR;
	} else if (ntohs(resp.rd_status) != 0) {
		return SYSERR;
	}

	/* Set the state to indicate the device is closed */

	rdptr->rd_state = RD_FREE;
	return OK;
}