1433d6423SLionel Sambuc /* This file contains the heart of the mechanism used to read (and write)
2433d6423SLionel Sambuc * files. Read and write requests are split up into chunks that do not cross
3433d6423SLionel Sambuc * block boundaries. Each chunk is then processed in turn. Reads on special
4433d6423SLionel Sambuc * files are also detected and handled.
5433d6423SLionel Sambuc *
6433d6423SLionel Sambuc * The entry points into this file are
7433d6423SLionel Sambuc * do_read: perform the READ system call by calling read_write
8433d6423SLionel Sambuc * do_getdents: read entries from a directory (GETDENTS)
9433d6423SLionel Sambuc * read_write: actually do the work of READ and WRITE
10433d6423SLionel Sambuc *
11433d6423SLionel Sambuc */
12433d6423SLionel Sambuc
13433d6423SLionel Sambuc #include "fs.h"
14433d6423SLionel Sambuc #include <minix/callnr.h>
15433d6423SLionel Sambuc #include <minix/com.h>
16433d6423SLionel Sambuc #include <minix/u64.h>
17433d6423SLionel Sambuc #include <minix/vfsif.h>
18433d6423SLionel Sambuc #include <assert.h>
19433d6423SLionel Sambuc #include <sys/dirent.h>
20433d6423SLionel Sambuc #include <fcntl.h>
21433d6423SLionel Sambuc #include <unistd.h>
22433d6423SLionel Sambuc #include "file.h"
23433d6423SLionel Sambuc #include "vnode.h"
24433d6423SLionel Sambuc #include "vmnt.h"
25433d6423SLionel Sambuc
26433d6423SLionel Sambuc
27433d6423SLionel Sambuc /*===========================================================================*
28433d6423SLionel Sambuc * do_read *
29433d6423SLionel Sambuc *===========================================================================*/
do_read(void)30433d6423SLionel Sambuc int do_read(void)
31433d6423SLionel Sambuc {
32232819ddSDavid van Moolenbroek
33232819ddSDavid van Moolenbroek /*
34232819ddSDavid van Moolenbroek * This field is currently reserved for internal usage only, and must be set
35232819ddSDavid van Moolenbroek * to zero by the caller. We may use it for future SA_RESTART support just
36232819ddSDavid van Moolenbroek * like we are using it internally now.
37232819ddSDavid van Moolenbroek */
38232819ddSDavid van Moolenbroek if (job_m_in.m_lc_vfs_readwrite.cum_io != 0)
39232819ddSDavid van Moolenbroek return(EINVAL);
40232819ddSDavid van Moolenbroek
41433d6423SLionel Sambuc return(do_read_write_peek(READING, job_m_in.m_lc_vfs_readwrite.fd,
42433d6423SLionel Sambuc job_m_in.m_lc_vfs_readwrite.buf, job_m_in.m_lc_vfs_readwrite.len));
43433d6423SLionel Sambuc }
44433d6423SLionel Sambuc
45433d6423SLionel Sambuc
46433d6423SLionel Sambuc /*===========================================================================*
47433d6423SLionel Sambuc * lock_bsf *
48433d6423SLionel Sambuc *===========================================================================*/
lock_bsf(void)49433d6423SLionel Sambuc void lock_bsf(void)
50433d6423SLionel Sambuc {
51433d6423SLionel Sambuc struct worker_thread *org_self;
52433d6423SLionel Sambuc
53433d6423SLionel Sambuc if (mutex_trylock(&bsf_lock) == 0)
54433d6423SLionel Sambuc return;
55433d6423SLionel Sambuc
56433d6423SLionel Sambuc org_self = worker_suspend();
57433d6423SLionel Sambuc
58433d6423SLionel Sambuc if (mutex_lock(&bsf_lock) != 0)
59433d6423SLionel Sambuc panic("unable to lock block special file lock");
60433d6423SLionel Sambuc
61433d6423SLionel Sambuc worker_resume(org_self);
62433d6423SLionel Sambuc }
63433d6423SLionel Sambuc
64433d6423SLionel Sambuc /*===========================================================================*
65433d6423SLionel Sambuc * unlock_bsf *
66433d6423SLionel Sambuc *===========================================================================*/
unlock_bsf(void)67433d6423SLionel Sambuc void unlock_bsf(void)
68433d6423SLionel Sambuc {
69433d6423SLionel Sambuc if (mutex_unlock(&bsf_lock) != 0)
70433d6423SLionel Sambuc panic("failed to unlock block special file lock");
71433d6423SLionel Sambuc }
72433d6423SLionel Sambuc
73433d6423SLionel Sambuc /*===========================================================================*
74433d6423SLionel Sambuc * check_bsf *
75433d6423SLionel Sambuc *===========================================================================*/
check_bsf_lock(void)76433d6423SLionel Sambuc void check_bsf_lock(void)
77433d6423SLionel Sambuc {
78433d6423SLionel Sambuc int r = mutex_trylock(&bsf_lock);
79433d6423SLionel Sambuc
80433d6423SLionel Sambuc if (r == -EBUSY)
81433d6423SLionel Sambuc panic("bsf_lock locked");
82433d6423SLionel Sambuc else if (r != 0)
83433d6423SLionel Sambuc panic("bsf_lock weird state");
84433d6423SLionel Sambuc
85433d6423SLionel Sambuc /* r == 0 */
86433d6423SLionel Sambuc unlock_bsf();
87433d6423SLionel Sambuc }
88433d6423SLionel Sambuc
89433d6423SLionel Sambuc /*===========================================================================*
90433d6423SLionel Sambuc * actual_read_write_peek *
91433d6423SLionel Sambuc *===========================================================================*/
actual_read_write_peek(struct fproc * rfp,int rw_flag,int fd,vir_bytes buf,size_t nbytes)92232819ddSDavid van Moolenbroek int actual_read_write_peek(struct fproc *rfp, int rw_flag, int fd,
93232819ddSDavid van Moolenbroek vir_bytes buf, size_t nbytes)
94433d6423SLionel Sambuc {
95433d6423SLionel Sambuc /* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
96433d6423SLionel Sambuc struct filp *f;
97433d6423SLionel Sambuc tll_access_t locktype;
98433d6423SLionel Sambuc int r;
99433d6423SLionel Sambuc int ro = 1;
100433d6423SLionel Sambuc
101433d6423SLionel Sambuc if(rw_flag == WRITING) ro = 0;
102433d6423SLionel Sambuc
103433d6423SLionel Sambuc locktype = rw_flag == WRITING ? VNODE_WRITE : VNODE_READ;
104232819ddSDavid van Moolenbroek if ((f = get_filp2(rfp, fd, locktype)) == NULL)
105433d6423SLionel Sambuc return(err_code);
106433d6423SLionel Sambuc
107433d6423SLionel Sambuc assert(f->filp_count > 0);
108433d6423SLionel Sambuc
109433d6423SLionel Sambuc if (((f->filp_mode) & (ro ? R_BIT : W_BIT)) == 0) {
110433d6423SLionel Sambuc unlock_filp(f);
111433d6423SLionel Sambuc return(EBADF);
112433d6423SLionel Sambuc }
113232819ddSDavid van Moolenbroek if (nbytes == 0) {
114433d6423SLionel Sambuc unlock_filp(f);
115433d6423SLionel Sambuc return(0); /* so char special files need not check for 0*/
116433d6423SLionel Sambuc }
117433d6423SLionel Sambuc
118232819ddSDavid van Moolenbroek r = read_write(rfp, rw_flag, fd, f, buf, nbytes, who_e);
119433d6423SLionel Sambuc
120433d6423SLionel Sambuc unlock_filp(f);
121433d6423SLionel Sambuc return(r);
122433d6423SLionel Sambuc }
123433d6423SLionel Sambuc
124433d6423SLionel Sambuc /*===========================================================================*
125433d6423SLionel Sambuc * do_read_write_peek *
126433d6423SLionel Sambuc *===========================================================================*/
do_read_write_peek(int rw_flag,int fd,vir_bytes buf,size_t nbytes)127232819ddSDavid van Moolenbroek int do_read_write_peek(int rw_flag, int fd, vir_bytes buf, size_t nbytes)
128433d6423SLionel Sambuc {
129232819ddSDavid van Moolenbroek return actual_read_write_peek(fp, rw_flag, fd, buf, nbytes);
130433d6423SLionel Sambuc }
131433d6423SLionel Sambuc
132433d6423SLionel Sambuc /*===========================================================================*
133433d6423SLionel Sambuc * read_write *
134433d6423SLionel Sambuc *===========================================================================*/
read_write(struct fproc * rfp,int rw_flag,int fd,struct filp * f,vir_bytes buf,size_t size,endpoint_t for_e)135232819ddSDavid van Moolenbroek int read_write(struct fproc *rfp, int rw_flag, int fd, struct filp *f,
136433d6423SLionel Sambuc vir_bytes buf, size_t size, endpoint_t for_e)
137433d6423SLionel Sambuc {
138433d6423SLionel Sambuc register struct vnode *vp;
139433d6423SLionel Sambuc off_t position, res_pos;
1403c8950ccSBen Gras size_t cum_io, res_cum_io;
1413c8950ccSBen Gras size_t cum_io_incr;
142433d6423SLionel Sambuc int op, r;
143433d6423SLionel Sambuc dev_t dev;
144433d6423SLionel Sambuc
145433d6423SLionel Sambuc position = f->filp_pos;
146433d6423SLionel Sambuc vp = f->filp_vno;
147433d6423SLionel Sambuc r = OK;
148433d6423SLionel Sambuc cum_io = 0;
149433d6423SLionel Sambuc
150433d6423SLionel Sambuc assert(rw_flag == READING || rw_flag == WRITING || rw_flag == PEEKING);
151433d6423SLionel Sambuc
152433d6423SLionel Sambuc if (size > SSIZE_MAX) return(EINVAL);
153433d6423SLionel Sambuc
154433d6423SLionel Sambuc if (S_ISFIFO(vp->v_mode)) { /* Pipes */
155433d6423SLionel Sambuc if(rw_flag == PEEKING) {
156433d6423SLionel Sambuc printf("read_write: peek on pipe makes no sense\n");
157433d6423SLionel Sambuc return EINVAL;
158433d6423SLionel Sambuc }
159232819ddSDavid van Moolenbroek assert(fd != -1);
160232819ddSDavid van Moolenbroek op = (rw_flag == READING ? VFS_READ : VFS_WRITE);
161232819ddSDavid van Moolenbroek r = rw_pipe(rw_flag, for_e, f, op, fd, buf, size, 0 /*cum_io*/);
162433d6423SLionel Sambuc } else if (S_ISCHR(vp->v_mode)) { /* Character special files. */
163433d6423SLionel Sambuc if(rw_flag == PEEKING) {
164433d6423SLionel Sambuc printf("read_write: peek on char device makes no sense\n");
165433d6423SLionel Sambuc return EINVAL;
166433d6423SLionel Sambuc }
167433d6423SLionel Sambuc
168433d6423SLionel Sambuc if (vp->v_sdev == NO_DEV)
169433d6423SLionel Sambuc panic("VFS: read_write tries to access char dev NO_DEV");
170433d6423SLionel Sambuc
171433d6423SLionel Sambuc dev = vp->v_sdev;
172232819ddSDavid van Moolenbroek op = (rw_flag == READING ? CDEV_READ : CDEV_WRITE);
173433d6423SLionel Sambuc
174433d6423SLionel Sambuc r = cdev_io(op, dev, for_e, buf, position, size, f->filp_flags);
175433d6423SLionel Sambuc if (r >= 0) {
176433d6423SLionel Sambuc /* This should no longer happen: all calls are asynchronous. */
177433d6423SLionel Sambuc printf("VFS: I/O to device %llx succeeded immediately!?\n", dev);
178433d6423SLionel Sambuc cum_io = r;
179433d6423SLionel Sambuc position += r;
180433d6423SLionel Sambuc r = OK;
181433d6423SLionel Sambuc } else if (r == SUSPEND) {
182433d6423SLionel Sambuc /* FIXME: multiple read/write operations on a single filp
183433d6423SLionel Sambuc * should be serialized. They currently aren't; in order to
184433d6423SLionel Sambuc * achieve a similar effect, we optimistically advance the file
185433d6423SLionel Sambuc * position here. This works under the following assumptions:
186433d6423SLionel Sambuc * - character drivers that use the seek position at all,
187433d6423SLionel Sambuc * expose a view of a statically-sized range of bytes, i.e.,
188433d6423SLionel Sambuc * they are basically byte-granular block devices;
189433d6423SLionel Sambuc * - if short I/O or an error is returned, all subsequent calls
190433d6423SLionel Sambuc * will return (respectively) EOF and an error;
191433d6423SLionel Sambuc * - the application never checks its own file seek position,
192433d6423SLionel Sambuc * or does not care that it may end up having seeked beyond
193433d6423SLionel Sambuc * the number of bytes it has actually read;
194433d6423SLionel Sambuc * - communication to the character driver is FIFO (this one
195433d6423SLionel Sambuc * is actually true! whew).
196433d6423SLionel Sambuc * Many improvements are possible here, but in the end,
197433d6423SLionel Sambuc * anything short of queuing concurrent operations will be
198433d6423SLionel Sambuc * suboptimal - so we settle for this hack for now.
199433d6423SLionel Sambuc */
200433d6423SLionel Sambuc position += size;
201433d6423SLionel Sambuc }
202*e3b8d4bbSDavid van Moolenbroek } else if (S_ISSOCK(vp->v_mode)) {
203*e3b8d4bbSDavid van Moolenbroek if (rw_flag == PEEKING) {
204*e3b8d4bbSDavid van Moolenbroek printf("VFS: read_write tries to peek on sock dev\n");
205*e3b8d4bbSDavid van Moolenbroek return EINVAL;
206*e3b8d4bbSDavid van Moolenbroek }
207*e3b8d4bbSDavid van Moolenbroek
208*e3b8d4bbSDavid van Moolenbroek if (vp->v_sdev == NO_DEV)
209*e3b8d4bbSDavid van Moolenbroek panic("VFS: read_write tries to access sock dev NO_DEV");
210*e3b8d4bbSDavid van Moolenbroek
211*e3b8d4bbSDavid van Moolenbroek r = sdev_readwrite(vp->v_sdev, buf, size, 0, 0, 0, 0, 0, rw_flag,
212*e3b8d4bbSDavid van Moolenbroek f->filp_flags, 0);
213433d6423SLionel Sambuc } else if (S_ISBLK(vp->v_mode)) { /* Block special files. */
214433d6423SLionel Sambuc if (vp->v_sdev == NO_DEV)
215433d6423SLionel Sambuc panic("VFS: read_write tries to access block dev NO_DEV");
216433d6423SLionel Sambuc
217433d6423SLionel Sambuc lock_bsf();
218433d6423SLionel Sambuc
219433d6423SLionel Sambuc if(rw_flag == PEEKING) {
220433d6423SLionel Sambuc r = req_bpeek(vp->v_bfs_e, vp->v_sdev, position, size);
221433d6423SLionel Sambuc } else {
222433d6423SLionel Sambuc r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev, position,
223433d6423SLionel Sambuc size, buf, rw_flag, &res_pos, &res_cum_io);
224433d6423SLionel Sambuc if (r == OK) {
225433d6423SLionel Sambuc position = res_pos;
226433d6423SLionel Sambuc cum_io += res_cum_io;
227433d6423SLionel Sambuc }
228433d6423SLionel Sambuc }
229433d6423SLionel Sambuc
230433d6423SLionel Sambuc unlock_bsf();
231433d6423SLionel Sambuc } else { /* Regular files */
232433d6423SLionel Sambuc if (rw_flag == WRITING) {
233433d6423SLionel Sambuc /* Check for O_APPEND flag. */
234433d6423SLionel Sambuc if (f->filp_flags & O_APPEND) position = vp->v_size;
235433d6423SLionel Sambuc }
236433d6423SLionel Sambuc
237433d6423SLionel Sambuc /* Issue request */
238433d6423SLionel Sambuc if(rw_flag == PEEKING) {
239433d6423SLionel Sambuc r = req_peek(vp->v_fs_e, vp->v_inode_nr, position, size);
240433d6423SLionel Sambuc } else {
241433d6423SLionel Sambuc off_t new_pos;
242433d6423SLionel Sambuc r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position,
243433d6423SLionel Sambuc rw_flag, for_e, buf, size, &new_pos,
244433d6423SLionel Sambuc &cum_io_incr);
245433d6423SLionel Sambuc
246433d6423SLionel Sambuc if (r >= 0) {
247433d6423SLionel Sambuc position = new_pos;
248433d6423SLionel Sambuc cum_io += cum_io_incr;
249433d6423SLionel Sambuc }
250433d6423SLionel Sambuc }
251433d6423SLionel Sambuc }
252433d6423SLionel Sambuc
253433d6423SLionel Sambuc /* On write, update file size and access time. */
254433d6423SLionel Sambuc if (rw_flag == WRITING) {
255433d6423SLionel Sambuc if (S_ISREG(vp->v_mode) || S_ISDIR(vp->v_mode)) {
256433d6423SLionel Sambuc if (position > vp->v_size) {
257433d6423SLionel Sambuc vp->v_size = position;
258433d6423SLionel Sambuc }
259433d6423SLionel Sambuc }
260433d6423SLionel Sambuc }
261433d6423SLionel Sambuc
262433d6423SLionel Sambuc f->filp_pos = position;
263433d6423SLionel Sambuc
264433d6423SLionel Sambuc if (r == EPIPE && rw_flag == WRITING) {
265433d6423SLionel Sambuc /* Process is writing, but there is no reader. Tell the kernel to
266179bddcfSDavid van Moolenbroek * generate a SIGPIPE signal.
267433d6423SLionel Sambuc */
268433d6423SLionel Sambuc if (!(f->filp_flags & O_NOSIGPIPE)) {
269433d6423SLionel Sambuc sys_kill(rfp->fp_endpoint, SIGPIPE);
270433d6423SLionel Sambuc }
271433d6423SLionel Sambuc }
272433d6423SLionel Sambuc
273433d6423SLionel Sambuc if (r == OK) {
274433d6423SLionel Sambuc return(cum_io);
275433d6423SLionel Sambuc }
276433d6423SLionel Sambuc return(r);
277433d6423SLionel Sambuc }
278433d6423SLionel Sambuc
279433d6423SLionel Sambuc /*===========================================================================*
280433d6423SLionel Sambuc * do_getdents *
281433d6423SLionel Sambuc *===========================================================================*/
do_getdents(void)282433d6423SLionel Sambuc int do_getdents(void)
283433d6423SLionel Sambuc {
284433d6423SLionel Sambuc /* Perform the getdents(fd, buf, size) system call. */
285232819ddSDavid van Moolenbroek int fd, r = OK;
286433d6423SLionel Sambuc off_t new_pos;
287232819ddSDavid van Moolenbroek vir_bytes buf;
288232819ddSDavid van Moolenbroek size_t size;
289433d6423SLionel Sambuc register struct filp *rfilp;
290433d6423SLionel Sambuc
291232819ddSDavid van Moolenbroek /* This field must always be set to zero for getdents(). */
292232819ddSDavid van Moolenbroek if (job_m_in.m_lc_vfs_readwrite.cum_io != 0)
293232819ddSDavid van Moolenbroek return(EINVAL);
294232819ddSDavid van Moolenbroek
295232819ddSDavid van Moolenbroek fd = job_m_in.m_lc_vfs_readwrite.fd;
296232819ddSDavid van Moolenbroek buf = job_m_in.m_lc_vfs_readwrite.buf;
297232819ddSDavid van Moolenbroek size = job_m_in.m_lc_vfs_readwrite.len;
298433d6423SLionel Sambuc
299433d6423SLionel Sambuc /* Is the file descriptor valid? */
300232819ddSDavid van Moolenbroek if ( (rfilp = get_filp(fd, VNODE_READ)) == NULL)
301433d6423SLionel Sambuc return(err_code);
302433d6423SLionel Sambuc
303433d6423SLionel Sambuc if (!(rfilp->filp_mode & R_BIT))
304433d6423SLionel Sambuc r = EBADF;
305433d6423SLionel Sambuc else if (!S_ISDIR(rfilp->filp_vno->v_mode))
306433d6423SLionel Sambuc r = EBADF;
307433d6423SLionel Sambuc
308433d6423SLionel Sambuc if (r == OK) {
309433d6423SLionel Sambuc r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
310232819ddSDavid van Moolenbroek rfilp->filp_pos, buf, size, &new_pos, 0);
311433d6423SLionel Sambuc
312433d6423SLionel Sambuc if (r > 0) rfilp->filp_pos = new_pos;
313433d6423SLionel Sambuc }
314433d6423SLionel Sambuc
315433d6423SLionel Sambuc unlock_filp(rfilp);
316433d6423SLionel Sambuc return(r);
317433d6423SLionel Sambuc }
318433d6423SLionel Sambuc
319433d6423SLionel Sambuc
320433d6423SLionel Sambuc /*===========================================================================*
321433d6423SLionel Sambuc * rw_pipe *
322433d6423SLionel Sambuc *===========================================================================*/
rw_pipe(int rw_flag,endpoint_t usr_e,struct filp * f,int callnr,int fd,vir_bytes buf,size_t nbytes,size_t cum_io)323232819ddSDavid van Moolenbroek int rw_pipe(int rw_flag, endpoint_t usr_e, struct filp *f, int callnr, int fd,
324232819ddSDavid van Moolenbroek vir_bytes buf, size_t nbytes, size_t cum_io)
325433d6423SLionel Sambuc {
326232819ddSDavid van Moolenbroek int r, oflags, partial_pipe = FALSE;
327232819ddSDavid van Moolenbroek size_t size;
3283c8950ccSBen Gras size_t cum_io_incr;
329433d6423SLionel Sambuc struct vnode *vp;
330433d6423SLionel Sambuc off_t position, new_pos;
331433d6423SLionel Sambuc
332433d6423SLionel Sambuc /* Must make sure we're operating on locked filp and vnode */
333433d6423SLionel Sambuc assert(tll_locked_by_me(&f->filp_vno->v_lock));
334433d6423SLionel Sambuc assert(mutex_trylock(&f->filp_lock) == -EDEADLK);
335433d6423SLionel Sambuc
336433d6423SLionel Sambuc oflags = f->filp_flags;
337433d6423SLionel Sambuc vp = f->filp_vno;
338433d6423SLionel Sambuc position = 0; /* Not actually used */
339433d6423SLionel Sambuc
340433d6423SLionel Sambuc assert(rw_flag == READING || rw_flag == WRITING);
341433d6423SLionel Sambuc
342232819ddSDavid van Moolenbroek r = pipe_check(f, rw_flag, oflags, nbytes, 0);
343433d6423SLionel Sambuc if (r <= 0) {
344232819ddSDavid van Moolenbroek if (r == SUSPEND)
345232819ddSDavid van Moolenbroek pipe_suspend(callnr, fd, buf, nbytes, cum_io);
346232819ddSDavid van Moolenbroek
347179bddcfSDavid van Moolenbroek /* If pipe_check returns an error instead of suspending the call, we
348179bddcfSDavid van Moolenbroek * return that error, even if we are resuming a partially completed
349179bddcfSDavid van Moolenbroek * operation (ie, a large blocking write), to match NetBSD's behavior.
350179bddcfSDavid van Moolenbroek */
351433d6423SLionel Sambuc return(r);
352433d6423SLionel Sambuc }
353433d6423SLionel Sambuc
354433d6423SLionel Sambuc size = r;
355232819ddSDavid van Moolenbroek if (size < nbytes) partial_pipe = TRUE;
356433d6423SLionel Sambuc
357433d6423SLionel Sambuc /* Truncate read request at size. */
358433d6423SLionel Sambuc if (rw_flag == READING && size > vp->v_size) {
359433d6423SLionel Sambuc size = vp->v_size;
360433d6423SLionel Sambuc }
361433d6423SLionel Sambuc
362433d6423SLionel Sambuc if (vp->v_mapfs_e == 0)
363433d6423SLionel Sambuc panic("unmapped pipe");
364433d6423SLionel Sambuc
365433d6423SLionel Sambuc r = req_readwrite(vp->v_mapfs_e, vp->v_mapinode_nr, position, rw_flag, usr_e,
366433d6423SLionel Sambuc buf, size, &new_pos, &cum_io_incr);
367433d6423SLionel Sambuc
368433d6423SLionel Sambuc if (r != OK) {
369179bddcfSDavid van Moolenbroek assert(r != SUSPEND);
370433d6423SLionel Sambuc return(r);
371433d6423SLionel Sambuc }
372433d6423SLionel Sambuc
373433d6423SLionel Sambuc cum_io += cum_io_incr;
374433d6423SLionel Sambuc buf += cum_io_incr;
375232819ddSDavid van Moolenbroek nbytes -= cum_io_incr;
376433d6423SLionel Sambuc
377f859061eSDavid van Moolenbroek if (rw_flag == READING)
378f859061eSDavid van Moolenbroek vp->v_size -= cum_io_incr;
379f859061eSDavid van Moolenbroek else
380f859061eSDavid van Moolenbroek vp->v_size += cum_io_incr;
381433d6423SLionel Sambuc
382433d6423SLionel Sambuc if (partial_pipe) {
383433d6423SLionel Sambuc /* partial write on pipe with */
384433d6423SLionel Sambuc /* O_NONBLOCK, return write count */
385433d6423SLionel Sambuc if (!(oflags & O_NONBLOCK)) {
386232819ddSDavid van Moolenbroek /* partial write on pipe with nbytes > PIPE_BUF, non-atomic */
387232819ddSDavid van Moolenbroek pipe_suspend(callnr, fd, buf, nbytes, cum_io);
388433d6423SLionel Sambuc return(SUSPEND);
389433d6423SLionel Sambuc }
390433d6423SLionel Sambuc }
391433d6423SLionel Sambuc
392433d6423SLionel Sambuc return(cum_io);
393433d6423SLionel Sambuc }
394