Path: utzoo!attcan!uunet!seismo!ukma!tut.cis.ohio-state.edu!gem.mps.ohio-state.edu!uwm.edu!bionet!ames!attctc!msm
From: msm@attctc.Dallas.TX.US (Michael Mattone)
Newsgroups: comp.os.minix
Subject: Fixing 7K pipes again
Keywords: pipes MINIX FS
Message-ID: <9507@attctc.Dallas.TX.US>
Date: 28 Sep 89 03:10:25 GMT
Organization: The Unix(R) Connection, Dallas, Texas
Lines: 199


A few weeks ago, Bruce Evans (evans@ditsyda.oz.au), mentioned a
fix I had posted about a year ago that was supposed to fix the
limit of 7K when writing to a pipe.  He also mentioned that it
had a bug that caused blocks to be skipped.  Well, I took a look
at FS with my patches again, and believe I have fixed this bug.

I believe the bug can be fixed by adding one line to the fs/read.c
file before the "goto bigpipe" statement (from my original posting):

	if (nbytes > xbytes) {
		f->filp_pos = position;	/* BUG fixed - add this line */
		goto bigpipe;		/* more in a pipe to do */
	}

I'm enclosing my patches again in case there are others interested.
I'd really like to hear if anyone tries this and of any other bugs they
might find.

