4f152f3601f50d205d0d876e0efb12d81ea54e46
[dragonfly.git] / sys / vfs / puffs / puffs_io.c
1 /*      $NetBSD: puffs_vnops.c,v 1.154 2011/07/04 08:07:30 manu Exp $   */
2
3 /*
4  * Copyright (c) 2005, 2006, 2007  Antti Kantee.  All Rights Reserved.
5  *
6  * Development of this software was supported by the
7  * Google Summer of Code program and the Ulla Tuominen Foundation.
8  * The Google SoC project was mentored by Bill Studenmund.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 #include <sys/param.h>
33 #include <sys/buf.h>
34 #include <sys/lockf.h>
35 #include <sys/malloc.h>
36 #include <sys/mount.h>
37 #include <sys/namei.h>
38 #include <sys/vnode.h>
39 #include <sys/proc.h>
40 #include <sys/thread2.h>
41
42 #include <vfs/puffs/puffs_msgif.h>
43 #include <vfs/puffs/puffs_sys.h>
44
45 #define RWARGS(cont, iofl, move, offset, creds)                         \
46         (cont)->pvnr_ioflag = (iofl);                                   \
47         (cont)->pvnr_resid = (move);                                    \
48         (cont)->pvnr_offset = (offset);                                 \
49         puffs_credcvt(&(cont)->pvnr_cred, creds)
50
51 int
52 puffs_directread(struct vnode *vp, struct uio *uio, int ioflag,
53     struct ucred *cred)
54 {
55         PUFFS_MSG_VARS(vn, read);
56         struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
57         size_t tomove, argsize;
58         int error;
59
60         KKASSERT(vp->v_type == VREG);
61
62         if (uio->uio_offset < 0)
63                 return EINVAL;
64         if (uio->uio_resid == 0)
65                 return 0;
66
67         read_msg = NULL;
68         error = 0;
69
70         /* std sanity */
71         if (uio->uio_resid == 0)
72                 return 0;
73         if (uio->uio_offset < 0)
74                 return EINVAL;
75
76         /*
77          * in case it's not a regular file or we're operating
78          * uncached, do read in the old-fashioned style,
79          * i.e. explicit read operations
80          */
81
82         tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
83         argsize = sizeof(struct puffs_vnmsg_read);
84         puffs_msgmem_alloc(argsize + tomove, &park_read,
85             (void *)&read_msg, 1);
86
87         error = 0;
88         while (uio->uio_resid > 0) {
89                 tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
90                 memset(read_msg, 0, argsize); /* XXX: touser KASSERT */
91                 RWARGS(read_msg, ioflag, tomove,
92                     uio->uio_offset, cred);
93                 puffs_msg_setinfo(park_read, PUFFSOP_VN,
94                     PUFFS_VN_READ, VPTOPNC(vp));
95                 puffs_msg_setdelta(park_read, tomove);
96
97                 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_read, vp->v_data,
98                     NULL, error);
99                 error = checkerr(pmp, error, __func__);
100                 if (error)
101                         break;
102
103                 if (read_msg->pvnr_resid > tomove) {
104                         puffs_senderr(pmp, PUFFS_ERR_READ,
105                             E2BIG, "resid grew", VPTOPNC(vp));
106                         error = EPROTO;
107                         break;
108                 }
109
110                 error = uiomove(read_msg->pvnr_data,
111                     tomove - read_msg->pvnr_resid, uio);
112
113                 /*
114                  * in case the file is out of juice, resid from
115                  * userspace is != 0.  and the error-case is
116                  * quite obvious
117                  */
118                 if (error || read_msg->pvnr_resid)
119                         break;
120         }
121
122         puffs_msgmem_release(park_read);
123
124         return error;
125 }
126
127 int
128 puffs_directwrite(struct vnode *vp, struct uio *uio, int ioflag,
129     struct ucred *cred)
130 {
131         PUFFS_MSG_VARS(vn, write);
132         struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
133         size_t tomove, argsize;
134         int error, uflags;
135
136         KKASSERT(vp->v_type == VREG);
137
138         if (uio->uio_offset < 0)
139                 return EINVAL;
140         if (uio->uio_resid == 0)
141                 return 0;
142
143         error = uflags = 0;
144         write_msg = NULL;
145
146         /* tomove is non-increasing */
147         tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
148         argsize = sizeof(struct puffs_vnmsg_write) + tomove;
149         puffs_msgmem_alloc(argsize, &park_write, (void *)&write_msg,1);
150
151         while (uio->uio_resid > 0) {
152                 /* move data to buffer */
153                 tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
154                 memset(write_msg, 0, argsize); /* XXX: touser KASSERT */
155                 RWARGS(write_msg, ioflag, tomove,
156                     uio->uio_offset, cred);
157                 error = uiomove(write_msg->pvnr_data, tomove, uio);
158                 if (error)
159                         break;
160
161                 /* move buffer to userspace */
162                 puffs_msg_setinfo(park_write, PUFFSOP_VN,
163                     PUFFS_VN_WRITE, VPTOPNC(vp));
164                 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_write, vp->v_data,
165                     NULL, error);
166                 error = checkerr(pmp, error, __func__);
167                 if (error)
168                         break;
169
170                 if (write_msg->pvnr_resid > tomove) {
171                         puffs_senderr(pmp, PUFFS_ERR_WRITE,
172                             E2BIG, "resid grew", VPTOPNC(vp));
173                         error = EPROTO;
174                         break;
175                 }
176
177                 if (PUFFS_USE_PAGECACHE(pmp))
178                         KKASSERT(vp->v_filesize >= uio->uio_offset);
179
180                 /* didn't move everything?  bad userspace.  bail */
181                 if (write_msg->pvnr_resid != 0) {
182                         error = EIO;
183                         break;
184                 }
185         }
186         puffs_msgmem_release(park_write);
187
188         return error;
189 }
190
191 static void
192 puffs_iodone(struct bio *bio)
193 {
194         bio->bio_flags = 0;
195         bpdone(bio->bio_buf, 0);
196 }
197
198 int
199 puffs_bioread(struct vnode *vp, struct uio *uio, int ioflag,
200     struct ucred *cred)
201 {
202         int biosize = vp->v_mount->mnt_stat.f_iosize;
203         struct buf *bp;
204         struct vattr vattr;
205         off_t lbn, loffset, fsize;
206         size_t n;
207         int boff, seqcount;
208         int error = 0;
209
210         KKASSERT(uio->uio_rw == UIO_READ);
211         KKASSERT(vp->v_type == VREG);
212
213         if (uio->uio_offset < 0)
214                 return EINVAL;
215         if (uio->uio_resid == 0)
216                 return 0;
217
218         seqcount = (int)((off_t)(ioflag >> IO_SEQSHIFT) * biosize / BKVASIZE);
219
220         /*
221          * Cache consistency can only be maintained approximately.
222          *
223          * GETATTR is called to synchronize the file size.
224          *
225          * NOTE: In the normal case the attribute cache is not
226          * cleared which means GETATTR may use cached data and
227          * not immediately detect changes made on the server.
228          */
229
230         error = VOP_GETATTR(vp, &vattr);
231         if (error)
232                 return error;
233
234         /*
235          * Loop until uio exhausted or we hit EOF
236          */
237         do {
238                 bp = NULL;
239
240                 lbn = uio->uio_offset / biosize;
241                 boff = uio->uio_offset & (biosize - 1);
242                 loffset = lbn * biosize;
243                 fsize = puffs_meta_getsize(vp);
244
245                 if (loffset + boff >= fsize) {
246                         n = 0;
247                         break;
248                 }
249                 bp = getblk(vp, loffset, biosize, 0, 0);
250
251                 if (bp == NULL)
252                         return EINTR;
253
254                 /*
255                  * If B_CACHE is not set, we must issue the read.  If this
256                  * fails, we return an error.
257                  */
258                 if ((bp->b_flags & B_CACHE) == 0) {
259                         bp->b_cmd = BUF_CMD_READ;
260                         bp->b_bio2.bio_done = puffs_iodone;
261                         bp->b_bio2.bio_flags |= BIO_SYNC;
262                         vfs_busy_pages(vp, bp);
263                         error = puffs_doio(vp, &bp->b_bio2, uio->uio_td);
264                         if (error) {
265                                 brelse(bp);
266                                 return error;
267                         }
268                 }
269
270                 /*
271                  * on is the offset into the current bp.  Figure out how many
272                  * bytes we can copy out of the bp.  Note that bcount is
273                  * NOT DEV_BSIZE aligned.
274                  *
275                  * Then figure out how many bytes we can copy into the uio.
276                  */
277                 n = biosize - boff;
278                 if (n > uio->uio_resid)
279                         n = uio->uio_resid;
280                 if (loffset + boff + n > fsize)
281                         n = fsize - loffset - boff;
282
283                 if (n > 0)
284                         error = uiomove(bp->b_data + boff, n, uio);
285                 if (bp)
286                         brelse(bp);
287         } while (error == 0 && uio->uio_resid > 0 && n > 0);
288
289         return error;
290 }
291
292 int
293 puffs_biowrite(struct vnode *vp, struct uio *uio, int ioflag,
294     struct ucred *cred)
295 {
296         int biosize = vp->v_mount->mnt_stat.f_iosize;
297         struct buf *bp;
298         struct vattr vattr;
299         off_t loffset, fsize;
300         int boff, bytes;
301         int error = 0;
302         int bcount;
303         int trivial;
304
305         KKASSERT(uio->uio_rw == UIO_WRITE);
306         KKASSERT(vp->v_type == VREG);
307
308         if (uio->uio_offset < 0)
309                 return EINVAL;
310         if (uio->uio_resid == 0)
311                 return 0;
312
313         /*
314          * If IO_APPEND then load uio_offset.  We restart here if we cannot
315          * get the append lock.
316          *
317          * We need to obtain exclusize lock if we intend to modify file size
318          * in order to guarentee the append point with multiple contending
319          * writers.
320          */
321         if (ioflag & IO_APPEND) {
322                 /* XXXDF relock if necessary */
323                 KKASSERT(vn_islocked(vp) == LK_EXCLUSIVE);
324                 error = VOP_GETATTR(vp, &vattr);
325                 if (error)
326                         return error;
327                 uio->uio_offset = puffs_meta_getsize(vp);
328         }
329
330         do {
331                 boff = uio->uio_offset & (biosize-1);
332                 loffset = uio->uio_offset - boff;
333                 bytes = (int)szmin((unsigned)(biosize - boff), uio->uio_resid);
334 again:
335                 /*
336                  * Handle direct append and file extension cases, calculate
337                  * unaligned buffer size.  When extending B_CACHE will be
338                  * set if possible.  See UIO_NOCOPY note below.
339                  */
340                 fsize = puffs_meta_getsize(vp);
341                 if (uio->uio_offset + bytes > fsize) {
342                         trivial = (uio->uio_segflg != UIO_NOCOPY &&
343                             uio->uio_offset <= fsize);
344                         puffs_meta_setsize(vp, uio->uio_offset + bytes,
345                             trivial);
346                 }
347                 bp = getblk(vp, loffset, biosize, 0, 0);
348                 if (bp == NULL) {
349                         error = EINTR;
350                         break;
351                 }
352
353                 /*
354                  * Actual bytes in buffer which we care about
355                  */
356                 if (loffset + biosize < fsize)
357                         bcount = biosize;
358                 else
359                         bcount = (int)(fsize - loffset);
360
361                 /*
362                  * Avoid a read by setting B_CACHE where the data we
363                  * intend to write covers the entire buffer.  Note
364                  * that the buffer may have been set to B_CACHE by
365                  * puffs_meta_setsize() above or otherwise inherited the
366                  * flag, but if B_CACHE isn't set the buffer may be
367                  * uninitialized and must be zero'd to accomodate
368                  * future seek+write's.
369                  *
370                  * See the comments in kern/vfs_bio.c's getblk() for
371                  * more information.
372                  *
373                  * When doing a UIO_NOCOPY write the buffer is not
374                  * overwritten and we cannot just set B_CACHE unconditionally
375                  * for full-block writes.
376                  */
377                 if (boff == 0 && bytes == biosize &&
378                     uio->uio_segflg != UIO_NOCOPY) {
379                         bp->b_flags |= B_CACHE;
380                         bp->b_flags &= ~(B_ERROR | B_INVAL);
381                 }
382
383                 /*
384                  * b_resid may be set due to file EOF if we extended out.
385                  * The NFS bio code will zero the difference anyway so
386                  * just acknowledged the fact and set b_resid to 0.
387                  */
388                 if ((bp->b_flags & B_CACHE) == 0) {
389                         bp->b_cmd = BUF_CMD_READ;
390                         bp->b_bio2.bio_done = puffs_iodone;
391                         bp->b_bio2.bio_flags |= BIO_SYNC;
392                         vfs_busy_pages(vp, bp);
393                         error = puffs_doio(vp, &bp->b_bio2, uio->uio_td);
394                         if (error) {
395                                 brelse(bp);
396                                 break;
397                         }
398                         bp->b_resid = 0;
399                 }
400
401                 /*
402                  * If dirtyend exceeds file size, chop it down.  This should
403                  * not normally occur but there is an append race where it
404                  * might occur XXX, so we log it.
405                  *
406                  * If the chopping creates a reverse-indexed or degenerate
407                  * situation with dirtyoff/end, we 0 both of them.
408                  */
409                 if (bp->b_dirtyend > bcount) {
410                         kprintf("PUFFS append race @%08llx:%d\n",
411                             (long long)bp->b_bio2.bio_offset,
412                             bp->b_dirtyend - bcount);
413                         bp->b_dirtyend = bcount;
414                 }
415
416                 if (bp->b_dirtyoff >= bp->b_dirtyend)
417                         bp->b_dirtyoff = bp->b_dirtyend = 0;
418
419                 /*
420                  * If the new write will leave a contiguous dirty
421                  * area, just update the b_dirtyoff and b_dirtyend,
422                  * otherwise force a write rpc of the old dirty area.
423                  *
424                  * While it is possible to merge discontiguous writes due to
425                  * our having a B_CACHE buffer ( and thus valid read data
426                  * for the hole), we don't because it could lead to
427                  * significant cache coherency problems with multiple clients,
428                  * especially if locking is implemented later on.
429                  *
430                  * as an optimization we could theoretically maintain
431                  * a linked list of discontinuous areas, but we would still
432                  * have to commit them separately so there isn't much
433                  * advantage to it except perhaps a bit of asynchronization.
434                  */
435                 if (bp->b_dirtyend > 0 &&
436                     (boff > bp->b_dirtyend ||
437                     (boff + bytes) < bp->b_dirtyoff)
438                    ) {
439                         if (bwrite(bp) == EINTR) {
440                                 error = EINTR;
441                                 break;
442                         }
443                         goto again;
444                 }
445
446                 error = uiomove(bp->b_data + boff, bytes, uio);
447
448                 /*
449                  * Since this block is being modified, it must be written
450                  * again and not just committed.  Since write clustering does
451                  * not work for the stage 1 data write, only the stage 2
452                  * commit rpc, we have to clear B_CLUSTEROK as well.
453                  */
454                 bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
455
456                 if (error) {
457                         brelse(bp);
458                         break;
459                 }
460
461                 /*
462                  * Only update dirtyoff/dirtyend if not a degenerate
463                  * condition.
464                  *
465                  * The underlying VM pages have been marked valid by
466                  * virtue of acquiring the bp.  Because the entire buffer
467                  * is marked dirty we do not have to worry about cleaning
468                  * out the related dirty bits (and wouldn't really know
469                  * how to deal with byte ranges anyway)
470                  */
471                 if (bytes) {
472                         if (bp->b_dirtyend > 0) {
473                                 bp->b_dirtyoff = imin(boff, bp->b_dirtyoff);
474                                 bp->b_dirtyend = imax(boff + bytes,
475                                     bp->b_dirtyend);
476                         } else {
477                                 bp->b_dirtyoff = boff;
478                                 bp->b_dirtyend = boff + bytes;
479                         }
480                 }
481
482                 if (ioflag & IO_SYNC) {
483                         if (ioflag & IO_INVAL)
484                                 bp->b_flags |= B_NOCACHE;
485                         error = bwrite(bp);
486                         if (error)
487                                 break;
488                 } else {
489                         bdwrite(bp);
490                 }
491         } while (uio->uio_resid > 0 && bytes > 0);
492
493         return error;
494 }
495
496 int
497 puffs_doio(struct vnode *vp, struct bio *bio, struct thread *td)
498 {
499         struct buf *bp = bio->bio_buf;
500         struct ucred *cred;
501         struct uio *uiop;
502         struct uio uio;
503         struct iovec io;
504         size_t n;
505         int error = 0;
506
507         if (td != NULL && td->td_proc != NULL)
508                 cred = td->td_proc->p_ucred;
509         else
510                 cred = proc0.p_ucred;
511
512         uiop = &uio;
513         uiop->uio_iov = &io;
514         uiop->uio_iovcnt = 1;
515         uiop->uio_segflg = UIO_SYSSPACE;
516         uiop->uio_td = td;
517
518         /*
519          * clear B_ERROR and B_INVAL state prior to initiating the I/O.  We
520          * do this here so we do not have to do it in all the code that
521          * calls us.
522          */
523         bp->b_flags &= ~(B_ERROR | B_INVAL);
524
525         KASSERT(bp->b_cmd != BUF_CMD_DONE,
526             ("puffs_doio: bp %p already marked done!", bp));
527
528         if (bp->b_cmd == BUF_CMD_READ) {
529                 io.iov_len = uiop->uio_resid = (size_t)bp->b_bcount;
530                 io.iov_base = bp->b_data;
531                 uiop->uio_rw = UIO_READ;
532
533                 uiop->uio_offset = bio->bio_offset;
534                 error = puffs_directread(vp, uiop, 0, cred);
535                 if (error == 0 && uiop->uio_resid) {
536                         n = (size_t)bp->b_bcount - uiop->uio_resid;
537                         bzero(bp->b_data + n, bp->b_bcount - n);
538                         uiop->uio_resid = 0;
539                 }
540                 if (error) {
541                         bp->b_flags |= B_ERROR;
542                         bp->b_error = error;
543                 }
544                 bp->b_resid = uiop->uio_resid;
545         } else {
546                 KKASSERT(bp->b_cmd == BUF_CMD_WRITE);
547                 if (bio->bio_offset + bp->b_dirtyend > puffs_meta_getsize(vp))
548                         bp->b_dirtyend = puffs_meta_getsize(vp) -
549                             bio->bio_offset;
550
551                 if (bp->b_dirtyend > bp->b_dirtyoff) {
552                         io.iov_len = uiop->uio_resid = bp->b_dirtyend
553                             - bp->b_dirtyoff;
554                         uiop->uio_offset = bio->bio_offset + bp->b_dirtyoff;
555                         io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
556                         uiop->uio_rw = UIO_WRITE;
557
558                         error = puffs_directwrite(vp, uiop, 0, cred);
559
560                         if (error == EINTR
561                             || (!error && (bp->b_flags & B_NEEDCOMMIT))) {
562                                 crit_enter();
563                                 bp->b_flags &= ~(B_INVAL|B_NOCACHE);
564                                 if ((bp->b_flags & B_PAGING) == 0)
565                                         bdirty(bp);
566                                 if (error)
567                                         bp->b_flags |= B_EINTR;
568                                 crit_exit();
569                         } else {
570                                 if (error) {
571                                         bp->b_flags |= B_ERROR;
572                                         bp->b_error = error;
573                                 }
574                                 bp->b_dirtyoff = bp->b_dirtyend = 0;
575                         }
576                         bp->b_resid = uiop->uio_resid;
577                 } else {
578                         bp->b_resid = 0;
579                 }
580         }
581
582         biodone(bio);
583         KKASSERT(bp->b_cmd == BUF_CMD_DONE);
584         if (bp->b_flags & B_EINTR)
585                 return (EINTR);
586         if (bp->b_flags & B_ERROR)
587                 return (bp->b_error ? bp->b_error : EIO);
588         return (0);
589 }