----------------------------------cut here---------------------------------
echo x - fproc.h.cdiff
sed '/^X/s///' > fproc.h.cdiff << '/'
X*** fproc.h	Tue Jun 28 22:28:05 1988
X--- new/fproc.h	Mon Aug 15 02:12:25 1988
X***************
X*** 22,27 ****
X--- 22,28 ----
X    char fp_task;			/* which task is proc suspended on */
X    int fp_pid;			/* process id */
X    int fp_pgrp;			/* process group */
X+   int fp_tot_io;		/* total cum_io for pipes */
X  } fproc[NR_PROCS];
X  
X  /* Field values. */
/
echo x - main.c.cdiff
sed '/^X/s///' > main.c.cdiff << '/'
X*** main.c	Tue Jun 28 22:28:13 1988
X--- new/main.c	Mon Aug 15 02:08:10 1988
X***************
X*** 110,115 ****
X--- 110,116 ----
X  
X    who = m.m_source;
X    fs_call = m.m_type;
X+   fproc[who].fp_tot_io = 0;		/* in case we do a pipe */
X  }
X  
X  
/
echo x - pipe.c.cdiff
sed '/^X/s///' > pipe.c.cdiff << '/'
X*** pipe.c	Sat Jul 16 20:34:19 1988
X--- new/pipe.c	Tue Nov  1 01:26:47 1988
X***************
X*** 21,26 ****
X--- 21,27 ----
X  #include "../h/signal.h"
X  #include "const.h"
X  #include "type.h"
X+ #include "dev.h"
X  #include "file.h"
X  #include "fproc.h"
X  #include "glo.h"
X***************
X*** 81,91 ****
X  /*===========================================================================*
X   *				pipe_check				     *
X   *===========================================================================*/
X! PUBLIC int pipe_check(rip, rw_flag, bytes, position)
X  register struct inode *rip;	/* the inode of the pipe */
X  int rw_flag;			/* READING or WRITING */
X  register int bytes;		/* bytes to be read or written (all chunks) */
X  register file_pos position;	/* pointer to current file position */
X  {
X  /* Pipes are a little different.  If a process reads from an empty pipe for
X   * which a writer still exists, suspend the reader.  If the pipe is empty
X--- 82,93 ----
X  /*===========================================================================*
X   *				pipe_check				     *
X   *===========================================================================*/
X! PUBLIC int pipe_check(rip, rw_flag, bytes, position, xbytes)
X  register struct inode *rip;	/* the inode of the pipe */
X  int rw_flag;			/* READING or WRITING */
X  register int bytes;		/* bytes to be read or written (all chunks) */
X  register file_pos position;	/* pointer to current file position */
X+ int  *xbytes;
X  {
X  /* Pipes are a little different.  If a process reads from an empty pipe for
X   * which a writer still exists, suspend the reader.  If the pipe is empty
X***************
X*** 110,122 ****
X  	}
X    } else {
X  	/* Process is writing to a pipe. */
X- 	if (bytes > PIPE_SIZE) return(EFBIG);
X  	if (find_filp(rip, R_BIT) == NIL_FILP) {
X  		/* Tell kernel to generate a SIGPIPE signal. */
X  		sys_kill((int)(fp - fproc), SIGPIPE);
X  		return(EPIPE);
X  	}
X  
X  	if (position + bytes > PIPE_SIZE) {
X  		suspend(XPIPE);	/* stop writer -- pipe full */
X  		return(0);
X--- 112,128 ----
X  	}
X    } else {
X  	/* Process is writing to a pipe. */
X  	if (find_filp(rip, R_BIT) == NIL_FILP) {
X  		/* Tell kernel to generate a SIGPIPE signal. */
X  		sys_kill((int)(fp - fproc), SIGPIPE);
X  		return(EPIPE);
X  	}
X  
X+ 	if (bytes > PIPE_SIZE) {
X+ 		if ((*xbytes = PIPE_SIZE - position) > 0)
X+ 			bytes = *xbytes;
X+ 	}
X+ 
X  	if (position + bytes > PIPE_SIZE) {
X  		suspend(XPIPE);	/* stop writer -- pipe full */
X  		return(0);
/
echo x - read.c.cdiff
sed '/^X/s///' > read.c.cdiff << '/'
X*** read.c	Fri Sep 30 03:15:42 1988
X--- new/read.c	Wed Sep 27 19:23:04 1989
X***************
X*** 54,59 ****
X--- 54,60 ----
X    register unsigned off, cum_io;
X    file_pos position;
X    int r, chunk, mode_word, usr, seg, block_spec, char_spec;
X+   int  xbytes;
X    struct filp *wf;
X    extern struct super_block *get_super();
X    extern struct filp *find_filp(), *get_filp();
X***************
X*** 111,124 ****
X  		if (position > f_size) clear_zone(rip, f_size, 0);
X  	}
X  
X! 	/* Pipes are a little different.  Check. */
X! 	if (rip->i_pipe &&
X! 	    (r = pipe_check(rip, rw_flag, nbytes, position)) <= 0)
X! 		return r;
X! 	/* Split the transfer into chunks that don't span two blocks. */
X! 	while (nbytes != 0) {
X! 		off = position % BLOCK_SIZE;	/* offset within a block */
X! 		chunk = MIN(nbytes, BLOCK_SIZE - off);
X  		if (chunk < 0) chunk = BLOCK_SIZE - off;
X  
X  		if (rw_flag == READING || (block_spec && rw_flag == WRITING)) {
X--- 112,127 ----
X  		if (position > f_size) clear_zone(rip, f_size, 0);
X  	}
X  
X! bigpipe:
X! 	xbytes = nbytes;
X! 	/* Pipes are a little different.  Check. */
X! 	if (rip->i_pipe &&
X! 	    (r = pipe_check(rip, rw_flag, nbytes, position, &xbytes)) <= 0)
X! 		return r;
X! 	/* Split the transfer into chunks that don't span two blocks. */
X! 	while (xbytes != 0) {
X! 		off = position % BLOCK_SIZE;	/* offset within a block */
X! 		chunk = MIN(xbytes, BLOCK_SIZE - off);
X  		if (chunk < 0) chunk = BLOCK_SIZE - off;
X  
X  		if (rw_flag == READING || (block_spec && rw_flag == WRITING)) {
X***************
X*** 136,141 ****
X--- 139,145 ----
X  		/* Update counters and pointers. */
X  		buffer += chunk;	/* user buffer address */
X  		nbytes -= chunk;	/* bytes yet to be read */
X+ 		xbytes -= chunk;	/* for pipes */
X  		cum_io += chunk;	/* bytes read so far */
X  		position += chunk;	/* position within the file */
X  	}
X***************
X*** 148,153 ****
X--- 152,165 ----
X  		rip->i_modtime = clock_time();
X  		rip->i_dirt = DIRTY;
X  	}
X+ 	if (r == OK && rip->i_pipe) {
X+ 		fp->fp_tot_io += cum_io;
X+ 		if (nbytes > xbytes) {
X+ 			f->filp_pos = position;	/* just in case */
X+ 			goto bigpipe;		/* more in a pipe to do */
X+ 		}
X+ 		cum_io = fp->fp_tot_io;		/* for accurate count */
X+ 	}
X    } else {
X  	if (rip->i_pipe && position >= rip->i_size) {
X  		/* Reset pipe pointers. */
/