]> git.saurik.com Git - apple/xnu.git/blame - bsd/nfs/nfs_bio.c
xnu-792.25.20.tar.gz
[apple/xnu.git] / bsd / nfs / nfs_bio.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
3 *
6601e61a 4 * @APPLE_LICENSE_HEADER_START@
1c79356b 5 *
6601e61a
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
8f6c56a5 11 *
6601e61a
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6601e61a
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
8f6c56a5 19 *
6601e61a 20 * @APPLE_LICENSE_HEADER_END@
1c79356b
A
21 */
22/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23/*
24 * Copyright (c) 1989, 1993
25 * The Regents of the University of California. All rights reserved.
26 *
27 * This code is derived from software contributed to Berkeley by
28 * Rick Macklem at The University of Guelph.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
58 * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
59 * FreeBSD-Id: nfs_bio.c,v 1.44 1997/09/10 19:52:25 phk Exp $
60 */
1c79356b
A
61#include <sys/param.h>
62#include <sys/systm.h>
63#include <sys/resourcevar.h>
64#include <sys/signalvar.h>
91447636
A
65#include <sys/proc_internal.h>
66#include <sys/kauth.h>
55e303ae 67#include <sys/malloc.h>
1c79356b 68#include <sys/vnode.h>
55e303ae 69#include <sys/dirent.h>
91447636 70#include <sys/mount_internal.h>
1c79356b
A
71#include <sys/kernel.h>
72#include <sys/sysctl.h>
91447636
A
73#include <sys/ubc_internal.h>
74#include <sys/uio_internal.h>
1c79356b
A
75
76#include <sys/vm.h>
77#include <sys/vmparam.h>
78
79#include <sys/time.h>
80#include <kern/clock.h>
91447636
A
81#include <libkern/OSAtomic.h>
82#include <kern/kalloc.h>
1c79356b
A
83
84#include <nfs/rpcv2.h>
85#include <nfs/nfsproto.h>
86#include <nfs/nfs.h>
87#include <nfs/nfsmount.h>
1c79356b 88#include <nfs/nfsnode.h>
91447636 89#include <sys/buf_internal.h>
1c79356b
A
90
91#include <sys/kdebug.h>
92
fa4905b1
A
93#define FSDBG(A, B, C, D, E) \
94 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_NONE, \
95 (int)(B), (int)(C), (int)(D), (int)(E), 0)
96#define FSDBG_TOP(A, B, C, D, E) \
97 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_START, \
98 (int)(B), (int)(C), (int)(D), (int)(E), 0)
99#define FSDBG_BOT(A, B, C, D, E) \
100 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_END, \
101 (int)(B), (int)(C), (int)(D), (int)(E), 0)
102
1c79356b 103extern int nfs_numasync;
55e303ae 104extern int nfs_ioddelwri;
1c79356b 105extern struct nfsstats nfsstats;
55e303ae 106
91447636
A
107#define NFSBUFHASH(np, lbn) \
108 (&nfsbufhashtbl[((long)(np) / sizeof(*(np)) + (int)(lbn)) & nfsbufhash])
55e303ae 109LIST_HEAD(nfsbufhashhead, nfsbuf) *nfsbufhashtbl;
483a1d10 110struct nfsbuffreehead nfsbuffree, nfsbuffreemeta, nfsbufdelwri;
55e303ae 111u_long nfsbufhash;
91447636 112int nfsbufcnt, nfsbufmin, nfsbufmax, nfsbufmetacnt, nfsbufmetamax;
483a1d10 113int nfsbuffreecnt, nfsbuffreemetacnt, nfsbufdelwricnt, nfsneedbuffer;
55e303ae 114int nfs_nbdwrite;
483a1d10
A
115time_t nfsbuffreeuptimestamp;
116
91447636
A
117lck_grp_t *nfs_buf_lck_grp;
118lck_grp_attr_t *nfs_buf_lck_grp_attr;
119lck_attr_t *nfs_buf_lck_attr;
120lck_mtx_t *nfs_buf_mutex;
121
483a1d10
A
122#define NFSBUFWRITE_THROTTLE 9
123#define NFSBUF_LRU_STALE 120
124#define NFSBUF_META_STALE 240
125
126/* number of nfsbufs nfs_buf_freeup() should attempt to free from nfsbuffree list */
127#define LRU_TO_FREEUP 6
128/* number of nfsbufs nfs_buf_freeup() should attempt to free from nfsbuffreemeta list */
129#define META_TO_FREEUP 3
130/* total number of nfsbufs nfs_buf_freeup() should attempt to free */
131#define TOTAL_TO_FREEUP (LRU_TO_FREEUP+META_TO_FREEUP)
132/* fraction of nfsbufs nfs_buf_freeup() should attempt to free from nfsbuffree list when called from nfs_timer() */
133#define LRU_FREEUP_FRAC_ON_TIMER 8
134/* fraction of nfsbufs nfs_buf_freeup() should attempt to free from nfsbuffreemeta list when called from nfs_timer() */
135#define META_FREEUP_FRAC_ON_TIMER 16
136/* fraction of total nfsbufs that nfsbuffreecnt should exceed before bothering to call nfs_buf_freeup() */
137#define LRU_FREEUP_MIN_FRAC 4
138/* fraction of total nfsbufs that nfsbuffreemetacnt should exceed before bothering to call nfs_buf_freeup() */
139#define META_FREEUP_MIN_FRAC 2
55e303ae 140
483a1d10 141#define NFS_BUF_FREEUP() \
91447636 142 do { \
483a1d10
A
143 /* only call nfs_buf_freeup() if it has work to do: */ \
144 if (((nfsbuffreecnt > nfsbufcnt/LRU_FREEUP_MIN_FRAC) || \
145 (nfsbuffreemetacnt > nfsbufcnt/META_FREEUP_MIN_FRAC)) && \
146 ((nfsbufcnt - TOTAL_TO_FREEUP) > nfsbufmin)) \
147 nfs_buf_freeup(0); \
148 } while (0)
55e303ae
A
149
150/*
151 * Initialize nfsbuf lists
152 */
153void
154nfs_nbinit(void)
155{
91447636 156 nfs_buf_lck_grp_attr = lck_grp_attr_alloc_init();
91447636
A
157 nfs_buf_lck_grp = lck_grp_alloc_init("nfs_buf", nfs_buf_lck_grp_attr);
158
159 nfs_buf_lck_attr = lck_attr_alloc_init();
160
161 nfs_buf_mutex = lck_mtx_alloc_init(nfs_buf_lck_grp, nfs_buf_lck_attr);
162
163 nfsbufcnt = nfsbufmetacnt =
164 nfsbuffreecnt = nfsbuffreemetacnt = nfsbufdelwricnt = 0;
165 nfsbufmin = 128;
166 nfsbufmax = (sane_size >> PAGE_SHIFT) / 4;
167 nfsbufmetamax = (sane_size >> PAGE_SHIFT) / 16;
55e303ae
A
168 nfsneedbuffer = 0;
169 nfs_nbdwrite = 0;
483a1d10 170 nfsbuffreeuptimestamp = 0;
91447636
A
171
172 nfsbufhashtbl = hashinit(nfsbufmax/4, M_TEMP, &nfsbufhash);
173 TAILQ_INIT(&nfsbuffree);
174 TAILQ_INIT(&nfsbuffreemeta);
175 TAILQ_INIT(&nfsbufdelwri);
176
55e303ae
A
177}
178
179/*
180 * try to free up some excess, unused nfsbufs
181 */
483a1d10
A
182void
183nfs_buf_freeup(int timer)
55e303ae
A
184{
185 struct nfsbuf *fbp;
483a1d10
A
186 struct timeval now;
187 int count;
91447636
A
188 struct nfsbuffreehead nfsbuffreeup;
189
190 TAILQ_INIT(&nfsbuffreeup);
191
192 lck_mtx_lock(nfs_buf_mutex);
55e303ae 193
483a1d10
A
194 microuptime(&now);
195 nfsbuffreeuptimestamp = now.tv_sec;
55e303ae 196
91447636
A
197 FSDBG(320, nfsbufcnt, nfsbuffreecnt, nfsbuffreemetacnt, 0);
198
483a1d10
A
199 count = timer ? nfsbuffreecnt/LRU_FREEUP_FRAC_ON_TIMER : LRU_TO_FREEUP;
200 while ((nfsbufcnt > nfsbufmin) && (count-- > 0)) {
55e303ae
A
201 fbp = TAILQ_FIRST(&nfsbuffree);
202 if (!fbp)
203 break;
91447636
A
204 if (fbp->nb_refs)
205 break;
206 if (NBUFSTAMPVALID(fbp) &&
207 (fbp->nb_timestamp + (2*NFSBUF_LRU_STALE)) > now.tv_sec)
483a1d10
A
208 break;
209 nfs_buf_remfree(fbp);
210 /* disassociate buffer from any vnode */
211 if (fbp->nb_vp) {
483a1d10
A
212 if (fbp->nb_vnbufs.le_next != NFSNOLIST) {
213 LIST_REMOVE(fbp, nb_vnbufs);
214 fbp->nb_vnbufs.le_next = NFSNOLIST;
215 }
483a1d10 216 fbp->nb_vp = NULL;
483a1d10
A
217 }
218 LIST_REMOVE(fbp, nb_hash);
91447636 219 TAILQ_INSERT_TAIL(&nfsbuffreeup, fbp, nb_free);
483a1d10
A
220 nfsbufcnt--;
221 }
222
223 count = timer ? nfsbuffreemetacnt/META_FREEUP_FRAC_ON_TIMER : META_TO_FREEUP;
224 while ((nfsbufcnt > nfsbufmin) && (count-- > 0)) {
225 fbp = TAILQ_FIRST(&nfsbuffreemeta);
226 if (!fbp)
227 break;
91447636
A
228 if (fbp->nb_refs)
229 break;
230 if (NBUFSTAMPVALID(fbp) &&
231 (fbp->nb_timestamp + (2*NFSBUF_META_STALE)) > now.tv_sec)
483a1d10 232 break;
55e303ae
A
233 nfs_buf_remfree(fbp);
234 /* disassociate buffer from any vnode */
235 if (fbp->nb_vp) {
55e303ae
A
236 if (fbp->nb_vnbufs.le_next != NFSNOLIST) {
237 LIST_REMOVE(fbp, nb_vnbufs);
238 fbp->nb_vnbufs.le_next = NFSNOLIST;
239 }
55e303ae 240 fbp->nb_vp = NULL;
55e303ae
A
241 }
242 LIST_REMOVE(fbp, nb_hash);
91447636
A
243 TAILQ_INSERT_TAIL(&nfsbuffreeup, fbp, nb_free);
244 nfsbufcnt--;
245 nfsbufmetacnt--;
246 }
247
248 FSDBG(320, nfsbufcnt, nfsbuffreecnt, nfsbuffreemetacnt, 0);
249 NFSBUFCNTCHK(1);
250
251 lck_mtx_unlock(nfs_buf_mutex);
252
253 while ((fbp = TAILQ_FIRST(&nfsbuffreeup))) {
254 TAILQ_REMOVE(&nfsbuffreeup, fbp, nb_free);
55e303ae 255 /* nuke any creds */
0c530ab8
A
256 if (IS_VALID_CRED(fbp->nb_rcred)) {
257 kauth_cred_unref(&fbp->nb_rcred);
55e303ae 258 }
0c530ab8
A
259 if (IS_VALID_CRED(fbp->nb_wcred)) {
260 kauth_cred_unref(&fbp->nb_wcred);
91447636
A
261 }
262 /* if buf was NB_META, dump buffer */
263 if (ISSET(fbp->nb_flags, NB_META) && fbp->nb_data)
264 kfree(fbp->nb_data, fbp->nb_bufsize);
55e303ae 265 FREE(fbp, M_TEMP);
55e303ae 266 }
91447636 267
55e303ae
A
268}
269
91447636
A
270/*
271 * remove a buffer from the freelist
272 * (must be called with nfs_buf_mutex held)
273 */
55e303ae
A
274void
275nfs_buf_remfree(struct nfsbuf *bp)
276{
277 if (bp->nb_free.tqe_next == NFSNOLIST)
278 panic("nfsbuf not on free list");
279 if (ISSET(bp->nb_flags, NB_DELWRI)) {
280 nfsbufdelwricnt--;
281 TAILQ_REMOVE(&nfsbufdelwri, bp, nb_free);
91447636 282 } else if (ISSET(bp->nb_flags, NB_META)) {
483a1d10
A
283 nfsbuffreemetacnt--;
284 TAILQ_REMOVE(&nfsbuffreemeta, bp, nb_free);
55e303ae
A
285 } else {
286 nfsbuffreecnt--;
287 TAILQ_REMOVE(&nfsbuffree, bp, nb_free);
288 }
289 bp->nb_free.tqe_next = NFSNOLIST;
91447636 290 NFSBUFCNTCHK(1);
55e303ae
A
291}
292
293/*
294 * check for existence of nfsbuf in cache
295 */
91447636
A
296boolean_t
297nfs_buf_is_incore(vnode_t vp, daddr64_t blkno)
298{
299 boolean_t rv;
300 lck_mtx_lock(nfs_buf_mutex);
301 if (nfs_buf_incore(vp, blkno))
302 rv = TRUE;
303 else
304 rv = FALSE;
305 lck_mtx_unlock(nfs_buf_mutex);
306 return (rv);
307}
308
309/*
310 * return incore buffer (must be called with nfs_buf_mutex held)
311 */
55e303ae 312struct nfsbuf *
91447636 313nfs_buf_incore(vnode_t vp, daddr64_t blkno)
55e303ae
A
314{
315 /* Search hash chain */
91447636 316 struct nfsbuf * bp = NFSBUFHASH(VTONFS(vp), blkno)->lh_first;
55e303ae 317 for (; bp != NULL; bp = bp->nb_hash.le_next)
483a1d10
A
318 if (bp->nb_lblkno == blkno && bp->nb_vp == vp) {
319 if (!ISSET(bp->nb_flags, NB_INVAL)) {
320 FSDBG(547, bp, blkno, bp->nb_flags, bp->nb_vp);
321 return (bp);
322 }
323 }
55e303ae
A
324 return (NULL);
325}
326
327/*
328 * Check if it's OK to drop a page.
329 *
330 * Called by vnode_pager() on pageout request of non-dirty page.
331 * We need to make sure that it's not part of a delayed write.
332 * If it is, we can't let the VM drop it because we may need it
333 * later when/if we need to write the data (again).
334 */
335int
91447636 336nfs_buf_page_inval(vnode_t vp, off_t offset)
55e303ae
A
337{
338 struct nfsbuf *bp;
91447636
A
339 int error = 0;
340
341 lck_mtx_lock(nfs_buf_mutex);
55e303ae
A
342 bp = nfs_buf_incore(vp, ubc_offtoblk(vp, offset));
343 if (!bp)
91447636 344 goto out;
55e303ae 345 FSDBG(325, bp, bp->nb_flags, bp->nb_dirtyoff, bp->nb_dirtyend);
91447636
A
346 if (ISSET(bp->nb_lflags, NBL_BUSY)) {
347 error = EBUSY;
348 goto out;
349 }
55e303ae
A
350 /*
351 * If there's a dirty range in the buffer, check to
352 * see if this page intersects with the dirty range.
353 * If it does, we can't let the pager drop the page.
354 */
355 if (bp->nb_dirtyend > 0) {
356 int start = offset - NBOFF(bp);
357 if (bp->nb_dirtyend <= start ||
358 bp->nb_dirtyoff >= (start + PAGE_SIZE))
91447636
A
359 error = 0;
360 else
361 error = EBUSY;
55e303ae 362 }
91447636
A
363out:
364 lck_mtx_unlock(nfs_buf_mutex);
365 return (error);
55e303ae
A
366}
367
91447636
A
368/*
369 * set up the UPL for a buffer
370 * (must NOT be called with nfs_buf_mutex held)
371 */
55e303ae
A
372int
373nfs_buf_upl_setup(struct nfsbuf *bp)
374{
375 kern_return_t kret;
376 upl_t upl;
91447636 377 int upl_flags;
55e303ae
A
378
379 if (ISSET(bp->nb_flags, NB_PAGELIST))
380 return (0);
381
91447636
A
382 upl_flags = UPL_PRECIOUS;
383 if (! ISSET(bp->nb_flags, NB_READ)) {
384 /*
385 * We're doing a "write", so we intend to modify
386 * the pages we're gathering.
387 */
388 upl_flags |= UPL_WILL_MODIFY;
389 }
55e303ae 390 kret = ubc_create_upl(bp->nb_vp, NBOFF(bp), bp->nb_bufsize,
91447636 391 &upl, NULL, upl_flags);
55e303ae
A
392 if (kret == KERN_INVALID_ARGUMENT) {
393 /* vm object probably doesn't exist any more */
394 bp->nb_pagelist = NULL;
395 return (EINVAL);
396 }
397 if (kret != KERN_SUCCESS) {
398 printf("nfs_buf_upl_setup(): failed to get pagelist %d\n", kret);
399 bp->nb_pagelist = NULL;
400 return (EIO);
401 }
402
403 FSDBG(538, bp, NBOFF(bp), bp->nb_bufsize, bp->nb_vp);
404
55e303ae
A
405 bp->nb_pagelist = upl;
406 SET(bp->nb_flags, NB_PAGELIST);
55e303ae
A
407 return (0);
408}
409
91447636
A
410/*
411 * update buffer's valid/dirty info from UBC
412 * (must NOT be called with nfs_buf_mutex held)
413 */
55e303ae
A
414void
415nfs_buf_upl_check(struct nfsbuf *bp)
416{
417 upl_page_info_t *pl;
418 off_t filesize, fileoffset;
419 int i, npages;
420
421 if (!ISSET(bp->nb_flags, NB_PAGELIST))
422 return;
423
424 npages = round_page_32(bp->nb_bufsize) / PAGE_SIZE;
425 filesize = ubc_getsize(bp->nb_vp);
426 fileoffset = NBOFF(bp);
427 if (fileoffset < filesize)
428 SET(bp->nb_flags, NB_CACHE);
429 else
430 CLR(bp->nb_flags, NB_CACHE);
431
432 pl = ubc_upl_pageinfo(bp->nb_pagelist);
433 bp->nb_valid = bp->nb_dirty = 0;
434
435 for (i=0; i < npages; i++, fileoffset += PAGE_SIZE_64) {
436 /* anything beyond the end of the file is not valid or dirty */
437 if (fileoffset >= filesize)
438 break;
439 if (!upl_valid_page(pl, i)) {
440 CLR(bp->nb_flags, NB_CACHE);
441 continue;
442 }
443 NBPGVALID_SET(bp,i);
444 if (upl_dirty_page(pl, i)) {
445 NBPGDIRTY_SET(bp, i);
446 if (!ISSET(bp->nb_flags, NB_WASDIRTY))
447 SET(bp->nb_flags, NB_WASDIRTY);
448 }
449 }
450 fileoffset = NBOFF(bp);
451 if (ISSET(bp->nb_flags, NB_CACHE)) {
452 bp->nb_validoff = 0;
453 bp->nb_validend = bp->nb_bufsize;
454 if (fileoffset + bp->nb_validend > filesize)
455 bp->nb_validend = filesize - fileoffset;
456 } else {
457 bp->nb_validoff = bp->nb_validend = -1;
458 }
459 FSDBG(539, bp, fileoffset, bp->nb_valid, bp->nb_dirty);
460 FSDBG(539, bp->nb_validoff, bp->nb_validend, bp->nb_dirtyoff, bp->nb_dirtyend);
461}
462
91447636
A
463/*
464 * make sure that a buffer is mapped
465 * (must NOT be called with nfs_buf_mutex held)
466 */
55e303ae
A
467static int
468nfs_buf_map(struct nfsbuf *bp)
469{
470 kern_return_t kret;
471
472 if (bp->nb_data)
473 return (0);
474 if (!ISSET(bp->nb_flags, NB_PAGELIST))
475 return (EINVAL);
476
477 kret = ubc_upl_map(bp->nb_pagelist, (vm_address_t *)&(bp->nb_data));
478 if (kret != KERN_SUCCESS)
479 panic("nfs_buf_map: ubc_upl_map() failed with (%d)", kret);
480 if (bp->nb_data == 0)
481 panic("ubc_upl_map mapped 0");
482 FSDBG(540, bp, bp->nb_flags, NBOFF(bp), bp->nb_data);
483 return (0);
484}
485
486/*
487 * check range of pages in nfsbuf's UPL for validity
488 */
489static int
490nfs_buf_upl_valid_range(struct nfsbuf *bp, int off, int size)
491{
492 off_t fileoffset, filesize;
493 int pg, lastpg;
494 upl_page_info_t *pl;
495
496 if (!ISSET(bp->nb_flags, NB_PAGELIST))
497 return (0);
498 pl = ubc_upl_pageinfo(bp->nb_pagelist);
499
500 size += off & PAGE_MASK;
501 off &= ~PAGE_MASK;
502 fileoffset = NBOFF(bp);
503 filesize = VTONFS(bp->nb_vp)->n_size;
504 if ((fileoffset + off + size) > filesize)
505 size = filesize - (fileoffset + off);
506
507 pg = off/PAGE_SIZE;
508 lastpg = (off + size - 1)/PAGE_SIZE;
509 while (pg <= lastpg) {
510 if (!upl_valid_page(pl, pg))
511 return (0);
512 pg++;
513 }
514 return (1);
515}
516
517/*
518 * normalize an nfsbuf's valid range
519 *
520 * the read/write code guarantees that we'll always have a valid
521 * region that is an integral number of pages. If either end
522 * of the valid range isn't page-aligned, it gets corrected
523 * here as we extend the valid range through all of the
524 * contiguous valid pages.
525 */
526static void
527nfs_buf_normalize_valid_range(struct nfsnode *np, struct nfsbuf *bp)
528{
529 int pg, npg;
530 /* pull validoff back to start of contiguous valid page range */
531 pg = bp->nb_validoff/PAGE_SIZE;
532 while (pg >= 0 && NBPGVALID(bp,pg))
533 pg--;
534 bp->nb_validoff = (pg+1) * PAGE_SIZE;
535 /* push validend forward to end of contiguous valid page range */
536 npg = bp->nb_bufsize/PAGE_SIZE;
537 pg = bp->nb_validend/PAGE_SIZE;
538 while (pg < npg && NBPGVALID(bp,pg))
539 pg++;
540 bp->nb_validend = pg * PAGE_SIZE;
541 /* clip to EOF */
91447636 542 if (NBOFF(bp) + bp->nb_validend > (off_t)np->n_size)
55e303ae
A
543 bp->nb_validend = np->n_size % bp->nb_bufsize;
544}
545
546/*
547 * try to push out some delayed/uncommitted writes
91447636 548 * ("locked" indicates whether nfs_buf_mutex is already held)
55e303ae
A
549 */
550static void
91447636 551nfs_buf_delwri_push(int locked)
55e303ae
A
552{
553 struct nfsbuf *bp;
91447636 554 int i, error;
55e303ae
A
555
556 if (TAILQ_EMPTY(&nfsbufdelwri))
557 return;
558
559 /* first try to tell the nfsiods to do it */
560 if (nfs_asyncio(NULL, NULL) == 0)
561 return;
562
563 /* otherwise, try to do some of the work ourselves */
564 i = 0;
91447636
A
565 if (!locked)
566 lck_mtx_lock(nfs_buf_mutex);
55e303ae
A
567 while (i < 8 && (bp = TAILQ_FIRST(&nfsbufdelwri)) != NULL) {
568 struct nfsnode *np = VTONFS(bp->nb_vp);
569 nfs_buf_remfree(bp);
91447636
A
570 nfs_buf_refget(bp);
571 while ((error = nfs_buf_acquire(bp, 0, 0, 0)) == EAGAIN);
572 nfs_buf_refrele(bp);
573 if (error)
574 break;
575 if (!bp->nb_vp) {
576 /* buffer is no longer valid */
577 nfs_buf_drop(bp);
578 continue;
579 }
8f6c56a5
A
580 if (ISSET(bp->nb_flags, NB_NEEDCOMMIT))
581 nfs_buf_check_write_verifier(np, bp);
55e303ae
A
582 if (ISSET(bp->nb_flags, NB_NEEDCOMMIT)) {
583 /* put buffer at end of delwri list */
584 TAILQ_INSERT_TAIL(&nfsbufdelwri, bp, nb_free);
585 nfsbufdelwricnt++;
91447636
A
586 nfs_buf_drop(bp);
587 lck_mtx_unlock(nfs_buf_mutex);
588 nfs_flushcommits(np->n_vnode, NULL, 1);
55e303ae 589 } else {
91447636
A
590 SET(bp->nb_flags, NB_ASYNC);
591 lck_mtx_unlock(nfs_buf_mutex);
55e303ae
A
592 nfs_buf_write(bp);
593 }
594 i++;
91447636 595 lck_mtx_lock(nfs_buf_mutex);
55e303ae 596 }
91447636
A
597 if (!locked)
598 lck_mtx_unlock(nfs_buf_mutex);
55e303ae
A
599}
600
601/*
91447636
A
602 * Get an nfs buffer.
603 *
604 * Returns errno on error, 0 otherwise.
605 * Any buffer is returned in *bpp.
606 *
607 * If NBLK_ONLYVALID is set, only return buffer if found in cache.
608 * If NBLK_NOWAIT is set, don't wait for the buffer if it's marked BUSY.
609 *
610 * Check for existence of buffer in cache.
611 * Or attempt to reuse a buffer from one of the free lists.
612 * Or allocate a new buffer if we haven't already hit max allocation.
613 * Or wait for a free buffer.
614 *
615 * If available buffer found, prepare it, and return it.
616 *
617 * If the calling process is interrupted by a signal for
618 * an interruptible mount point, return EINTR.
55e303ae 619 */
91447636 620int
55e303ae 621nfs_buf_get(
91447636
A
622 vnode_t vp,
623 daddr64_t blkno,
55e303ae 624 int size,
91447636
A
625 proc_t p,
626 int flags,
627 struct nfsbuf **bpp)
55e303ae
A
628{
629 struct nfsnode *np = VTONFS(vp);
0c530ab8 630 struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
55e303ae 631 struct nfsbuf *bp;
91447636 632 int biosize, bufsize;
55e303ae 633 int slpflag = PCATCH;
91447636
A
634 int operation = (flags & NBLK_OPMASK);
635 int error = 0;
636 struct timespec ts;
55e303ae 637
91447636
A
638 FSDBG_TOP(541, vp, blkno, size, flags);
639 *bpp = NULL;
55e303ae
A
640
641 bufsize = size;
0c530ab8
A
642 if (bufsize > NFS_MAXBSIZE)
643 panic("nfs_buf_get: buffer larger than NFS_MAXBSIZE requested");
55e303ae 644
0c530ab8
A
645 if (!nmp) {
646 FSDBG_BOT(541, vp, blkno, 0, ENXIO);
647 return (ENXIO);
648 }
649 biosize = nmp->nm_biosize;
55e303ae 650
91447636
A
651 if (UBCINVALID(vp) || !UBCINFOEXISTS(vp)) {
652 operation = NBLK_META;
653 } else if (bufsize < biosize) {
55e303ae
A
654 /* reg files should always have biosize blocks */
655 bufsize = biosize;
91447636 656 }
55e303ae 657
91447636
A
658 /* if NBLK_WRITE, check for too many delayed/uncommitted writes */
659 if ((operation == NBLK_WRITE) && (nfs_nbdwrite > ((nfsbufcnt*3)/4))) {
55e303ae
A
660 FSDBG_TOP(542, vp, blkno, nfs_nbdwrite, ((nfsbufcnt*3)/4));
661
662 /* poke the delwri list */
91447636 663 nfs_buf_delwri_push(0);
55e303ae
A
664
665 /* sleep to let other threads run... */
666 tsleep(&nfs_nbdwrite, PCATCH, "nfs_nbdwrite", 1);
667 FSDBG_BOT(542, vp, blkno, nfs_nbdwrite, ((nfsbufcnt*3)/4));
668 }
669
670loop:
91447636 671 lck_mtx_lock(nfs_buf_mutex);
55e303ae
A
672
673 /* check for existence of nfsbuf in cache */
91447636 674 if ((bp = nfs_buf_incore(vp, blkno))) {
55e303ae 675 /* if busy, set wanted and wait */
91447636
A
676 if (ISSET(bp->nb_lflags, NBL_BUSY)) {
677 if (flags & NBLK_NOWAIT) {
678 lck_mtx_unlock(nfs_buf_mutex);
679 FSDBG_BOT(541, vp, blkno, bp, 0xbcbcbcbc);
680 return (0);
681 }
55e303ae 682 FSDBG_TOP(543, vp, blkno, bp, bp->nb_flags);
91447636
A
683 SET(bp->nb_lflags, NBL_WANTED);
684
685 ts.tv_sec = 2;
686 ts.tv_nsec = 0;
687 msleep(bp, nfs_buf_mutex, slpflag|(PRIBIO+1)|PDROP,
688 "nfsbufget", (slpflag == PCATCH) ? 0 : &ts);
55e303ae
A
689 slpflag = 0;
690 FSDBG_BOT(543, vp, blkno, bp, bp->nb_flags);
91447636
A
691 if ((error = nfs_sigintr(VFSTONFS(vnode_mount(vp)), NULL, p))) {
692 FSDBG_BOT(541, vp, blkno, 0, error);
693 return (error);
55e303ae
A
694 }
695 goto loop;
696 }
697 if (bp->nb_bufsize != bufsize)
698 panic("nfsbuf size mismatch");
91447636
A
699 SET(bp->nb_lflags, NBL_BUSY);
700 SET(bp->nb_flags, NB_CACHE);
55e303ae
A
701 nfs_buf_remfree(bp);
702 /* additional paranoia: */
703 if (ISSET(bp->nb_flags, NB_PAGELIST))
704 panic("pagelist buffer was not busy");
705 goto buffer_setup;
706 }
707
91447636
A
708 if (flags & NBLK_ONLYVALID) {
709 lck_mtx_unlock(nfs_buf_mutex);
710 FSDBG_BOT(541, vp, blkno, 0, 0x0000cace);
711 return (0);
712 }
713
55e303ae
A
714 /*
715 * where to get a free buffer:
91447636 716 * - if meta and maxmeta reached, must reuse meta
55e303ae 717 * - alloc new if we haven't reached min bufs
483a1d10
A
718 * - if free lists are NOT empty
719 * - if free list is stale, use it
720 * - else if freemeta list is stale, use it
721 * - else if max bufs allocated, use least-time-to-stale
55e303ae
A
722 * - alloc new if we haven't reached max allowed
723 * - start clearing out delwri list and try again
724 */
725
91447636
A
726 if ((operation == NBLK_META) && (nfsbufmetacnt >= nfsbufmetamax)) {
727 /* if we've hit max meta buffers, must reuse a meta buffer */
728 bp = TAILQ_FIRST(&nfsbuffreemeta);
729 } else if ((nfsbufcnt > nfsbufmin) &&
483a1d10
A
730 (!TAILQ_EMPTY(&nfsbuffree) || !TAILQ_EMPTY(&nfsbuffreemeta))) {
731 /* try to pull an nfsbuf off a free list */
732 struct nfsbuf *lrubp, *metabp;
733 struct timeval now;
734 microuptime(&now);
735
91447636 736 /* if the next LRU or META buffer is invalid or stale, use it */
483a1d10 737 lrubp = TAILQ_FIRST(&nfsbuffree);
91447636
A
738 if (lrubp && (!NBUFSTAMPVALID(lrubp) ||
739 ((lrubp->nb_timestamp + NFSBUF_LRU_STALE) < now.tv_sec)))
483a1d10
A
740 bp = lrubp;
741 metabp = TAILQ_FIRST(&nfsbuffreemeta);
91447636
A
742 if (!bp && metabp && (!NBUFSTAMPVALID(metabp) ||
743 ((metabp->nb_timestamp + NFSBUF_META_STALE) < now.tv_sec)))
483a1d10
A
744 bp = metabp;
745
746 if (!bp && (nfsbufcnt >= nfsbufmax)) {
747 /* we've already allocated all bufs, so */
748 /* choose the buffer that'll go stale first */
749 if (!metabp)
750 bp = lrubp;
751 else if (!lrubp)
752 bp = metabp;
753 else {
754 int32_t lru_stale_time, meta_stale_time;
755 lru_stale_time = lrubp->nb_timestamp + NFSBUF_LRU_STALE;
756 meta_stale_time = metabp->nb_timestamp + NFSBUF_META_STALE;
757 if (lru_stale_time <= meta_stale_time)
758 bp = lrubp;
759 else
760 bp = metabp;
55e303ae 761 }
55e303ae 762 }
91447636 763 }
483a1d10 764
91447636
A
765 if (bp) {
766 /* we have a buffer to reuse */
767 FSDBG(544, vp, blkno, bp, bp->nb_flags);
768 nfs_buf_remfree(bp);
769 if (ISSET(bp->nb_flags, NB_DELWRI))
770 panic("nfs_buf_get: delwri");
771 SET(bp->nb_lflags, NBL_BUSY);
772 /* disassociate buffer from previous vnode */
773 if (bp->nb_vp) {
774 if (bp->nb_vnbufs.le_next != NFSNOLIST) {
775 LIST_REMOVE(bp, nb_vnbufs);
776 bp->nb_vnbufs.le_next = NFSNOLIST;
483a1d10 777 }
91447636
A
778 bp->nb_vp = NULL;
779 }
780 LIST_REMOVE(bp, nb_hash);
781 /* nuke any creds we're holding */
0c530ab8
A
782 if (IS_VALID_CRED(bp->nb_rcred)) {
783 kauth_cred_unref(&bp->nb_rcred);
91447636 784 }
0c530ab8
A
785 if (IS_VALID_CRED(bp->nb_wcred)) {
786 kauth_cred_unref(&bp->nb_wcred);
91447636
A
787 }
788 /* if buf will no longer be NB_META, dump old buffer */
789 if (operation == NBLK_META) {
790 if (!ISSET(bp->nb_flags, NB_META))
791 nfsbufmetacnt++;
792 } else if (ISSET(bp->nb_flags, NB_META)) {
793 if (bp->nb_data) {
794 kfree(bp->nb_data, bp->nb_bufsize);
483a1d10
A
795 bp->nb_data = NULL;
796 }
91447636 797 nfsbufmetacnt--;
55e303ae 798 }
91447636
A
799 /* re-init buf fields */
800 bp->nb_error = 0;
801 bp->nb_validoff = bp->nb_validend = -1;
802 bp->nb_dirtyoff = bp->nb_dirtyend = 0;
803 bp->nb_valid = 0;
804 bp->nb_dirty = 0;
8f6c56a5 805 bp->nb_verf = 0;
91447636
A
806 } else {
807 /* no buffer to reuse */
808 if ((nfsbufcnt < nfsbufmax) &&
809 ((operation != NBLK_META) || (nfsbufmetacnt < nfsbufmetamax))) {
483a1d10
A
810 /* just alloc a new one */
811 MALLOC(bp, struct nfsbuf *, sizeof(struct nfsbuf), M_TEMP, M_WAITOK);
91447636
A
812 if (!bp) {
813 lck_mtx_unlock(nfs_buf_mutex);
814 FSDBG_BOT(541, vp, blkno, 0, error);
815 return (ENOMEM);
816 }
483a1d10 817 nfsbufcnt++;
91447636
A
818 if (operation == NBLK_META)
819 nfsbufmetacnt++;
820 NFSBUFCNTCHK(1);
483a1d10
A
821 /* init nfsbuf */
822 bzero(bp, sizeof(*bp));
823 bp->nb_free.tqe_next = NFSNOLIST;
824 bp->nb_validoff = bp->nb_validend = -1;
825 FSDBG(545, vp, blkno, bp, 0);
826 } else {
827 /* too many bufs... wait for buffers to free up */
828 FSDBG_TOP(546, vp, blkno, nfsbufcnt, nfsbufmax);
55e303ae 829
483a1d10 830 /* poke the delwri list */
91447636 831 nfs_buf_delwri_push(1);
483a1d10
A
832
833 nfsneedbuffer = 1;
91447636
A
834 msleep(&nfsneedbuffer, nfs_buf_mutex, PCATCH|PDROP,
835 "nfsbufget", 0);
483a1d10 836 FSDBG_BOT(546, vp, blkno, nfsbufcnt, nfsbufmax);
91447636
A
837 if ((error = nfs_sigintr(VFSTONFS(vnode_mount(vp)), NULL, p))) {
838 FSDBG_BOT(541, vp, blkno, 0, error);
839 return (error);
483a1d10
A
840 }
841 goto loop;
55e303ae 842 }
55e303ae
A
843 }
844
55e303ae 845 /* setup nfsbuf */
91447636
A
846 bp->nb_lflags = NBL_BUSY;
847 bp->nb_flags = 0;
55e303ae
A
848 bp->nb_lblkno = blkno;
849 /* insert buf in hash */
91447636 850 LIST_INSERT_HEAD(NFSBUFHASH(np, blkno), bp, nb_hash);
55e303ae 851 /* associate buffer with new vnode */
55e303ae
A
852 bp->nb_vp = vp;
853 LIST_INSERT_HEAD(&np->n_cleanblkhd, bp, nb_vnbufs);
854
855buffer_setup:
856
91447636
A
857 /* unlock hash */
858 lck_mtx_unlock(nfs_buf_mutex);
859
55e303ae 860 switch (operation) {
91447636 861 case NBLK_META:
55e303ae
A
862 SET(bp->nb_flags, NB_META);
863 if ((bp->nb_bufsize != bufsize) && bp->nb_data) {
91447636 864 kfree(bp->nb_data, bp->nb_bufsize);
55e303ae
A
865 bp->nb_data = NULL;
866 bp->nb_validoff = bp->nb_validend = -1;
867 bp->nb_dirtyoff = bp->nb_dirtyend = 0;
868 bp->nb_valid = 0;
869 bp->nb_dirty = 0;
870 CLR(bp->nb_flags, NB_CACHE);
871 }
872 if (!bp->nb_data)
91447636
A
873 bp->nb_data = kalloc(bufsize);
874 if (!bp->nb_data) {
875 /* Ack! couldn't allocate the data buffer! */
876 /* cleanup buffer and return error */
877 lck_mtx_lock(nfs_buf_mutex);
878 LIST_REMOVE(bp, nb_vnbufs);
879 bp->nb_vnbufs.le_next = NFSNOLIST;
880 bp->nb_vp = NULL;
881 /* invalidate usage timestamp to allow immediate freeing */
882 NBUFSTAMPINVALIDATE(bp);
883 if (bp->nb_free.tqe_next != NFSNOLIST)
884 panic("nfsbuf on freelist");
885 TAILQ_INSERT_HEAD(&nfsbuffree, bp, nb_free);
886 nfsbuffreecnt++;
887 lck_mtx_unlock(nfs_buf_mutex);
888 FSDBG_BOT(541, vp, blkno, 0xb00, ENOMEM);
889 return (ENOMEM);
890 }
55e303ae
A
891 bp->nb_bufsize = bufsize;
892 break;
893
91447636
A
894 case NBLK_READ:
895 case NBLK_WRITE:
896 /*
897 * Set or clear NB_READ now to let the UPL subsystem know
898 * if we intend to modify the pages or not.
899 */
900 if (operation == NBLK_READ) {
901 SET(bp->nb_flags, NB_READ);
902 } else {
903 CLR(bp->nb_flags, NB_READ);
904 }
55e303ae
A
905 if (bufsize < PAGE_SIZE)
906 bufsize = PAGE_SIZE;
907 bp->nb_bufsize = bufsize;
908 bp->nb_validoff = bp->nb_validend = -1;
909
91447636 910 if (UBCINFOEXISTS(vp)) {
55e303ae
A
911 /* setup upl */
912 if (nfs_buf_upl_setup(bp)) {
913 /* unable to create upl */
914 /* vm object must no longer exist */
91447636
A
915 /* cleanup buffer and return error */
916 lck_mtx_lock(nfs_buf_mutex);
55e303ae
A
917 LIST_REMOVE(bp, nb_vnbufs);
918 bp->nb_vnbufs.le_next = NFSNOLIST;
919 bp->nb_vp = NULL;
91447636
A
920 /* invalidate usage timestamp to allow immediate freeing */
921 NBUFSTAMPINVALIDATE(bp);
55e303ae
A
922 if (bp->nb_free.tqe_next != NFSNOLIST)
923 panic("nfsbuf on freelist");
924 TAILQ_INSERT_HEAD(&nfsbuffree, bp, nb_free);
925 nfsbuffreecnt++;
91447636 926 lck_mtx_unlock(nfs_buf_mutex);
55e303ae 927 FSDBG_BOT(541, vp, blkno, 0x2bc, EIO);
91447636 928 return (EIO);
55e303ae
A
929 }
930 nfs_buf_upl_check(bp);
931 }
932 break;
933
934 default:
935 panic("nfs_buf_get: %d unknown operation", operation);
936 }
937
91447636 938 *bpp = bp;
55e303ae
A
939
940 FSDBG_BOT(541, vp, blkno, bp, bp->nb_flags);
941
91447636 942 return (0);
55e303ae
A
943}
944
945void
483a1d10 946nfs_buf_release(struct nfsbuf *bp, int freeup)
55e303ae 947{
91447636 948 vnode_t vp = bp->nb_vp;
483a1d10 949 struct timeval now;
91447636 950 int wakeup_needbuffer, wakeup_buffer, wakeup_nbdwrite;
55e303ae
A
951
952 FSDBG_TOP(548, bp, NBOFF(bp), bp->nb_flags, bp->nb_data);
953 FSDBG(548, bp->nb_validoff, bp->nb_validend, bp->nb_dirtyoff, bp->nb_dirtyend);
954 FSDBG(548, bp->nb_valid, 0, bp->nb_dirty, 0);
955
956 if (UBCINFOEXISTS(vp) && bp->nb_bufsize) {
957 int upl_flags;
958 upl_t upl;
959 int i, rv;
960
961 if (!ISSET(bp->nb_flags, NB_PAGELIST) && !ISSET(bp->nb_flags, NB_INVAL)) {
962 rv = nfs_buf_upl_setup(bp);
963 if (rv)
964 printf("nfs_buf_release: upl create failed %d\n", rv);
965 else
966 nfs_buf_upl_check(bp);
967 }
968 upl = bp->nb_pagelist;
969 if (!upl)
970 goto pagelist_cleanup_done;
971 if (bp->nb_data) {
972 if (ubc_upl_unmap(upl) != KERN_SUCCESS)
973 panic("ubc_upl_unmap failed");
974 bp->nb_data = NULL;
975 }
0c530ab8
A
976 /* abort pages if error, invalid, or non-needcommit nocache */
977 if ((bp->nb_flags & (NB_ERROR | NB_INVAL)) ||
978 ((bp->nb_flags & NB_NOCACHE) && !(bp->nb_flags & (NB_NEEDCOMMIT | NB_DELWRI)))) {
3a60a9f5 979 if (bp->nb_flags & (NB_READ | NB_INVAL | NB_NOCACHE))
55e303ae
A
980 upl_flags = UPL_ABORT_DUMP_PAGES;
981 else
982 upl_flags = 0;
983 ubc_upl_abort(upl, upl_flags);
984 goto pagelist_cleanup_done;
985 }
986 for (i=0; i <= (bp->nb_bufsize - 1)/PAGE_SIZE; i++) {
987 if (!NBPGVALID(bp,i))
988 ubc_upl_abort_range(upl,
989 i*PAGE_SIZE, PAGE_SIZE,
990 UPL_ABORT_DUMP_PAGES |
991 UPL_ABORT_FREE_ON_EMPTY);
992 else {
993 if (NBPGDIRTY(bp,i))
994 upl_flags = UPL_COMMIT_SET_DIRTY;
995 else
996 upl_flags = UPL_COMMIT_CLEAR_DIRTY;
997 ubc_upl_commit_range(upl,
998 i*PAGE_SIZE, PAGE_SIZE,
999 upl_flags |
1000 UPL_COMMIT_INACTIVATE |
1001 UPL_COMMIT_FREE_ON_EMPTY);
1002 }
1003 }
1004pagelist_cleanup_done:
1005 /* was this the last buffer in the file? */
91447636 1006 if (NBOFF(bp) + bp->nb_bufsize > (off_t)(VTONFS(vp)->n_size)) {
55e303ae 1007 /* if so, invalidate all pages of last buffer past EOF */
91447636
A
1008 off_t start, end;
1009 start = trunc_page_64(VTONFS(vp)->n_size) + PAGE_SIZE_64;
0c530ab8 1010 end = trunc_page_64(NBOFF(bp) + bp->nb_bufsize);
91447636
A
1011 if (end > start) {
1012 if (!(rv = ubc_sync_range(vp, start, end, UBC_INVALIDATE)))
1013 printf("nfs_buf_release(): ubc_sync_range failed!\n");
1014 }
55e303ae
A
1015 }
1016 CLR(bp->nb_flags, NB_PAGELIST);
1017 bp->nb_pagelist = NULL;
1018 }
1019
91447636
A
1020 lck_mtx_lock(nfs_buf_mutex);
1021
1022 wakeup_needbuffer = wakeup_buffer = wakeup_nbdwrite = 0;
1023
55e303ae
A
1024 /* Wake up any processes waiting for any buffer to become free. */
1025 if (nfsneedbuffer) {
1026 nfsneedbuffer = 0;
91447636 1027 wakeup_needbuffer = 1;
55e303ae
A
1028 }
1029 /* Wake up any processes waiting for _this_ buffer to become free. */
91447636
A
1030 if (ISSET(bp->nb_lflags, NBL_WANTED)) {
1031 CLR(bp->nb_lflags, NBL_WANTED);
1032 wakeup_buffer = 1;
55e303ae
A
1033 }
1034
0c530ab8
A
1035 /* If it's non-needcommit nocache, or an error, mark it invalid. */
1036 if (ISSET(bp->nb_flags, NB_ERROR) ||
1037 (ISSET(bp->nb_flags, NB_NOCACHE) && !ISSET(bp->nb_flags, (NB_NEEDCOMMIT | NB_DELWRI))))
55e303ae
A
1038 SET(bp->nb_flags, NB_INVAL);
1039
1040 if ((bp->nb_bufsize <= 0) || ISSET(bp->nb_flags, NB_INVAL)) {
1041 /* If it's invalid or empty, dissociate it from its vnode */
1042 if (bp->nb_vnbufs.le_next != NFSNOLIST) {
1043 LIST_REMOVE(bp, nb_vnbufs);
1044 bp->nb_vnbufs.le_next = NFSNOLIST;
1045 }
1046 bp->nb_vp = NULL;
55e303ae
A
1047 /* if this was a delayed write, wakeup anyone */
1048 /* waiting for delayed writes to complete */
1049 if (ISSET(bp->nb_flags, NB_DELWRI)) {
1050 CLR(bp->nb_flags, NB_DELWRI);
91447636
A
1051 OSAddAtomic(-1, (SInt32*)&nfs_nbdwrite);
1052 NFSBUFCNTCHK(1);
1053 wakeup_nbdwrite = 1;
55e303ae 1054 }
91447636
A
1055 /* invalidate usage timestamp to allow immediate freeing */
1056 NBUFSTAMPINVALIDATE(bp);
55e303ae
A
1057 /* put buffer at head of free list */
1058 if (bp->nb_free.tqe_next != NFSNOLIST)
1059 panic("nfsbuf on freelist");
483a1d10 1060 SET(bp->nb_flags, NB_INVAL);
91447636
A
1061 if (ISSET(bp->nb_flags, NB_META)) {
1062 TAILQ_INSERT_HEAD(&nfsbuffreemeta, bp, nb_free);
1063 nfsbuffreemetacnt++;
1064 } else {
1065 TAILQ_INSERT_HEAD(&nfsbuffree, bp, nb_free);
1066 nfsbuffreecnt++;
1067 }
55e303ae
A
1068 } else if (ISSET(bp->nb_flags, NB_DELWRI)) {
1069 /* put buffer at end of delwri list */
1070 if (bp->nb_free.tqe_next != NFSNOLIST)
1071 panic("nfsbuf on freelist");
1072 TAILQ_INSERT_TAIL(&nfsbufdelwri, bp, nb_free);
1073 nfsbufdelwricnt++;
91447636 1074 freeup = 0;
55e303ae 1075 } else {
483a1d10
A
1076 /* update usage timestamp */
1077 microuptime(&now);
1078 bp->nb_timestamp = now.tv_sec;
55e303ae
A
1079 /* put buffer at end of free list */
1080 if (bp->nb_free.tqe_next != NFSNOLIST)
1081 panic("nfsbuf on freelist");
483a1d10
A
1082 if (ISSET(bp->nb_flags, NB_META)) {
1083 TAILQ_INSERT_TAIL(&nfsbuffreemeta, bp, nb_free);
1084 nfsbuffreemetacnt++;
1085 } else {
1086 TAILQ_INSERT_TAIL(&nfsbuffree, bp, nb_free);
1087 nfsbuffreecnt++;
1088 }
55e303ae
A
1089 }
1090
91447636 1091 NFSBUFCNTCHK(1);
55e303ae
A
1092
1093 /* Unlock the buffer. */
0c530ab8 1094 CLR(bp->nb_flags, (NB_ASYNC | NB_STABLE | NB_IOD));
91447636 1095 CLR(bp->nb_lflags, NBL_BUSY);
55e303ae
A
1096
1097 FSDBG_BOT(548, bp, NBOFF(bp), bp->nb_flags, bp->nb_data);
91447636
A
1098
1099 lck_mtx_unlock(nfs_buf_mutex);
1100
1101 if (wakeup_needbuffer)
1102 wakeup(&nfsneedbuffer);
1103 if (wakeup_buffer)
1104 wakeup(bp);
1105 if (wakeup_nbdwrite)
1106 wakeup(&nfs_nbdwrite);
1107 if (freeup)
1108 NFS_BUF_FREEUP();
55e303ae
A
1109}
1110
1111/*
1112 * Wait for operations on the buffer to complete.
1113 * When they do, extract and return the I/O's error value.
1114 */
1115int
1116nfs_buf_iowait(struct nfsbuf *bp)
1117{
1118 FSDBG_TOP(549, bp, NBOFF(bp), bp->nb_flags, bp->nb_error);
1119
91447636
A
1120 lck_mtx_lock(nfs_buf_mutex);
1121
55e303ae 1122 while (!ISSET(bp->nb_flags, NB_DONE))
91447636
A
1123 msleep(bp, nfs_buf_mutex, PRIBIO + 1, "nfs_buf_iowait", 0);
1124
1125 lck_mtx_unlock(nfs_buf_mutex);
55e303ae
A
1126
1127 FSDBG_BOT(549, bp, NBOFF(bp), bp->nb_flags, bp->nb_error);
1128
1129 /* check for interruption of I/O, then errors. */
1130 if (ISSET(bp->nb_flags, NB_EINTR)) {
1131 CLR(bp->nb_flags, NB_EINTR);
1132 return (EINTR);
1133 } else if (ISSET(bp->nb_flags, NB_ERROR))
1134 return (bp->nb_error ? bp->nb_error : EIO);
1135 return (0);
1136}
1137
1138/*
1139 * Mark I/O complete on a buffer.
1140 */
1141void
1142nfs_buf_iodone(struct nfsbuf *bp)
1143{
55e303ae
A
1144
1145 FSDBG_TOP(550, bp, NBOFF(bp), bp->nb_flags, bp->nb_error);
1146
1147 if (ISSET(bp->nb_flags, NB_DONE))
1148 panic("nfs_buf_iodone already");
55e303ae
A
1149 /*
1150 * I/O was done, so don't believe
1151 * the DIRTY state from VM anymore
1152 */
1153 CLR(bp->nb_flags, NB_WASDIRTY);
1154
1155 if (!ISSET(bp->nb_flags, NB_READ)) {
1156 CLR(bp->nb_flags, NB_WRITEINPROG);
91447636
A
1157 /*
1158 * vnode_writedone() takes care of waking up
1159 * any throttled write operations
1160 */
1161 vnode_writedone(bp->nb_vp);
55e303ae 1162 }
91447636
A
1163 if (ISSET(bp->nb_flags, NB_ASYNC)) { /* if async, release it */
1164 SET(bp->nb_flags, NB_DONE); /* note that it's done */
483a1d10 1165 nfs_buf_release(bp, 1);
91447636
A
1166 } else { /* or just wakeup the buffer */
1167 lck_mtx_lock(nfs_buf_mutex);
1168 SET(bp->nb_flags, NB_DONE); /* note that it's done */
1169 CLR(bp->nb_lflags, NBL_WANTED);
1170 lck_mtx_unlock(nfs_buf_mutex);
55e303ae
A
1171 wakeup(bp);
1172 }
1173
1174 FSDBG_BOT(550, bp, NBOFF(bp), bp->nb_flags, bp->nb_error);
1175}
1176
1177void
91447636 1178nfs_buf_write_delayed(struct nfsbuf *bp, proc_t p)
55e303ae 1179{
91447636 1180 vnode_t vp = bp->nb_vp;
55e303ae
A
1181
1182 FSDBG_TOP(551, bp, NBOFF(bp), bp->nb_flags, 0);
1183 FSDBG(551, bp, bp->nb_dirtyoff, bp->nb_dirtyend, bp->nb_dirty);
1184
1185 /*
1186 * If the block hasn't been seen before:
1187 * (1) Mark it as having been seen,
1188 * (2) Charge for the write.
1189 * (3) Make sure it's on its vnode's correct block list,
1190 */
1191 if (!ISSET(bp->nb_flags, NB_DELWRI)) {
1192 SET(bp->nb_flags, NB_DELWRI);
1193 if (p && p->p_stats)
1194 p->p_stats->p_ru.ru_oublock++; /* XXX */
91447636
A
1195 OSAddAtomic(1, (SInt32*)&nfs_nbdwrite);
1196 NFSBUFCNTCHK(0);
55e303ae 1197 /* move to dirty list */
91447636 1198 lck_mtx_lock(nfs_buf_mutex);
55e303ae
A
1199 if (bp->nb_vnbufs.le_next != NFSNOLIST)
1200 LIST_REMOVE(bp, nb_vnbufs);
1201 LIST_INSERT_HEAD(&VTONFS(vp)->n_dirtyblkhd, bp, nb_vnbufs);
91447636 1202 lck_mtx_unlock(nfs_buf_mutex);
55e303ae
A
1203 }
1204
1205 /*
1206 * If the vnode has "too many" write operations in progress
1207 * wait for them to finish the IO
1208 */
91447636 1209 (void)vnode_waitforwrites(vp, VNODE_ASYNC_THROTTLE, 0, 0, "nfs_buf_write_delayed");
55e303ae
A
1210
1211 /*
1212 * If we have too many delayed write buffers,
1213 * more than we can "safely" handle, just fall back to
1214 * doing the async write
1215 */
1216 if (nfs_nbdwrite < 0)
1217 panic("nfs_buf_write_delayed: Negative nfs_nbdwrite");
1218
1219 if (nfs_nbdwrite > ((nfsbufcnt/4)*3)) {
1220 /* issue async write */
1221 SET(bp->nb_flags, NB_ASYNC);
1222 nfs_buf_write(bp);
1223 FSDBG_BOT(551, bp, NBOFF(bp), bp->nb_flags, bp->nb_error);
1224 return;
1225 }
1226
1227 /* Otherwise, the "write" is done, so mark and release the buffer. */
1228 SET(bp->nb_flags, NB_DONE);
483a1d10 1229 nfs_buf_release(bp, 1);
55e303ae
A
1230 FSDBG_BOT(551, bp, NBOFF(bp), bp->nb_flags, 0);
1231 return;
1232}
1233
8f6c56a5
A
1234/*
1235 * Check that a "needcommit" buffer can still be committed.
1236 * If the write verifier has changed, we need to clear the
1237 * the needcommit flag.
1238 */
1239void
1240nfs_buf_check_write_verifier(struct nfsnode *np, struct nfsbuf *bp)
1241{
1242 struct nfsmount *nmp;
1243
1244 if (!ISSET(bp->nb_flags, NB_NEEDCOMMIT))
1245 return;
1246
1247 nmp = VFSTONFS(vnode_mount(NFSTOV(np)));
1248 if (!nmp || (bp->nb_verf == nmp->nm_verf))
1249 return;
1250
1251 /* write verifier changed, clear commit flag */
1252 bp->nb_flags &= ~NB_NEEDCOMMIT;
1253 np->n_needcommitcnt--;
1254 CHECK_NEEDCOMMITCNT(np);
1255}
1256
91447636
A
1257/*
1258 * add a reference to a buffer so it doesn't disappear while being used
1259 * (must be called with nfs_buf_mutex held)
1260 */
1261void
1262nfs_buf_refget(struct nfsbuf *bp)
1263{
1264 bp->nb_refs++;
1265}
1266/*
1267 * release a reference on a buffer
1268 * (must be called with nfs_buf_mutex held)
1269 */
1270void
1271nfs_buf_refrele(struct nfsbuf *bp)
1272{
1273 bp->nb_refs--;
1274}
1275
1276/*
1277 * mark a particular buffer as BUSY
1278 * (must be called with nfs_buf_mutex held)
1279 */
1280errno_t
1281nfs_buf_acquire(struct nfsbuf *bp, int flags, int slpflag, int slptimeo)
1282{
1283 errno_t error;
1284 struct timespec ts;
1285
1286 if (ISSET(bp->nb_lflags, NBL_BUSY)) {
1287 /*
1288 * since the mutex_lock may block, the buffer
1289 * may become BUSY, so we need to recheck for
1290 * a NOWAIT request
1291 */
1292 if (flags & NBAC_NOWAIT)
1293 return (EBUSY);
1294 SET(bp->nb_lflags, NBL_WANTED);
1295
1296 ts.tv_sec = (slptimeo/100);
1297 /* the hz value is 100; which leads to 10ms */
1298 ts.tv_nsec = (slptimeo % 100) * 10 * NSEC_PER_USEC * 1000;
1299
1300 error = msleep(bp, nfs_buf_mutex, slpflag | (PRIBIO + 1),
1301 "nfs_buf_acquire", &ts);
1302 if (error)
1303 return (error);
1304 return (EAGAIN);
1305 }
1306 if (flags & NBAC_REMOVE)
1307 nfs_buf_remfree(bp);
1308 SET(bp->nb_lflags, NBL_BUSY);
1309
1310 return (0);
1311}
1312
1313/*
1314 * simply drop the BUSY status of a buffer
1315 * (must be called with nfs_buf_mutex held)
1316 */
1317void
1318nfs_buf_drop(struct nfsbuf *bp)
1319{
1320 int need_wakeup = 0;
1321
1322 if (!ISSET(bp->nb_lflags, NBL_BUSY))
1323 panic("nfs_buf_drop: buffer not busy!");
1324 if (ISSET(bp->nb_lflags, NBL_WANTED)) {
1325 /*
1326 * delay the actual wakeup until after we
1327 * clear NBL_BUSY and we've dropped nfs_buf_mutex
1328 */
1329 need_wakeup = 1;
1330 }
1331 /* Unlock the buffer. */
1332 CLR(bp->nb_lflags, (NBL_BUSY | NBL_WANTED));
1333
1334 if (need_wakeup)
1335 wakeup(bp);
1336}
1337
1338/*
1339 * prepare for iterating over an nfsnode's buffer list
1340 * this lock protects the queue manipulation
1341 * (must be called with nfs_buf_mutex held)
1342 */
1343int
1344nfs_buf_iterprepare(struct nfsnode *np, struct nfsbuflists *iterheadp, int flags)
1345{
1346 struct nfsbuflists *listheadp;
1347
1348 if (flags & NBI_DIRTY)
1349 listheadp = &np->n_dirtyblkhd;
1350 else
1351 listheadp = &np->n_cleanblkhd;
1352
1353 if ((flags & NBI_NOWAIT) && (np->n_bufiterflags & NBI_ITER)) {
1354 LIST_INIT(iterheadp);
1355 return(EWOULDBLOCK);
1356 }
1357
1358 while (np->n_bufiterflags & NBI_ITER) {
1359 np->n_bufiterflags |= NBI_ITERWANT;
1360 msleep(&np->n_bufiterflags, nfs_buf_mutex, 0, "nfs_buf_iterprepare", 0);
1361 }
1362 if (LIST_EMPTY(listheadp)) {
1363 LIST_INIT(iterheadp);
1364 return(EINVAL);
1365 }
1366 np->n_bufiterflags |= NBI_ITER;
1367
1368 iterheadp->lh_first = listheadp->lh_first;
1369 listheadp->lh_first->nb_vnbufs.le_prev = &iterheadp->lh_first;
1370 LIST_INIT(listheadp);
1371
1372 return(0);
1373}
1374
1375/*
1376 * cleanup after iterating over an nfsnode's buffer list
1377 * this lock protects the queue manipulation
1378 * (must be called with nfs_buf_mutex held)
1379 */
1380void
1381nfs_buf_itercomplete(struct nfsnode *np, struct nfsbuflists *iterheadp, int flags)
1382{
1383 struct nfsbuflists * listheadp;
1384 struct nfsbuf *bp;
1385
1386 if (flags & NBI_DIRTY)
1387 listheadp = &np->n_dirtyblkhd;
1388 else
1389 listheadp = &np->n_cleanblkhd;
1390
1391 while (!LIST_EMPTY(iterheadp)) {
1392 bp = LIST_FIRST(iterheadp);
1393 LIST_REMOVE(bp, nb_vnbufs);
1394 LIST_INSERT_HEAD(listheadp, bp, nb_vnbufs);
1395 }
1396
1397 np->n_bufiterflags &= ~NBI_ITER;
1398 if (np->n_bufiterflags & NBI_ITERWANT) {
1399 np->n_bufiterflags &= ~NBI_ITERWANT;
1400 wakeup(&np->n_bufiterflags);
1401 }
1402}
1403
1c79356b
A
1404
1405/*
1406 * Vnode op for read using bio
1407 * Any similarity to readip() is purely coincidental
1408 */
1409int
91447636
A
1410nfs_bioread(
1411 vnode_t vp,
1412 struct uio *uio,
1413 __unused int ioflag,
1414 kauth_cred_t cred,
1415 proc_t p)
1c79356b 1416{
55e303ae 1417 struct nfsnode *np = VTONFS(vp);
91447636 1418 int biosize;
b4c24cb9 1419 off_t diff;
91447636
A
1420 struct nfsbuf *bp = NULL, *rabp;
1421 struct nfs_vattr nvattr;
1422 struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
1423 daddr64_t lbn, rabn, lastrabn = -1, tlbn;
1c79356b 1424 int bufsize;
55e303ae 1425 int nra, error = 0, n = 0, on = 0;
55e303ae 1426 caddr_t dp;
91447636
A
1427 struct dirent *direntp = NULL;
1428 enum vtype vtype;
1429 int nocachereadahead = 0;
55e303ae 1430
91447636 1431 FSDBG_TOP(514, vp, uio->uio_offset, uio_uio_resid(uio), ioflag);
1c79356b
A
1432
1433#if DIAGNOSTIC
1434 if (uio->uio_rw != UIO_READ)
1435 panic("nfs_read mode");
1436#endif
91447636 1437 if (uio_uio_resid(uio) == 0) {
55e303ae 1438 FSDBG_BOT(514, vp, 0xd1e0001, 0, 0);
1c79356b 1439 return (0);
55e303ae
A
1440 }
1441 if (uio->uio_offset < 0) {
1442 FSDBG_BOT(514, vp, 0xd1e0002, 0, EINVAL);
1c79356b 1443 return (EINVAL);
55e303ae 1444 }
91447636 1445
0c530ab8 1446 biosize = nmp->nm_biosize;
91447636
A
1447 if ((nmp->nm_flag & NFSMNT_NFSV3) && !(nmp->nm_state & NFSSTA_GOTFSINFO))
1448 nfs_fsinfo(nmp, vp, cred, p);
0c530ab8 1449
91447636 1450 vtype = vnode_vtype(vp);
1c79356b
A
1451 /*
1452 * For nfs, cache consistency can only be maintained approximately.
1453 * Although RFC1094 does not specify the criteria, the following is
1454 * believed to be compatible with the reference port.
1c79356b
A
1455 * For nfs:
1456 * If the file's modify time on the server has changed since the
1457 * last read rpc or you have written to the file,
1458 * you may have lost data cache consistency with the
1459 * server, so flush all of the file's data out of the cache.
1460 * Then force a getattr rpc to ensure that you have up to date
1461 * attributes.
1462 * NB: This implies that cache data can be read when up to
ab86ba33 1463 * NFS_MAXATTRTIMEO seconds out of date. If you find that you need
91447636
A
1464 * current attributes this could be forced by setting calling
1465 * NATTRINVALIDATE() before the nfs_getattr() call.
1c79356b 1466 */
91447636
A
1467 if (np->n_flag & NNEEDINVALIDATE) {
1468 np->n_flag &= ~NNEEDINVALIDATE;
1469 nfs_vinvalbuf(vp, V_SAVE|V_IGNORE_WRITEERR, cred, p, 1);
1470 }
1471 if (np->n_flag & NMODIFIED) {
1472 if (vtype != VREG) {
1473 if (vtype != VDIR)
1474 panic("nfs: bioread, not dir");
1475 nfs_invaldir(vp);
1476 error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
55e303ae 1477 if (error) {
91447636 1478 FSDBG_BOT(514, vp, 0xd1e0003, 0, error);
1c79356b 1479 return (error);
55e303ae 1480 }
91447636
A
1481 }
1482 NATTRINVALIDATE(np);
1483 error = nfs_getattr(vp, &nvattr, cred, p);
1484 if (error) {
1485 FSDBG_BOT(514, vp, 0xd1e0004, 0, error);
1486 return (error);
1487 }
1488 if (vtype == VDIR) {
1489 /* if directory changed, purge any name cache entries */
1490 if (nfstimespeccmp(&np->n_ncmtime, &nvattr.nva_mtime, !=))
1491 cache_purge(vp);
1492 np->n_ncmtime = nvattr.nva_mtime;
1493 }
1494 np->n_mtime = nvattr.nva_mtime;
1495 } else {
1496 error = nfs_getattr(vp, &nvattr, cred, p);
1497 if (error) {
1498 FSDBG_BOT(514, vp, 0xd1e0005, 0, error);
1499 return (error);
1500 }
1501 if (nfstimespeccmp(&np->n_mtime, &nvattr.nva_mtime, !=)) {
1502 if (vtype == VDIR) {
1503 nfs_invaldir(vp);
1504 /* purge name cache entries */
1505 if (nfstimespeccmp(&np->n_ncmtime, &nvattr.nva_mtime, !=))
483a1d10 1506 cache_purge(vp);
483a1d10 1507 }
91447636 1508 error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
55e303ae 1509 if (error) {
91447636 1510 FSDBG_BOT(514, vp, 0xd1e0006, 0, error);
1c79356b 1511 return (error);
55e303ae 1512 }
91447636
A
1513 if (vtype == VDIR)
1514 np->n_ncmtime = nvattr.nva_mtime;
1515 np->n_mtime = nvattr.nva_mtime;
1516 }
1517 }
1518
1519 if (vnode_isnocache(vp)) {
1520 if (!(np->n_flag & NNOCACHE)) {
1521 if (NVALIDBUFS(np)) {
1c79356b 1522 error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
55e303ae 1523 if (error) {
91447636 1524 FSDBG_BOT(514, vp, 0xd1e000a, 0, error);
1c79356b 1525 return (error);
55e303ae 1526 }
1c79356b 1527 }
91447636 1528 np->n_flag |= NNOCACHE;
1c79356b 1529 }
91447636
A
1530 } else if (np->n_flag & NNOCACHE) {
1531 np->n_flag &= ~NNOCACHE;
1c79356b 1532 }
1c79356b 1533
91447636
A
1534 do {
1535 if (np->n_flag & NNOCACHE) {
1536 switch (vtype) {
1537 case VREG:
1538 /*
1539 * If we have only a block or so to read,
1540 * just do the rpc directly.
1541 * If we have a couple blocks or more to read,
1542 * then we'll take advantage of readahead within
1543 * this loop to try to fetch all the data in parallel
1544 */
1545 if (!nocachereadahead && (uio_uio_resid(uio) < 2*biosize)) {
1546 error = nfs_readrpc(vp, uio, cred, p);
1547 FSDBG_BOT(514, vp, uio->uio_offset, uio_uio_resid(uio), error);
55e303ae
A
1548 return (error);
1549 }
91447636
A
1550 nocachereadahead = 1;
1551 break;
1c79356b 1552 case VLNK:
91447636
A
1553 error = nfs_readlinkrpc(vp, uio, cred, p);
1554 FSDBG_BOT(514, vp, uio->uio_offset, uio_uio_resid(uio), error);
55e303ae 1555 return (error);
1c79356b
A
1556 case VDIR:
1557 break;
1558 default:
91447636 1559 printf(" NFSNOCACHE: type %x unexpected\n", vtype);
1c79356b
A
1560 };
1561 }
91447636 1562 switch (vtype) {
1c79356b 1563 case VREG:
1c79356b 1564 lbn = uio->uio_offset / biosize;
55e303ae
A
1565
1566 /*
1567 * Copy directly from any cached pages without grabbing the bufs.
91447636
A
1568 *
1569 * Note: for "nocache" reads, we don't copy directly from UBC
1570 * because any cached pages will be for readahead buffers that
1571 * need to be invalidated anyway before we finish this request.
55e303ae 1572 */
91447636
A
1573 if (!(np->n_flag & NNOCACHE) &&
1574 (uio->uio_segflg == UIO_USERSPACE32 ||
1575 uio->uio_segflg == UIO_USERSPACE64 ||
1576 uio->uio_segflg == UIO_USERSPACE)) {
1577 // LP64todo - fix this!
1578 int io_resid = uio_uio_resid(uio);
55e303ae
A
1579 diff = np->n_size - uio->uio_offset;
1580 if (diff < io_resid)
1581 io_resid = diff;
1582 if (io_resid > 0) {
1583 error = cluster_copy_ubc_data(vp, uio, &io_resid, 0);
1584 if (error) {
1585 FSDBG_BOT(514, vp, uio->uio_offset, 0xcacefeed, error);
1586 return (error);
1587 }
1588 }
1589 /* count any biocache reads that we just copied directly */
1590 if (lbn != uio->uio_offset / biosize) {
91447636 1591 OSAddAtomic((uio->uio_offset / biosize) - lbn, (SInt32*)&nfsstats.biocache_reads);
55e303ae
A
1592 FSDBG(514, vp, 0xcacefeed, uio->uio_offset, error);
1593 }
1594 }
1595
1596 lbn = uio->uio_offset / biosize;
1597 on = uio->uio_offset % biosize;
1c79356b
A
1598
1599 /*
1600 * Start the read ahead(s), as required.
1601 */
1602 if (nfs_numasync > 0 && nmp->nm_readahead > 0) {
55e303ae 1603 for (nra = 0; nra < nmp->nm_readahead; nra++) {
1c79356b 1604 rabn = lbn + 1 + nra;
55e303ae
A
1605 if (rabn <= lastrabn) {
1606 /* we've already (tried to) read this block */
1607 /* no need to try it again... */
1608 continue;
1c79356b 1609 }
55e303ae 1610 lastrabn = rabn;
91447636
A
1611 if ((off_t)rabn * biosize >= (off_t)np->n_size)
1612 break;
1613 if ((np->n_flag & NNOCACHE) &&
1614 (((off_t)rabn * biosize) >= (uio->uio_offset + uio_uio_resid(uio))))
1615 /* for uncached readahead, don't go beyond end of request */
55e303ae
A
1616 break;
1617 /* check if block exists and is valid. */
91447636
A
1618 error = nfs_buf_get(vp, rabn, biosize, p, NBLK_READ|NBLK_NOWAIT, &rabp);
1619 if (error) {
1620 FSDBG_BOT(514, vp, 0xd1e000b, 1, error);
1621 return (error);
1622 }
1623 if (!rabp)
1624 continue;
1625 if (nfs_buf_upl_valid_range(rabp, 0, rabp->nb_bufsize)) {
1626 nfs_buf_release(rabp, 1);
55e303ae 1627 continue;
55e303ae
A
1628 }
1629 if (!ISSET(rabp->nb_flags, (NB_CACHE|NB_DELWRI))) {
1630 SET(rabp->nb_flags, (NB_READ|NB_ASYNC));
1631 if (nfs_asyncio(rabp, cred)) {
1632 SET(rabp->nb_flags, (NB_INVAL|NB_ERROR));
1633 rabp->nb_error = EIO;
483a1d10 1634 nfs_buf_release(rabp, 1);
55e303ae
A
1635 }
1636 } else
483a1d10 1637 nfs_buf_release(rabp, 1);
55e303ae 1638 }
1c79356b
A
1639 }
1640
91447636
A
1641 if ((uio_uio_resid(uio) <= 0) || (uio->uio_offset >= (off_t)np->n_size)) {
1642 FSDBG_BOT(514, vp, uio->uio_offset, uio_uio_resid(uio), 0xaaaaaaaa);
55e303ae
A
1643 return (0);
1644 }
1645
91447636 1646 OSAddAtomic(1, (SInt32*)&nfsstats.biocache_reads);
55e303ae 1647
1c79356b
A
1648 /*
1649 * If the block is in the cache and has the required data
1650 * in a valid region, just copy it out.
1651 * Otherwise, get the block and write back/read in,
1652 * as required.
1653 */
1654again:
1655 bufsize = biosize;
91447636
A
1656 // LP64todo - fix this!
1657 n = min((unsigned)(bufsize - on), uio_uio_resid(uio));
1c79356b
A
1658 diff = np->n_size - uio->uio_offset;
1659 if (diff < n)
1660 n = diff;
55e303ae 1661
91447636
A
1662 error = nfs_buf_get(vp, lbn, bufsize, p, NBLK_READ, &bp);
1663 if (error) {
55e303ae
A
1664 FSDBG_BOT(514, vp, 0xd1e000c, 0, EINTR);
1665 return (EINTR);
1666 }
1667
1668 /* if any pages are valid... */
1669 if (bp->nb_valid) {
1670 /* ...check for any invalid pages in the read range */
1671 int pg, firstpg, lastpg, dirtypg;
1672 dirtypg = firstpg = lastpg = -1;
1673 pg = on/PAGE_SIZE;
1674 while (pg <= (on + n - 1)/PAGE_SIZE) {
1675 if (!NBPGVALID(bp,pg)) {
1676 if (firstpg < 0)
1677 firstpg = pg;
1678 lastpg = pg;
1679 } else if (firstpg >= 0 && dirtypg < 0 && NBPGDIRTY(bp,pg))
1680 dirtypg = pg;
1681 pg++;
1682 }
1683
1684 /* if there are no invalid pages, we're all set */
1685 if (firstpg < 0) {
1686 if (bp->nb_validoff < 0) {
1687 /* valid range isn't set up, so */
1688 /* set it to what we know is valid */
91447636
A
1689 bp->nb_validoff = trunc_page(on);
1690 bp->nb_validend = round_page(on+n);
55e303ae
A
1691 nfs_buf_normalize_valid_range(np, bp);
1692 }
1693 goto buffer_ready;
1694 }
1695
1696 /* there are invalid pages in the read range */
1697 if ((dirtypg > firstpg) && (dirtypg < lastpg)) {
1698 /* there are also dirty page(s) in the range, */
1699 /* so write the buffer out and try again */
1700 CLR(bp->nb_flags, (NB_DONE | NB_ERROR | NB_INVAL));
1701 SET(bp->nb_flags, NB_ASYNC);
0c530ab8 1702 if (!IS_VALID_CRED(bp->nb_wcred)) {
91447636
A
1703 kauth_cred_ref(cred);
1704 bp->nb_wcred = cred;
1705 }
55e303ae
A
1706 error = nfs_buf_write(bp);
1707 if (error) {
1708 FSDBG_BOT(514, vp, 0xd1e000d, 0, error);
1709 return (error);
1710 }
1c79356b
A
1711 goto again;
1712 }
55e303ae
A
1713 if (!bp->nb_dirty && bp->nb_dirtyend <= 0 &&
1714 (lastpg - firstpg + 1) > (bufsize/PAGE_SIZE)/2) {
1715 /* we need to read in more than half the buffer and the */
1716 /* buffer's not dirty, so just fetch the whole buffer */
1717 bp->nb_valid = 0;
1718 } else {
1719 /* read the page range in */
91447636
A
1720 uio_t auio;
1721 char uio_buf[ UIO_SIZEOF(1) ];
1722
55e303ae 1723 NFS_BUF_MAP(bp);
91447636
A
1724 auio = uio_createwithbuffer(1, (NBOFF(bp) + firstpg * PAGE_SIZE_64),
1725 UIO_SYSSPACE, UIO_READ, &uio_buf[0], sizeof(uio_buf));
1726 if (!auio) {
1727 error = ENOMEM;
1728 } else {
1729 uio_addiov(auio, CAST_USER_ADDR_T((bp->nb_data + firstpg * PAGE_SIZE)),
1730 ((lastpg - firstpg + 1) * PAGE_SIZE));
1731 error = nfs_readrpc(vp, auio, cred, p);
1732 }
55e303ae 1733 if (error) {
91447636
A
1734 if (np->n_flag & NNOCACHE)
1735 SET(bp->nb_flags, NB_NOCACHE);
483a1d10 1736 nfs_buf_release(bp, 1);
55e303ae
A
1737 FSDBG_BOT(514, vp, 0xd1e000e, 0, error);
1738 return (error);
1739 }
1740 /* Make sure that the valid range is set to cover this read. */
1741 bp->nb_validoff = trunc_page_32(on);
1742 bp->nb_validend = round_page_32(on+n);
1743 nfs_buf_normalize_valid_range(np, bp);
91447636 1744 if (uio_resid(auio) > 0) {
55e303ae
A
1745 /* if short read, must have hit EOF, */
1746 /* so zero the rest of the range */
91447636 1747 bzero(CAST_DOWN(caddr_t, uio_curriovbase(auio)), uio_resid(auio));
55e303ae
A
1748 }
1749 /* mark the pages (successfully read) as valid */
1750 for (pg=firstpg; pg <= lastpg; pg++)
1751 NBPGVALID_SET(bp,pg);
1752 }
1c79356b 1753 }
55e303ae
A
1754 /* if no pages are valid, read the whole block */
1755 if (!bp->nb_valid) {
1756 SET(bp->nb_flags, NB_READ);
1757 CLR(bp->nb_flags, (NB_DONE | NB_ERROR | NB_INVAL));
1758 error = nfs_doio(bp, cred, p);
1759 if (error) {
91447636
A
1760 if (np->n_flag & NNOCACHE)
1761 SET(bp->nb_flags, NB_NOCACHE);
483a1d10 1762 nfs_buf_release(bp, 1);
55e303ae
A
1763 FSDBG_BOT(514, vp, 0xd1e000f, 0, error);
1764 return (error);
1765 }
1766 }
1767buffer_ready:
55e303ae
A
1768 /* validate read range against valid range and clip */
1769 if (bp->nb_validend > 0) {
1770 diff = (on >= bp->nb_validend) ? 0 : (bp->nb_validend - on);
1771 if (diff < n)
1772 n = diff;
1773 }
1774 if (n > 0)
1775 NFS_BUF_MAP(bp);
1c79356b
A
1776 break;
1777 case VLNK:
91447636
A
1778 OSAddAtomic(1, (SInt32*)&nfsstats.biocache_readlinks);
1779 error = nfs_buf_get(vp, 0, NFS_MAXPATHLEN, p, NBLK_READ, &bp);
1780 if (error) {
1781 FSDBG_BOT(514, vp, 0xd1e0010, 0, error);
1782 return (error);
55e303ae
A
1783 }
1784 if (!ISSET(bp->nb_flags, NB_CACHE)) {
1785 SET(bp->nb_flags, NB_READ);
1c79356b
A
1786 error = nfs_doio(bp, cred, p);
1787 if (error) {
55e303ae 1788 SET(bp->nb_flags, NB_ERROR);
483a1d10 1789 nfs_buf_release(bp, 1);
55e303ae 1790 FSDBG_BOT(514, vp, 0xd1e0011, 0, error);
1c79356b
A
1791 return (error);
1792 }
1793 }
91447636
A
1794 // LP64todo - fix this!
1795 n = min(uio_uio_resid(uio), bp->nb_validend);
1c79356b
A
1796 on = 0;
1797 break;
1798 case VDIR:
91447636 1799 OSAddAtomic(1, (SInt32*)&nfsstats.biocache_readdirs);
55e303ae
A
1800 if (np->n_direofoffset && uio->uio_offset >= np->n_direofoffset) {
1801 FSDBG_BOT(514, vp, 0xde0f0001, 0, 0);
1802 return (0);
1c79356b
A
1803 }
1804 lbn = uio->uio_offset / NFS_DIRBLKSIZ;
1805 on = uio->uio_offset & (NFS_DIRBLKSIZ - 1);
91447636
A
1806 error = nfs_buf_get(vp, lbn, NFS_DIRBLKSIZ, p, NBLK_READ, &bp);
1807 if (error) {
1808 FSDBG_BOT(514, vp, 0xd1e0012, 0, error);
1809 return (error);
55e303ae
A
1810 }
1811 if (!ISSET(bp->nb_flags, NB_CACHE)) {
1812 SET(bp->nb_flags, NB_READ);
1c79356b
A
1813 error = nfs_doio(bp, cred, p);
1814 if (error) {
483a1d10 1815 nfs_buf_release(bp, 1);
1c79356b 1816 }
fa4905b1
A
1817 while (error == NFSERR_BAD_COOKIE) {
1818 nfs_invaldir(vp);
1819 error = nfs_vinvalbuf(vp, 0, cred, p, 1);
1820 /*
1821 * Yuck! The directory has been modified on the
1822 * server. The only way to get the block is by
1823 * reading from the beginning to get all the
1824 * offset cookies.
1825 */
91447636 1826 for (tlbn = 0; tlbn <= lbn && !error; tlbn++) {
fa4905b1 1827 if (np->n_direofoffset
91447636 1828 && (tlbn * NFS_DIRBLKSIZ) >= np->n_direofoffset) {
55e303ae 1829 FSDBG_BOT(514, vp, 0xde0f0002, 0, 0);
fa4905b1 1830 return (0);
55e303ae 1831 }
91447636
A
1832 error = nfs_buf_get(vp, tlbn, NFS_DIRBLKSIZ, p, NBLK_READ, &bp);
1833 if (error) {
1834 FSDBG_BOT(514, vp, 0xd1e0013, 0, error);
1835 return (error);
55e303ae
A
1836 }
1837 if (!ISSET(bp->nb_flags, NB_CACHE)) {
1838 SET(bp->nb_flags, NB_READ);
fa4905b1
A
1839 error = nfs_doio(bp, cred, p);
1840 /*
55e303ae 1841 * no error + NB_INVAL == directory EOF,
fa4905b1
A
1842 * use the block.
1843 */
55e303ae 1844 if (error == 0 && (bp->nb_flags & NB_INVAL))
fa4905b1
A
1845 break;
1846 }
1847 /*
1848 * An error will throw away the block and the
1849 * for loop will break out. If no error and this
1850 * is not the block we want, we throw away the
1851 * block and go for the next one via the for loop.
1852 */
91447636 1853 if (error || tlbn < lbn)
483a1d10 1854 nfs_buf_release(bp, 1);
fa4905b1
A
1855 }
1856 }
1857 /*
1858 * The above while is repeated if we hit another cookie
1859 * error. If we hit an error and it wasn't a cookie error,
1860 * we give up.
1861 */
55e303ae
A
1862 if (error) {
1863 FSDBG_BOT(514, vp, 0xd1e0014, 0, error);
fa4905b1 1864 return (error);
55e303ae 1865 }
1c79356b
A
1866 }
1867
1868 /*
1869 * If not eof and read aheads are enabled, start one.
1870 * (You need the current block first, so that you have the
1871 * directory offset cookie of the next block.)
1872 */
1873 if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
1874 (np->n_direofoffset == 0 ||
1875 (lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) &&
91447636
A
1876 !nfs_buf_is_incore(vp, lbn + 1)) {
1877 error = nfs_buf_get(vp, lbn + 1, NFS_DIRBLKSIZ, p, NBLK_READ|NBLK_NOWAIT, &rabp);
1878 if (error) {
1879 FSDBG_BOT(514, vp, 0xd1e0015, 0, error);
1880 return (error);
1881 }
1c79356b 1882 if (rabp) {
55e303ae
A
1883 if (!ISSET(rabp->nb_flags, (NB_CACHE))) {
1884 SET(rabp->nb_flags, (NB_READ | NB_ASYNC));
fa4905b1 1885 if (nfs_asyncio(rabp, cred)) {
55e303ae
A
1886 SET(rabp->nb_flags, (NB_INVAL|NB_ERROR));
1887 rabp->nb_error = EIO;
483a1d10 1888 nfs_buf_release(rabp, 1);
fa4905b1 1889 }
1c79356b 1890 } else {
483a1d10 1891 nfs_buf_release(rabp, 1);
1c79356b
A
1892 }
1893 }
1894 }
1895 /*
1896 * Make sure we use a signed variant of min() since
1897 * the second term may be negative.
1898 */
91447636
A
1899 // LP64todo - fix this!
1900 n = lmin(uio_uio_resid(uio), bp->nb_validend - on);
fa4905b1 1901 /*
55e303ae
A
1902 * We keep track of the directory eof in
1903 * np->n_direofoffset and chop it off as an
1904 * extra step right here.
fa4905b1
A
1905 */
1906 if (np->n_direofoffset &&
1907 n > np->n_direofoffset - uio->uio_offset)
1908 n = np->n_direofoffset - uio->uio_offset;
55e303ae
A
1909 /*
1910 * Make sure that we return an integral number of entries so
1911 * that any subsequent calls will start copying from the start
1912 * of the next entry.
1913 *
1914 * If the current value of n has the last entry cut short,
1915 * set n to copy everything up to the last entry instead.
1916 */
1917 if (n > 0) {
1918 dp = bp->nb_data + on;
1919 while (dp < (bp->nb_data + on + n)) {
1920 direntp = (struct dirent *)dp;
1921 dp += direntp->d_reclen;
1922 }
1923 if (dp > (bp->nb_data + on + n))
1924 n = (dp - direntp->d_reclen) - (bp->nb_data + on);
1925 }
1c79356b
A
1926 break;
1927 default:
91447636
A
1928 printf("nfs_bioread: type %x unexpected\n", vtype);
1929 FSDBG_BOT(514, vp, 0xd1e0016, 0, EINVAL);
55e303ae 1930 return (EINVAL);
1c79356b
A
1931 };
1932
1933 if (n > 0) {
55e303ae 1934 error = uiomove(bp->nb_data + on, (int)n, uio);
1c79356b 1935 }
91447636 1936 switch (vtype) {
1c79356b 1937 case VREG:
91447636
A
1938 if (np->n_flag & NNOCACHE)
1939 SET(bp->nb_flags, NB_NOCACHE);
1c79356b
A
1940 break;
1941 case VLNK:
1942 n = 0;
1943 break;
1944 case VDIR:
91447636
A
1945 break;
1946 default:
1c79356b 1947 break;
1c79356b 1948 }
91447636
A
1949 nfs_buf_release(bp, 1);
1950 } while (error == 0 && uio_uio_resid(uio) > 0 && n > 0);
1951 FSDBG_BOT(514, vp, uio->uio_offset, uio_uio_resid(uio), error);
1c79356b
A
1952 return (error);
1953}
1954
fa4905b1 1955
1c79356b
A
1956/*
1957 * Vnode op for write using bio
1958 */
1959int
1960nfs_write(ap)
91447636
A
1961 struct vnop_write_args /* {
1962 struct vnodeop_desc *a_desc;
1963 vnode_t a_vp;
1c79356b 1964 struct uio *a_uio;
91447636
A
1965 int a_ioflag;
1966 vfs_context_t a_context;
1c79356b
A
1967 } */ *ap;
1968{
55e303ae 1969 struct uio *uio = ap->a_uio;
91447636 1970 vnode_t vp = ap->a_vp;
1c79356b 1971 struct nfsnode *np = VTONFS(vp);
91447636
A
1972 proc_t p;
1973 kauth_cred_t cred;
1c79356b 1974 int ioflag = ap->a_ioflag;
55e303ae 1975 struct nfsbuf *bp;
91447636
A
1976 struct nfs_vattr nvattr;
1977 struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
1978 daddr64_t lbn;
1979 int biosize, bufsize;
1980 int n, on, error = 0;
483a1d10 1981 off_t boff, start, end, cureof;
91447636 1982 struct iovec_32 iov;
fa4905b1 1983 struct uio auio;
1c79356b 1984
91447636 1985 FSDBG_TOP(515, vp, uio->uio_offset, uio_uio_resid(uio), ioflag);
55e303ae 1986
1c79356b
A
1987#if DIAGNOSTIC
1988 if (uio->uio_rw != UIO_WRITE)
1989 panic("nfs_write mode");
91447636 1990 if (UIO_SEG_IS_USER_SPACE(uio->uio_segflg))
1c79356b
A
1991 panic("nfs_write proc");
1992#endif
91447636
A
1993
1994 p = vfs_context_proc(ap->a_context);
1995 cred = vfs_context_ucred(ap->a_context);
1996
1997 if (vnode_vtype(vp) != VREG)
1c79356b 1998 return (EIO);
91447636
A
1999
2000 np->n_flag |= NWRBUSY;
2001
2002 if (np->n_flag & NNEEDINVALIDATE) {
2003 np->n_flag &= ~NNEEDINVALIDATE;
2004 nfs_vinvalbuf(vp, V_SAVE|V_IGNORE_WRITEERR, cred, p, 1);
2005 }
1c79356b 2006 if (np->n_flag & NWRITEERR) {
91447636
A
2007 np->n_flag &= ~(NWRITEERR | NWRBUSY);
2008 FSDBG_BOT(515, vp, uio->uio_offset, uio_uio_resid(uio), np->n_error);
1c79356b
A
2009 return (np->n_error);
2010 }
0c530ab8
A
2011
2012 biosize = nmp->nm_biosize;
2013 if ((nmp->nm_flag & NFSMNT_NFSV3) && !(nmp->nm_state & NFSSTA_GOTFSINFO))
2014 nfs_fsinfo(nmp, vp, cred, p);
2015
1c79356b
A
2016 if (ioflag & (IO_APPEND | IO_SYNC)) {
2017 if (np->n_flag & NMODIFIED) {
91447636 2018 NATTRINVALIDATE(np);
1c79356b 2019 error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
55e303ae 2020 if (error) {
91447636 2021 np->n_flag &= ~NWRBUSY;
55e303ae 2022 FSDBG_BOT(515, vp, uio->uio_offset, 0x10bad01, error);
1c79356b 2023 return (error);
55e303ae 2024 }
1c79356b
A
2025 }
2026 if (ioflag & IO_APPEND) {
91447636
A
2027 NATTRINVALIDATE(np);
2028 error = nfs_getattr(vp, &nvattr, cred, p);
55e303ae 2029 if (error) {
91447636 2030 np->n_flag &= ~NWRBUSY;
55e303ae 2031 FSDBG_BOT(515, vp, uio->uio_offset, 0x10bad02, error);
1c79356b 2032 return (error);
55e303ae 2033 }
1c79356b
A
2034 uio->uio_offset = np->n_size;
2035 }
2036 }
55e303ae 2037 if (uio->uio_offset < 0) {
91447636 2038 np->n_flag &= ~NWRBUSY;
55e303ae 2039 FSDBG_BOT(515, vp, uio->uio_offset, 0xbad0ff, EINVAL);
1c79356b 2040 return (EINVAL);
55e303ae 2041 }
91447636
A
2042 if (uio_uio_resid(uio) == 0) {
2043 np->n_flag &= ~NWRBUSY;
2044 FSDBG_BOT(515, vp, uio->uio_offset, uio_uio_resid(uio), 0);
1c79356b 2045 return (0);
55e303ae 2046 }
55e303ae 2047
91447636
A
2048 if (vnode_isnocache(vp)) {
2049 if (!(np->n_flag & NNOCACHE)) {
2050 if (NVALIDBUFS(np)) {
1c79356b 2051 error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
55e303ae 2052 if (error) {
91447636
A
2053 np->n_flag &= ~NWRBUSY;
2054 FSDBG_BOT(515, vp, 0, 0, error);
1c79356b 2055 return (error);
55e303ae 2056 }
55e303ae 2057 }
91447636 2058 np->n_flag |= NNOCACHE;
55e303ae 2059 }
91447636
A
2060 } else if (np->n_flag & NNOCACHE) {
2061 np->n_flag &= ~NNOCACHE;
2062 }
2063
2064 do {
2065 OSAddAtomic(1, (SInt32*)&nfsstats.biocache_writes);
1c79356b 2066 lbn = uio->uio_offset / biosize;
55e303ae 2067 on = uio->uio_offset % biosize;
91447636
A
2068 // LP64todo - fix this
2069 n = min((unsigned)(biosize - on), uio_uio_resid(uio));
1c79356b 2070again:
1c79356b 2071 bufsize = biosize;
fa4905b1
A
2072 /*
2073 * Get a cache block for writing. The range to be written is
55e303ae 2074 * (off..off+n) within the block. We ensure that the block
fa4905b1
A
2075 * either has no dirty region or that the given range is
2076 * contiguous with the existing dirty region.
2077 */
91447636
A
2078 error = nfs_buf_get(vp, lbn, bufsize, p, NBLK_WRITE, &bp);
2079 if (error) {
2080 np->n_flag &= ~NWRBUSY;
2081 FSDBG_BOT(515, vp, uio->uio_offset, uio_uio_resid(uio), error);
2082 return (error);
55e303ae
A
2083 }
2084 /* map the block because we know we're going to write to it */
2085 NFS_BUF_MAP(bp);
2086
91447636 2087 if (np->n_flag & NNOCACHE)
0c530ab8 2088 SET(bp->nb_flags, NB_NOCACHE);
55e303ae 2089
0c530ab8 2090 if (!IS_VALID_CRED(bp->nb_wcred)) {
91447636
A
2091 kauth_cred_ref(cred);
2092 bp->nb_wcred = cred;
2093 }
55e303ae
A
2094
2095 /*
2096 * If there's already a dirty range AND dirty pages in this block we
2097 * need to send a commit AND write the dirty pages before continuing.
2098 *
2099 * If there's already a dirty range OR dirty pages in this block
2100 * and the new write range is not contiguous with the existing range,
2101 * then force the buffer to be written out now.
2102 * (We used to just extend the dirty range to cover the valid,
2103 * but unwritten, data in between also. But writing ranges
2104 * of data that weren't actually written by an application
2105 * risks overwriting some other client's data with stale data
2106 * that's just masquerading as new written data.)
2107 */
2108 if (bp->nb_dirtyend > 0) {
2109 if (on > bp->nb_dirtyend || (on + n) < bp->nb_dirtyoff || bp->nb_dirty) {
2110 FSDBG(515, vp, uio->uio_offset, bp, 0xd15c001);
2111 /* write/commit buffer "synchronously" */
2112 /* (NB_STABLE indicates that data writes should be FILESYNC) */
2113 CLR(bp->nb_flags, (NB_DONE | NB_ERROR | NB_INVAL));
2114 SET(bp->nb_flags, (NB_ASYNC | NB_STABLE));
2115 error = nfs_buf_write(bp);
2116 if (error) {
91447636
A
2117 np->n_flag &= ~NWRBUSY;
2118 FSDBG_BOT(515, vp, uio->uio_offset, uio_uio_resid(uio), error);
55e303ae
A
2119 return (error);
2120 }
2121 goto again;
2122 }
2123 } else if (bp->nb_dirty) {
2124 int firstpg, lastpg;
2125 u_int32_t pagemask;
2126 /* calculate write range pagemask */
2127 firstpg = on/PAGE_SIZE;
2128 lastpg = (on+n-1)/PAGE_SIZE;
2129 pagemask = ((1 << (lastpg+1)) - 1) & ~((1 << firstpg) - 1);
2130 /* check if there are dirty pages outside the write range */
2131 if (bp->nb_dirty & ~pagemask) {
2132 FSDBG(515, vp, uio->uio_offset, bp, 0xd15c002);
2133 /* write/commit buffer "synchronously" */
2134 /* (NB_STABLE indicates that data writes should be FILESYNC) */
2135 CLR(bp->nb_flags, (NB_DONE | NB_ERROR | NB_INVAL));
2136 SET(bp->nb_flags, (NB_ASYNC | NB_STABLE));
2137 error = nfs_buf_write(bp);
2138 if (error) {
91447636
A
2139 np->n_flag &= ~NWRBUSY;
2140 FSDBG_BOT(515, vp, uio->uio_offset, uio_uio_resid(uio), error);
55e303ae
A
2141 return (error);
2142 }
2143 goto again;
2144 }
2145 /* if the first or last pages are already dirty */
2146 /* make sure that the dirty range encompasses those pages */
2147 if (NBPGDIRTY(bp,firstpg) || NBPGDIRTY(bp,lastpg)) {
2148 FSDBG(515, vp, uio->uio_offset, bp, 0xd15c003);
2149 bp->nb_dirtyoff = min(on, firstpg * PAGE_SIZE);
2150 if (NBPGDIRTY(bp,lastpg)) {
2151 bp->nb_dirtyend = (lastpg+1) * PAGE_SIZE;
2152 /* clip to EOF */
91447636 2153 if (NBOFF(bp) + bp->nb_dirtyend > (off_t)np->n_size)
55e303ae
A
2154 bp->nb_dirtyend = np->n_size - NBOFF(bp);
2155 } else
2156 bp->nb_dirtyend = on+n;
2157 }
2158 }
2159
fa4905b1 2160 /*
55e303ae
A
2161 * Are we extending the size of the file with this write?
2162 * If so, update file size now that we have the block.
fa4905b1
A
2163 * If there was a partial buf at the old eof, validate
2164 * and zero the new bytes.
2165 */
483a1d10 2166 cureof = (off_t)np->n_size;
91447636 2167 if (uio->uio_offset + n > (off_t)np->n_size) {
55e303ae 2168 struct nfsbuf *eofbp = NULL;
91447636 2169 daddr64_t eofbn = np->n_size / biosize;
55e303ae
A
2170 int eofoff = np->n_size % biosize;
2171 int neweofoff = (uio->uio_offset + n) % biosize;
2172
2173 FSDBG(515, 0xb1ffa000, uio->uio_offset + n, eofoff, neweofoff);
fa4905b1 2174
91447636
A
2175 if (eofoff && (eofbn < lbn)) {
2176 error = nfs_buf_get(vp, eofbn, biosize, p, NBLK_WRITE|NBLK_ONLYVALID, &eofbp);
2177 if (error) {
2178 np->n_flag &= ~NWRBUSY;
2179 FSDBG_BOT(515, vp, uio->uio_offset, uio_uio_resid(uio), error);
2180 return (error);
2181 }
2182 }
55e303ae
A
2183
2184 /* if we're extending within the same last block */
2185 /* and the block is flagged as being cached... */
2186 if ((lbn == eofbn) && ISSET(bp->nb_flags, NB_CACHE)) {
2187 /* ...check that all pages in buffer are valid */
2188 int endpg = ((neweofoff ? neweofoff : biosize) - 1)/PAGE_SIZE;
2189 u_int32_t pagemask;
2190 /* pagemask only has to extend to last page being written to */
2191 pagemask = (1 << (endpg+1)) - 1;
2192 FSDBG(515, 0xb1ffa001, bp->nb_valid, pagemask, 0);
2193 if ((bp->nb_valid & pagemask) != pagemask) {
2194 /* zerofill any hole */
2195 if (on > bp->nb_validend) {
2196 int i;
2197 for (i=bp->nb_validend/PAGE_SIZE; i <= (on - 1)/PAGE_SIZE; i++)
2198 NBPGVALID_SET(bp, i);
2199 NFS_BUF_MAP(bp);
2200 FSDBG(516, bp, bp->nb_validend, on - bp->nb_validend, 0xf01e);
2201 bzero((char *)bp->nb_data + bp->nb_validend,
2202 on - bp->nb_validend);
2203 }
2204 /* zerofill any trailing data in the last page */
2205 if (neweofoff) {
2206 NFS_BUF_MAP(bp);
2207 FSDBG(516, bp, neweofoff, PAGE_SIZE - (neweofoff & PAGE_MASK), 0xe0f);
2208 bzero((char *)bp->nb_data + neweofoff,
2209 PAGE_SIZE - (neweofoff & PAGE_MASK));
2210 }
2211 }
2212 }
fa4905b1
A
2213 np->n_flag |= NMODIFIED;
2214 np->n_size = uio->uio_offset + n;
2215 ubc_setsize(vp, (off_t)np->n_size); /* XXX errors */
55e303ae
A
2216 if (eofbp) {
2217 /*
2218 * We may need to zero any previously invalid data
2219 * after the old EOF in the previous EOF buffer.
2220 *
2221 * For the old last page, don't zero bytes if there
2222 * are invalid bytes in that page (i.e. the page isn't
2223 * currently valid).
2224 * For pages after the old last page, zero them and
2225 * mark them as valid.
2226 */
2227 char *d;
2228 int i;
91447636 2229 if (np->n_flag & NNOCACHE)
0c530ab8 2230 SET(eofbp->nb_flags, NB_NOCACHE);
55e303ae
A
2231 NFS_BUF_MAP(eofbp);
2232 FSDBG(516, eofbp, eofoff, biosize - eofoff, 0xe0fff01e);
2233 d = eofbp->nb_data;
2234 i = eofoff/PAGE_SIZE;
2235 while (eofoff < biosize) {
2236 int poff = eofoff & PAGE_MASK;
2237 if (!poff || NBPGVALID(eofbp,i)) {
2238 bzero(d + eofoff, PAGE_SIZE - poff);
2239 NBPGVALID_SET(eofbp, i);
2240 }
2241 if (bp->nb_validend == eofoff)
2242 bp->nb_validend += PAGE_SIZE - poff;
2243 eofoff += PAGE_SIZE - poff;
2244 i++;
2245 }
483a1d10 2246 nfs_buf_release(eofbp, 1);
fa4905b1
A
2247 }
2248 }
fa4905b1
A
2249 /*
2250 * If dirtyend exceeds file size, chop it down. This should
2251 * not occur unless there is a race.
2252 */
91447636 2253 if (NBOFF(bp) + bp->nb_dirtyend > (off_t)np->n_size)
55e303ae 2254 bp->nb_dirtyend = np->n_size - NBOFF(bp);
fa4905b1 2255 /*
55e303ae
A
2256 * UBC doesn't handle partial pages, so we need to make sure
2257 * that any pages left in the page cache are completely valid.
2258 *
2259 * Writes that are smaller than a block are delayed if they
2260 * don't extend to the end of the block.
fa4905b1 2261 *
55e303ae
A
2262 * If the block isn't (completely) cached, we may need to read
2263 * in some parts of pages that aren't covered by the write.
2264 * If the write offset (on) isn't page aligned, we'll need to
2265 * read the start of the first page being written to. Likewise,
2266 * if the offset of the end of the write (on+n) isn't page aligned,
2267 * we'll need to read the end of the last page being written to.
2268 *
2269 * Notes:
2270 * We don't want to read anything we're just going to write over.
2271 * We don't want to issue multiple I/Os if we don't have to
2272 * (because they're synchronous rpcs).
2273 * We don't want to read anything we already have modified in the
2274 * page cache.
fa4905b1 2275 */
55e303ae
A
2276 if (!ISSET(bp->nb_flags, NB_CACHE) && n < biosize) {
2277 int firstpg, lastpg, dirtypg;
2278 int firstpgoff, lastpgoff;
2279 start = end = -1;
2280 firstpg = on/PAGE_SIZE;
2281 firstpgoff = on & PAGE_MASK;
2282 lastpg = (on+n-1)/PAGE_SIZE;
2283 lastpgoff = (on+n) & PAGE_MASK;
2284 if (firstpgoff && !NBPGVALID(bp,firstpg)) {
2285 /* need to read start of first page */
2286 start = firstpg * PAGE_SIZE;
2287 end = start + firstpgoff;
fa4905b1 2288 }
55e303ae
A
2289 if (lastpgoff && !NBPGVALID(bp,lastpg)) {
2290 /* need to read end of last page */
2291 if (start < 0)
2292 start = (lastpg * PAGE_SIZE) + lastpgoff;
2293 end = (lastpg + 1) * PAGE_SIZE;
fa4905b1 2294 }
fa4905b1 2295 if (end > start) {
55e303ae
A
2296 /* need to read the data in range: start...end-1 */
2297
55e303ae
A
2298 /* first, check for dirty pages in between */
2299 /* if there are, we'll have to do two reads because */
2300 /* we don't want to overwrite the dirty pages. */
2301 for (dirtypg=start/PAGE_SIZE; dirtypg <= (end-1)/PAGE_SIZE; dirtypg++)
2302 if (NBPGDIRTY(bp,dirtypg))
2303 break;
2304
2305 /* if start is at beginning of page, try */
2306 /* to get any preceeding pages as well. */
2307 if (!(start & PAGE_MASK)) {
2308 /* stop at next dirty/valid page or start of block */
2309 for (; start > 0; start-=PAGE_SIZE)
2310 if (NBPGVALID(bp,((start-1)/PAGE_SIZE)))
2311 break;
2312 }
2313
2314 NFS_BUF_MAP(bp);
2315 /* setup uio for read(s) */
2316 boff = NBOFF(bp);
91447636 2317 auio.uio_iovs.iov32p = &iov;
fa4905b1 2318 auio.uio_iovcnt = 1;
91447636 2319#if 1 /* LP64todo - can't use new segment flags until the drivers are ready */
fa4905b1 2320 auio.uio_segflg = UIO_SYSSPACE;
91447636
A
2321#else
2322 auio.uio_segflg = UIO_SYSSPACE32;
2323#endif
fa4905b1 2324 auio.uio_rw = UIO_READ;
55e303ae
A
2325
2326 if (dirtypg <= (end-1)/PAGE_SIZE) {
2327 /* there's a dirty page in the way, so just do two reads */
2328 /* we'll read the preceding data here */
2329 auio.uio_offset = boff + start;
91447636
A
2330 iov.iov_len = on - start;
2331 uio_uio_resid_set(&auio, iov.iov_len);
2332 iov.iov_base = (uintptr_t) bp->nb_data + start;
2333 error = nfs_readrpc(vp, &auio, cred, p);
55e303ae
A
2334 if (error) {
2335 bp->nb_error = error;
2336 SET(bp->nb_flags, NB_ERROR);
2337 printf("nfs_write: readrpc %d", error);
2338 }
91447636
A
2339 if (uio_uio_resid(&auio) > 0) {
2340 FSDBG(516, bp, iov.iov_base - bp->nb_data, uio_uio_resid(&auio), 0xd00dee01);
2341 // LP64todo - fix this
2342 bzero((caddr_t)iov.iov_base, uio_uio_resid(&auio));
55e303ae
A
2343 }
2344 /* update validoff/validend if necessary */
2345 if ((bp->nb_validoff < 0) || (bp->nb_validoff > start))
2346 bp->nb_validoff = start;
2347 if ((bp->nb_validend < 0) || (bp->nb_validend < on))
2348 bp->nb_validend = on;
91447636 2349 if ((off_t)np->n_size > boff + bp->nb_validend)
55e303ae
A
2350 bp->nb_validend = min(np->n_size - (boff + start), biosize);
2351 /* validate any pages before the write offset */
2352 for (; start < on/PAGE_SIZE; start+=PAGE_SIZE)
2353 NBPGVALID_SET(bp, start/PAGE_SIZE);
2354 /* adjust start to read any trailing data */
2355 start = on+n;
2356 }
2357
2358 /* if end is at end of page, try to */
2359 /* get any following pages as well. */
2360 if (!(end & PAGE_MASK)) {
2361 /* stop at next valid page or end of block */
2362 for (; end < bufsize; end+=PAGE_SIZE)
2363 if (NBPGVALID(bp,end/PAGE_SIZE))
2364 break;
2365 }
2366
483a1d10
A
2367 if (((boff+start) >= cureof) || ((start >= on) && ((boff + on + n) >= cureof))) {
2368 /*
2369 * Either this entire read is beyond the current EOF
2370 * or the range that we won't be modifying (on+n...end)
2371 * is all beyond the current EOF.
2372 * No need to make a trip across the network to
2373 * read nothing. So, just zero the buffer instead.
2374 */
2375 FSDBG(516, bp, start, end - start, 0xd00dee00);
2376 bzero(bp->nb_data + start, end - start);
2377 } else {
2378 /* now we'll read the (rest of the) data */
2379 auio.uio_offset = boff + start;
91447636
A
2380 iov.iov_len = end - start;
2381 uio_uio_resid_set(&auio, iov.iov_len);
2382 iov.iov_base = (uintptr_t) (bp->nb_data + start);
2383 error = nfs_readrpc(vp, &auio, cred, p);
483a1d10
A
2384 if (error) {
2385 bp->nb_error = error;
2386 SET(bp->nb_flags, NB_ERROR);
2387 printf("nfs_write: readrpc %d", error);
2388 }
91447636
A
2389 if (uio_uio_resid(&auio) > 0) {
2390 FSDBG(516, bp, iov.iov_base - bp->nb_data, uio_uio_resid(&auio), 0xd00dee02);
2391 // LP64todo - fix this
2392 bzero((caddr_t)iov.iov_base, uio_uio_resid(&auio));
483a1d10 2393 }
55e303ae
A
2394 }
2395 /* update validoff/validend if necessary */
2396 if ((bp->nb_validoff < 0) || (bp->nb_validoff > start))
2397 bp->nb_validoff = start;
2398 if ((bp->nb_validend < 0) || (bp->nb_validend < end))
2399 bp->nb_validend = end;
91447636 2400 if ((off_t)np->n_size > boff + bp->nb_validend)
55e303ae
A
2401 bp->nb_validend = min(np->n_size - (boff + start), biosize);
2402 /* validate any pages before the write offset's page */
2403 for (; start < trunc_page_32(on); start+=PAGE_SIZE)
2404 NBPGVALID_SET(bp, start/PAGE_SIZE);
2405 /* validate any pages after the range of pages being written to */
2406 for (; (end - 1) > round_page_32(on+n-1); end-=PAGE_SIZE)
2407 NBPGVALID_SET(bp, (end-1)/PAGE_SIZE);
2408 /* Note: pages being written to will be validated when written */
fa4905b1 2409 }
fa4905b1 2410 }
55e303ae
A
2411
2412 if (ISSET(bp->nb_flags, NB_ERROR)) {
2413 error = bp->nb_error;
483a1d10 2414 nfs_buf_release(bp, 1);
91447636
A
2415 np->n_flag &= ~NWRBUSY;
2416 FSDBG_BOT(515, vp, uio->uio_offset, uio_uio_resid(uio), error);
1c79356b
A
2417 return (error);
2418 }
55e303ae 2419
1c79356b
A
2420 np->n_flag |= NMODIFIED;
2421
55e303ae
A
2422 NFS_BUF_MAP(bp);
2423 error = uiomove((char *)bp->nb_data + on, n, uio);
1c79356b 2424 if (error) {
55e303ae 2425 SET(bp->nb_flags, NB_ERROR);
483a1d10 2426 nfs_buf_release(bp, 1);
91447636
A
2427 np->n_flag &= ~NWRBUSY;
2428 FSDBG_BOT(515, vp, uio->uio_offset, uio_uio_resid(uio), error);
1c79356b
A
2429 return (error);
2430 }
55e303ae
A
2431
2432 /* validate any pages written to */
2433 start = on & ~PAGE_MASK;
2434 for (; start < on+n; start += PAGE_SIZE) {
2435 NBPGVALID_SET(bp, start/PAGE_SIZE);
2436 /*
2437 * This may seem a little weird, but we don't actually set the
2438 * dirty bits for writes. This is because we keep the dirty range
2439 * in the nb_dirtyoff/nb_dirtyend fields. Also, particularly for
2440 * delayed writes, when we give the pages back to the VM we don't
2441 * want to keep them marked dirty, because when we later write the
2442 * buffer we won't be able to tell which pages were written dirty
2443 * and which pages were mmapped and dirtied.
2444 */
2445 }
2446 if (bp->nb_dirtyend > 0) {
2447 bp->nb_dirtyoff = min(on, bp->nb_dirtyoff);
2448 bp->nb_dirtyend = max((on + n), bp->nb_dirtyend);
1c79356b 2449 } else {
55e303ae
A
2450 bp->nb_dirtyoff = on;
2451 bp->nb_dirtyend = on + n;
1c79356b 2452 }
55e303ae
A
2453 if (bp->nb_validend <= 0 || bp->nb_validend < bp->nb_dirtyoff ||
2454 bp->nb_validoff > bp->nb_dirtyend) {
2455 bp->nb_validoff = bp->nb_dirtyoff;
2456 bp->nb_validend = bp->nb_dirtyend;
1c79356b 2457 } else {
55e303ae
A
2458 bp->nb_validoff = min(bp->nb_validoff, bp->nb_dirtyoff);
2459 bp->nb_validend = max(bp->nb_validend, bp->nb_dirtyend);
1c79356b 2460 }
55e303ae
A
2461 if (!ISSET(bp->nb_flags, NB_CACHE))
2462 nfs_buf_normalize_valid_range(np, bp);
1c79356b
A
2463
2464 /*
2465 * Since this block is being modified, it must be written
2466 * again and not just committed.
2467 */
55e303ae
A
2468 if (ISSET(bp->nb_flags, NB_NEEDCOMMIT)) {
2469 np->n_needcommitcnt--;
2470 CHECK_NEEDCOMMITCNT(np);
2471 }
2472 CLR(bp->nb_flags, NB_NEEDCOMMIT);
1c79356b 2473
91447636 2474 if (ioflag & IO_SYNC) {
55e303ae
A
2475 bp->nb_proc = p;
2476 error = nfs_buf_write(bp);
2477 if (error) {
91447636 2478 np->n_flag &= ~NWRBUSY;
55e303ae 2479 FSDBG_BOT(515, vp, uio->uio_offset,
91447636 2480 uio_uio_resid(uio), error);
1c79356b 2481 return (error);
55e303ae 2482 }
91447636
A
2483 } else if (((n + on) == biosize) || (np->n_flag & NNOCACHE)) {
2484 bp->nb_proc = NULL;
55e303ae
A
2485 SET(bp->nb_flags, NB_ASYNC);
2486 nfs_buf_write(bp);
1c79356b 2487 } else
91447636 2488 nfs_buf_write_delayed(bp, p);
55e303ae 2489
91447636
A
2490 if (np->n_needcommitcnt > (nfsbufcnt/16))
2491 nfs_flushcommits(vp, p, 1);
55e303ae 2492
91447636 2493 } while (uio_uio_resid(uio) > 0 && n > 0);
55e303ae 2494
0c530ab8
A
2495 if (np->n_flag & NNOCACHE) {
2496 /* make sure all the buffers are flushed out */
2497 error = nfs_flush(vp, MNT_WAIT, cred, p, 0);
2498 }
2499
91447636 2500 np->n_flag &= ~NWRBUSY;
0c530ab8
A
2501 FSDBG_BOT(515, vp, uio->uio_offset, uio_uio_resid(uio), error);
2502 return (error);
1c79356b
A
2503}
2504
1c79356b 2505/*
55e303ae
A
2506 * Flush out and invalidate all buffers associated with a vnode.
2507 * Called with the underlying object locked.
1c79356b 2508 */
55e303ae 2509static int
91447636
A
2510nfs_vinvalbuf_internal(
2511 vnode_t vp,
2512 int flags,
2513 kauth_cred_t cred,
2514 proc_t p,
2515 int slpflag,
2516 int slptimeo)
1c79356b 2517{
55e303ae 2518 struct nfsbuf *bp;
91447636
A
2519 struct nfsbuflists blist;
2520 int list, error = 0;
55e303ae 2521 struct nfsnode *np = VTONFS(vp);
9bccf70c 2522
55e303ae 2523 if (flags & V_SAVE) {
91447636
A
2524 if ((error = nfs_flush(vp, MNT_WAIT, cred, p,
2525 (flags & V_IGNORE_WRITEERR))))
55e303ae 2526 return (error);
91447636 2527 if (!LIST_EMPTY(&np->n_dirtyblkhd))
55e303ae 2528 panic("nfs_vinvalbuf: dirty bufs (vp 0x%x, bp 0x%x)",
91447636 2529 vp, LIST_FIRST(&np->n_dirtyblkhd));
9bccf70c
A
2530 }
2531
91447636 2532 lck_mtx_lock(nfs_buf_mutex);
55e303ae 2533 for (;;) {
91447636
A
2534 list = NBI_CLEAN;
2535 if (nfs_buf_iterprepare(np, &blist, list)) {
2536 list = NBI_DIRTY;
2537 if (nfs_buf_iterprepare(np, &blist, list))
2538 break;
2539 }
2540 while ((bp = LIST_FIRST(&blist))) {
2541 LIST_REMOVE(bp, nb_vnbufs);
2542 if (list == NBI_CLEAN)
2543 LIST_INSERT_HEAD(&np->n_cleanblkhd, bp, nb_vnbufs);
2544 else
2545 LIST_INSERT_HEAD(&np->n_dirtyblkhd, bp, nb_vnbufs);
2546 nfs_buf_refget(bp);
2547 while ((error = nfs_buf_acquire(bp, NBAC_REMOVE, slpflag, slptimeo))) {
2548 FSDBG(556, vp, bp, NBOFF(bp), bp->nb_flags);
2549 if (error != EAGAIN) {
55e303ae 2550 FSDBG(554, vp, bp, -1, error);
91447636
A
2551 nfs_buf_refrele(bp);
2552 nfs_buf_itercomplete(np, &blist, list);
2553 lck_mtx_unlock(nfs_buf_mutex);
55e303ae
A
2554 return (error);
2555 }
55e303ae 2556 }
91447636 2557 nfs_buf_refrele(bp);
55e303ae 2558 FSDBG(554, vp, bp, NBOFF(bp), bp->nb_flags);
91447636
A
2559 lck_mtx_unlock(nfs_buf_mutex);
2560 if ((flags & V_SAVE) && UBCINFOEXISTS(vp) && bp->nb_vp &&
2561 (NBOFF(bp) < (off_t)np->n_size)) {
55e303ae
A
2562 /* XXX extra paranoia: make sure we're not */
2563 /* somehow leaving any dirty data around */
2564 int mustwrite = 0;
91447636
A
2565 int end = (NBOFF(bp) + bp->nb_bufsize > (off_t)np->n_size) ?
2566 ((off_t)np->n_size - NBOFF(bp)) : bp->nb_bufsize;
55e303ae
A
2567 if (!ISSET(bp->nb_flags, NB_PAGELIST)) {
2568 error = nfs_buf_upl_setup(bp);
2569 if (error == EINVAL) {
2570 /* vm object must no longer exist */
2571 /* hopefully we don't need to do */
2572 /* anything for this buffer */
2573 } else if (error)
91447636 2574 printf("nfs_vinvalbuf: upl setup failed %d\n", error);
55e303ae
A
2575 bp->nb_valid = bp->nb_dirty = 0;
2576 }
2577 nfs_buf_upl_check(bp);
2578 /* check for any dirty data before the EOF */
2579 if (bp->nb_dirtyend && bp->nb_dirtyoff < end) {
2580 /* clip dirty range to EOF */
2581 if (bp->nb_dirtyend > end)
2582 bp->nb_dirtyend = end;
2583 mustwrite++;
2584 }
2585 bp->nb_dirty &= (1 << (round_page_32(end)/PAGE_SIZE)) - 1;
91447636 2586 /* also make sure we'll have a credential to do the write */
0c530ab8 2587 if (mustwrite && !IS_VALID_CRED(bp->nb_wcred) && !IS_VALID_CRED(cred)) {
91447636
A
2588 printf("nfs_vinvalbuf: found dirty buffer with no write creds\n");
2589 mustwrite = 0;
2590 }
55e303ae
A
2591 if (mustwrite) {
2592 FSDBG(554, vp, bp, 0xd00dee, bp->nb_flags);
2593 if (!ISSET(bp->nb_flags, NB_PAGELIST))
2594 panic("nfs_vinvalbuf: dirty buffer without upl");
2595 /* gotta write out dirty data before invalidating */
2596 /* (NB_STABLE indicates that data writes should be FILESYNC) */
2597 /* (NB_NOCACHE indicates buffer should be discarded) */
2598 CLR(bp->nb_flags, (NB_DONE | NB_ERROR | NB_INVAL | NB_ASYNC));
2599 SET(bp->nb_flags, NB_STABLE | NB_NOCACHE);
0c530ab8 2600 if (!IS_VALID_CRED(bp->nb_wcred)) {
91447636
A
2601 kauth_cred_ref(cred);
2602 bp->nb_wcred = cred;
2603 }
55e303ae
A
2604 error = nfs_buf_write(bp);
2605 // Note: bp has been released
2606 if (error) {
2607 FSDBG(554, bp, 0xd00dee, 0xbad, error);
2608 np->n_error = error;
2609 np->n_flag |= NWRITEERR;
91447636
A
2610 /*
2611 * There was a write error and we need to
2612 * invalidate attrs to sync with server.
2613 * (if this write was extending the file,
2614 * we may no longer know the correct size)
2615 */
2616 NATTRINVALIDATE(np);
55e303ae
A
2617 error = 0;
2618 }
91447636
A
2619 lck_mtx_lock(nfs_buf_mutex);
2620 continue;
55e303ae
A
2621 }
2622 }
2623 SET(bp->nb_flags, NB_INVAL);
91447636 2624 // hold off on FREEUPs until we're done here
483a1d10 2625 nfs_buf_release(bp, 0);
91447636 2626 lck_mtx_lock(nfs_buf_mutex);
55e303ae 2627 }
91447636 2628 nfs_buf_itercomplete(np, &blist, list);
55e303ae 2629 }
91447636 2630 lck_mtx_unlock(nfs_buf_mutex);
483a1d10 2631 NFS_BUF_FREEUP();
91447636 2632 if (NVALIDBUFS(np))
55e303ae
A
2633 panic("nfs_vinvalbuf: flush failed");
2634 return (0);
1c79356b
A
2635}
2636
55e303ae 2637
1c79356b
A
2638/*
2639 * Flush and invalidate all dirty buffers. If another process is already
2640 * doing the flush, just wait for completion.
2641 */
2642int
91447636
A
2643nfs_vinvalbuf(
2644 vnode_t vp,
2645 int flags,
2646 kauth_cred_t cred,
2647 proc_t p,
2648 int intrflg)
1c79356b 2649{
91447636
A
2650 struct nfsnode *np = VTONFS(vp);
2651 struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
1c79356b 2652 int error = 0, slpflag, slptimeo;
91447636 2653 off_t size;
1c79356b 2654
55e303ae
A
2655 FSDBG_TOP(554, vp, flags, intrflg, 0);
2656
2657 if (nmp && ((nmp->nm_flag & NFSMNT_INT) == 0))
1c79356b
A
2658 intrflg = 0;
2659 if (intrflg) {
2660 slpflag = PCATCH;
2661 slptimeo = 2 * hz;
2662 } else {
2663 slpflag = 0;
2664 slptimeo = 0;
2665 }
2666 /*
2667 * First wait for any other process doing a flush to complete.
2668 */
2669 while (np->n_flag & NFLUSHINPROG) {
2670 np->n_flag |= NFLUSHWANT;
55e303ae
A
2671 FSDBG_TOP(555, vp, flags, intrflg, np->n_flag);
2672 error = tsleep((caddr_t)&np->n_flag, PRIBIO + 2, "nfsvinval", slptimeo);
2673 FSDBG_BOT(555, vp, flags, intrflg, np->n_flag);
91447636 2674 if (error && (error = nfs_sigintr(VFSTONFS(vnode_mount(vp)), NULL, p))) {
55e303ae
A
2675 FSDBG_BOT(554, vp, flags, intrflg, error);
2676 return (error);
2677 }
1c79356b
A
2678 }
2679
2680 /*
2681 * Now, flush as required.
2682 */
2683 np->n_flag |= NFLUSHINPROG;
55e303ae 2684 error = nfs_vinvalbuf_internal(vp, flags, cred, p, slpflag, 0);
1c79356b 2685 while (error) {
55e303ae 2686 FSDBG(554, vp, 0, 0, error);
91447636 2687 error = nfs_sigintr(VFSTONFS(vnode_mount(vp)), NULL, p);
55e303ae 2688 if (error) {
1c79356b
A
2689 np->n_flag &= ~NFLUSHINPROG;
2690 if (np->n_flag & NFLUSHWANT) {
2691 np->n_flag &= ~NFLUSHWANT;
2692 wakeup((caddr_t)&np->n_flag);
2693 }
55e303ae
A
2694 FSDBG_BOT(554, vp, flags, intrflg, error);
2695 return (error);
1c79356b 2696 }
55e303ae 2697 error = nfs_vinvalbuf_internal(vp, flags, cred, p, 0, slptimeo);
1c79356b
A
2698 }
2699 np->n_flag &= ~(NMODIFIED | NFLUSHINPROG);
2700 if (np->n_flag & NFLUSHWANT) {
2701 np->n_flag &= ~NFLUSHWANT;
2702 wakeup((caddr_t)&np->n_flag);
2703 }
91447636
A
2704 /*
2705 * get the pages out of vm also
2706 */
2707 if (UBCINFOEXISTS(vp) && (size = ubc_getsize(vp))) {
2708 int rv = ubc_sync_range(vp, 0, size, UBC_PUSHALL | UBC_INVALIDATE);
55e303ae 2709 if (!rv)
91447636 2710 panic("nfs_vinvalbuf(): ubc_sync_range failed!");
0b4e3aa0 2711 }
91447636 2712
55e303ae 2713 FSDBG_BOT(554, vp, flags, intrflg, 0);
1c79356b
A
2714 return (0);
2715}
2716
2717/*
2718 * Initiate asynchronous I/O. Return an error if no nfsiods are available.
2719 * This is mainly to avoid queueing async I/O requests when the nfsiods
2720 * are all hung on a dead server.
2721 */
2722int
2723nfs_asyncio(bp, cred)
55e303ae 2724 struct nfsbuf *bp;
91447636 2725 kauth_cred_t cred;
1c79356b
A
2726{
2727 struct nfsmount *nmp;
2728 int i;
2729 int gotiod;
2730 int slpflag = 0;
2731 int slptimeo = 0;
55e303ae 2732 int error, error2;
91447636
A
2733 void *wakeme = NULL;
2734 struct timespec ts;
1c79356b
A
2735
2736 if (nfs_numasync == 0)
2737 return (EIO);
55e303ae
A
2738
2739 FSDBG_TOP(552, bp, bp ? NBOFF(bp) : 0, bp ? bp->nb_flags : 0, 0);
2740
91447636 2741 nmp = ((bp != NULL) ? VFSTONFS(vnode_mount(bp->nb_vp)) : NULL);
1c79356b 2742again:
55e303ae 2743 if (nmp && nmp->nm_flag & NFSMNT_INT)
1c79356b
A
2744 slpflag = PCATCH;
2745 gotiod = FALSE;
2746
91447636
A
2747 lck_mtx_lock(nfs_iod_mutex);
2748
55e303ae
A
2749 /* no nfsbuf means tell nfsiod to process delwri list */
2750 if (!bp)
2751 nfs_ioddelwri = 1;
2752
1c79356b
A
2753 /*
2754 * Find a free iod to process this request.
2755 */
2756 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
2757 if (nfs_iodwant[i]) {
2758 /*
2759 * Found one, so wake it up and tell it which
2760 * mount to process.
2761 */
91447636 2762 nfs_iodwant[i] = NULL;
1c79356b 2763 nfs_iodmount[i] = nmp;
55e303ae
A
2764 if (nmp)
2765 nmp->nm_bufqiods++;
91447636 2766 wakeme = &nfs_iodwant[i];
1c79356b
A
2767 gotiod = TRUE;
2768 break;
2769 }
2770
55e303ae 2771 /* if we're just poking the delwri list, we're done */
91447636
A
2772 if (!bp) {
2773 lck_mtx_unlock(nfs_iod_mutex);
2774 if (wakeme)
2775 wakeup(wakeme);
2776 FSDBG_BOT(552, bp, 0x10101010, wakeme, 0);
55e303ae 2777 return (0);
91447636 2778 }
55e303ae 2779
1c79356b
A
2780 /*
2781 * If none are free, we may already have an iod working on this mount
2782 * point. If so, it will process our request.
2783 */
2784 if (!gotiod) {
2785 if (nmp->nm_bufqiods > 0) {
1c79356b
A
2786 gotiod = TRUE;
2787 }
2788 }
2789
2790 /*
2791 * If we have an iod which can process the request, then queue
2792 * the buffer.
2793 */
55e303ae 2794 FSDBG(552, bp, gotiod, i, nmp->nm_bufqiods);
1c79356b
A
2795 if (gotiod) {
2796 /*
2797 * Ensure that the queue never grows too large.
2798 */
2799 while (nmp->nm_bufqlen >= 2*nfs_numasync) {
55e303ae
A
2800 if (ISSET(bp->nb_flags, NB_IOD)) {
2801 /* An nfsiod is attempting this async operation so */
2802 /* we must not fall asleep on the bufq because we */
2803 /* could be waiting on ourself. Just return error */
2804 /* and we'll do this operation syncrhonously. */
2805 goto out;
2806 }
2807 FSDBG(552, bp, nmp->nm_bufqlen, 2*nfs_numasync, -1);
1c79356b 2808 nmp->nm_bufqwant = TRUE;
91447636
A
2809
2810 ts.tv_sec = (slptimeo/100);
2811 /* the hz value is 100; which leads to 10ms */
2812 ts.tv_nsec = (slptimeo % 100) * 10 * NSEC_PER_USEC * 1000;
2813
2814 error = msleep(&nmp->nm_bufq, nfs_iod_mutex, slpflag | PRIBIO,
2815 "nfsaio", &ts);
1c79356b 2816 if (error) {
55e303ae
A
2817 error2 = nfs_sigintr(nmp, NULL, bp->nb_proc);
2818 if (error2) {
91447636 2819 lck_mtx_unlock(nfs_iod_mutex);
55e303ae
A
2820 FSDBG_BOT(552, bp, NBOFF(bp), bp->nb_flags, error2);
2821 return (error2);
2822 }
1c79356b
A
2823 if (slpflag == PCATCH) {
2824 slpflag = 0;
2825 slptimeo = 2 * hz;
2826 }
2827 }
2828 /*
2829 * We might have lost our iod while sleeping,
2830 * so check and loop if nescessary.
2831 */
2832 if (nmp->nm_bufqiods == 0) {
91447636 2833 lck_mtx_unlock(nfs_iod_mutex);
1c79356b
A
2834 goto again;
2835 }
2836 }
2837
55e303ae 2838 if (ISSET(bp->nb_flags, NB_READ)) {
0c530ab8 2839 if (!IS_VALID_CRED(bp->nb_rcred) && IS_VALID_CRED(cred)) {
91447636
A
2840 kauth_cred_ref(cred);
2841 bp->nb_rcred = cred;
1c79356b
A
2842 }
2843 } else {
55e303ae 2844 SET(bp->nb_flags, NB_WRITEINPROG);
0c530ab8 2845 if (!IS_VALID_CRED(bp->nb_wcred) && IS_VALID_CRED(cred)) {
91447636
A
2846 kauth_cred_ref(cred);
2847 bp->nb_wcred = cred;
1c79356b
A
2848 }
2849 }
2850
55e303ae 2851 TAILQ_INSERT_TAIL(&nmp->nm_bufq, bp, nb_free);
1c79356b 2852 nmp->nm_bufqlen++;
91447636
A
2853 lck_mtx_unlock(nfs_iod_mutex);
2854 if (wakeme)
2855 wakeup(wakeme);
55e303ae 2856 FSDBG_BOT(552, bp, NBOFF(bp), bp->nb_flags, 0);
1c79356b
A
2857 return (0);
2858 }
2859
55e303ae 2860out:
91447636 2861 lck_mtx_unlock(nfs_iod_mutex);
1c79356b
A
2862 /*
2863 * All the iods are busy on other mounts, so return EIO to
2864 * force the caller to process the i/o synchronously.
2865 */
55e303ae 2866 FSDBG_BOT(552, bp, NBOFF(bp), bp->nb_flags, EIO);
1c79356b
A
2867 return (EIO);
2868}
2869
2870/*
2871 * Do an I/O operation to/from a cache block. This may be called
2872 * synchronously or from an nfsiod.
2873 */
2874int
91447636 2875nfs_doio(struct nfsbuf *bp, kauth_cred_t cr, proc_t p)
1c79356b 2876{
91447636
A
2877 struct uio *uiop;
2878 vnode_t vp;
1c79356b
A
2879 struct nfsnode *np;
2880 struct nfsmount *nmp;
8f6c56a5 2881 int error = 0, diff, len, iomode, invalidate = 0;
1c79356b 2882 struct uio uio;
91447636
A
2883 struct iovec_32 io;
2884 enum vtype vtype;
1c79356b 2885
55e303ae 2886 vp = bp->nb_vp;
91447636 2887 vtype = vnode_vtype(vp);
1c79356b 2888 np = VTONFS(vp);
91447636 2889 nmp = VFSTONFS(vnode_mount(vp));
1c79356b 2890 uiop = &uio;
91447636 2891 uiop->uio_iovs.iov32p = &io;
1c79356b 2892 uiop->uio_iovcnt = 1;
91447636 2893#if 1 /* LP64todo - can't use new segment flags until the drivers are ready */
1c79356b 2894 uiop->uio_segflg = UIO_SYSSPACE;
91447636
A
2895#else
2896 uiop->uio_segflg = UIO_SYSSPACE32;
2897#endif
1c79356b 2898
55e303ae
A
2899 /*
2900 * we've decided to perform I/O for this block,
2901 * so we couldn't possibly NB_DONE. So, clear it.
1c79356b 2902 */
55e303ae
A
2903 if (ISSET(bp->nb_flags, NB_DONE)) {
2904 if (!ISSET(bp->nb_flags, NB_ASYNC))
1c79356b 2905 panic("nfs_doio: done and not async");
55e303ae 2906 CLR(bp->nb_flags, NB_DONE);
1c79356b 2907 }
55e303ae
A
2908 FSDBG_TOP(256, np->n_size, NBOFF(bp), bp->nb_bufsize, bp->nb_flags);
2909 FSDBG(257, bp->nb_validoff, bp->nb_validend, bp->nb_dirtyoff,
2910 bp->nb_dirtyend);
2911
2912 if (ISSET(bp->nb_flags, NB_READ)) {
91447636 2913 if (vtype == VREG)
55e303ae 2914 NFS_BUF_MAP(bp);
91447636
A
2915 io.iov_len = bp->nb_bufsize;
2916 uio_uio_resid_set(uiop, io.iov_len);
2917 io.iov_base = (uintptr_t) bp->nb_data;
1c79356b 2918 uiop->uio_rw = UIO_READ;
91447636 2919 switch (vtype) {
1c79356b 2920 case VREG:
55e303ae 2921 uiop->uio_offset = NBOFF(bp);
91447636
A
2922 OSAddAtomic(1, (SInt32*)&nfsstats.read_bios);
2923 error = nfs_readrpc(vp, uiop, cr, p);
2924 FSDBG(262, np->n_size, NBOFF(bp), uio_uio_resid(uiop), error);
1c79356b 2925 if (!error) {
55e303ae
A
2926 /* update valid range */
2927 bp->nb_validoff = 0;
91447636 2928 if (uio_uio_resid(uiop) != 0) {
1c79356b
A
2929 /*
2930 * If len > 0, there is a hole in the file and
2931 * no writes after the hole have been pushed to
2932 * the server yet.
2933 * Just zero fill the rest of the valid area.
2934 */
91447636
A
2935 // LP64todo - fix this
2936 diff = bp->nb_bufsize - uio_uio_resid(uiop);
55e303ae 2937 len = np->n_size - (NBOFF(bp) + diff);
fa4905b1 2938 if (len > 0) {
91447636
A
2939 // LP64todo - fix this
2940 len = min(len, uio_uio_resid(uiop));
55e303ae
A
2941 bzero((char *)bp->nb_data + diff, len);
2942 bp->nb_validend = diff + len;
fa4905b1
A
2943 FSDBG(258, diff, len, 0, 1);
2944 } else
55e303ae 2945 bp->nb_validend = diff;
1c79356b 2946 } else
55e303ae
A
2947 bp->nb_validend = bp->nb_bufsize;
2948 bp->nb_valid = (1 << (round_page_32(bp->nb_validend)/PAGE_SIZE)) - 1;
2949 if (bp->nb_validend & PAGE_MASK) {
2950 /* valid range ends in the middle of a page so we */
2951 /* need to zero-fill any invalid data at the end */
2952 /* of the last page */
2953 bzero((caddr_t)(bp->nb_data + bp->nb_validend),
2954 bp->nb_bufsize - bp->nb_validend);
2955 FSDBG(258, bp->nb_validend,
2956 bp->nb_bufsize - bp->nb_validend, 0, 2);
1c79356b 2957 }
1c79356b 2958 }
1c79356b
A
2959 break;
2960 case VLNK:
2961 uiop->uio_offset = (off_t)0;
91447636
A
2962 OSAddAtomic(1, (SInt32*)&nfsstats.readlink_bios);
2963 error = nfs_readlinkrpc(vp, uiop, cr, p);
55e303ae
A
2964 if (!error) {
2965 bp->nb_validoff = 0;
2966 bp->nb_validend = uiop->uio_offset;
2967 }
1c79356b
A
2968 break;
2969 case VDIR:
91447636 2970 OSAddAtomic(1, (SInt32*)&nfsstats.readdir_bios);
55e303ae 2971 uiop->uio_offset = NBOFF(bp);
1c79356b
A
2972 if (!(nmp->nm_flag & NFSMNT_NFSV3))
2973 nmp->nm_flag &= ~NFSMNT_RDIRPLUS; /* dk@farm.org */
2974 if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
91447636 2975 error = nfs_readdirplusrpc(vp, uiop, cr, p);
1c79356b
A
2976 if (error == NFSERR_NOTSUPP)
2977 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
2978 }
2979 if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
91447636 2980 error = nfs_readdirrpc(vp, uiop, cr, p);
55e303ae
A
2981 if (!error) {
2982 bp->nb_validoff = 0;
2983 bp->nb_validend = uiop->uio_offset - NBOFF(bp);
2984 bp->nb_valid = (1 << (round_page_32(bp->nb_validend)/PAGE_SIZE)) - 1;
2985 }
1c79356b
A
2986 break;
2987 default:
91447636 2988 printf("nfs_doio: type %x unexpected\n", vtype);
1c79356b
A
2989 break;
2990 };
2991 if (error) {
55e303ae
A
2992 SET(bp->nb_flags, NB_ERROR);
2993 bp->nb_error = error;
1c79356b 2994 }
55e303ae 2995
1c79356b 2996 } else {
55e303ae
A
2997 /* we're doing a write */
2998 int doff, dend = 0;
2999
3000 /* We need to make sure the pages are locked before doing I/O. */
91447636 3001 if (!ISSET(bp->nb_flags, NB_META) && UBCINFOEXISTS(vp)) {
55e303ae
A
3002 if (!ISSET(bp->nb_flags, NB_PAGELIST)) {
3003 error = nfs_buf_upl_setup(bp);
3004 if (error) {
3005 printf("nfs_doio: upl create failed %d\n", error);
3006 SET(bp->nb_flags, NB_ERROR);
3007 bp->nb_error = EIO;
3008 return (EIO);
3009 }
3010 nfs_buf_upl_check(bp);
3011 }
3012 }
3013
3014 if (ISSET(bp->nb_flags, NB_WASDIRTY)) {
3015 FSDBG(256, bp, NBOFF(bp), bp->nb_dirty, 0xd00dee);
3016 /*
3017 * There are pages marked dirty that need to be written out.
3018 *
3019 * We don't want to just combine the write range with the
3020 * range of pages that are dirty because that could cause us
3021 * to write data that wasn't actually written to.
3022 * We also don't want to write data more than once.
3023 *
3024 * If the dirty range just needs to be committed, we do that.
3025 * Otherwise, we write the dirty range and clear the dirty bits
3026 * for any COMPLETE pages covered by that range.
3027 * If there are dirty pages left after that, we write out the
3028 * parts that we haven't written yet.
3029 */
3030 }
3031
fa4905b1 3032 /*
55e303ae
A
3033 * If NB_NEEDCOMMIT is set, a commit rpc may do the trick. If not
3034 * an actual write will have to be done.
3035 * If NB_WRITEINPROG is already set, then push it with a write anyhow.
fa4905b1 3036 */
8f6c56a5
A
3037 if (ISSET(bp->nb_flags, NB_NEEDCOMMIT))
3038 nfs_buf_check_write_verifier(np, bp);
55e303ae
A
3039 if ((bp->nb_flags & (NB_NEEDCOMMIT | NB_WRITEINPROG)) == NB_NEEDCOMMIT) {
3040 doff = NBOFF(bp) + bp->nb_dirtyoff;
3041 SET(bp->nb_flags, NB_WRITEINPROG);
3042 error = nfs_commit(vp, doff, bp->nb_dirtyend - bp->nb_dirtyoff,
3043 bp->nb_wcred, bp->nb_proc);
3044 CLR(bp->nb_flags, NB_WRITEINPROG);
3045 if (!error) {
3046 bp->nb_dirtyoff = bp->nb_dirtyend = 0;
3047 CLR(bp->nb_flags, NB_NEEDCOMMIT);
3048 np->n_needcommitcnt--;
3049 CHECK_NEEDCOMMITCNT(np);
8f6c56a5 3050 }
fa4905b1 3051 }
1c79356b 3052
55e303ae
A
3053 if (!error && bp->nb_dirtyend > 0) {
3054 /* there's a dirty range that needs to be written out */
3055 u_int32_t pagemask;
3056 int firstpg, lastpg;
3057
91447636 3058 if (NBOFF(bp) + bp->nb_dirtyend > (off_t)np->n_size)
55e303ae
A
3059 bp->nb_dirtyend = np->n_size - NBOFF(bp);
3060
3061 NFS_BUF_MAP(bp);
3062
3063 doff = bp->nb_dirtyoff;
3064 dend = bp->nb_dirtyend;
3065
3066 /* if doff page is dirty, move doff to start of page */
3067 if (NBPGDIRTY(bp,doff/PAGE_SIZE))
3068 doff -= doff & PAGE_MASK;
3069 /* try to expand write range to include preceding dirty pages */
3070 if (!(doff & PAGE_MASK))
3071 while (doff > 0 && NBPGDIRTY(bp,(doff-1)/PAGE_SIZE))
3072 doff -= PAGE_SIZE;
3073 /* if dend page is dirty, move dend to start of next page */
3074 if ((dend & PAGE_MASK) && NBPGDIRTY(bp,dend/PAGE_SIZE))
3075 dend = round_page_32(dend);
3076 /* try to expand write range to include trailing dirty pages */
3077 if (!(dend & PAGE_MASK))
3078 while (dend < bp->nb_bufsize && NBPGDIRTY(bp,dend/PAGE_SIZE))
3079 dend += PAGE_SIZE;
3080 /* make sure to keep dend clipped to EOF */
91447636 3081 if (NBOFF(bp) + dend > (off_t)np->n_size)
55e303ae
A
3082 dend = np->n_size - NBOFF(bp);
3083 /* calculate range of complete pages being written */
3084 firstpg = round_page_32(doff) / PAGE_SIZE;
3085 lastpg = (trunc_page_32(dend) - 1)/ PAGE_SIZE;
3086 /* calculate mask for that page range */
3087 pagemask = ((1 << (lastpg+1)) - 1) & ~((1 << firstpg) - 1);
3088
3089 /* compare page mask to nb_dirty; if there are other dirty pages */
3090 /* then write FILESYNC; otherwise, write UNSTABLE if async and */
0c530ab8 3091 /* not needcommit/stable; otherwise write FILESYNC */
55e303ae
A
3092 if (bp->nb_dirty & ~pagemask)
3093 iomode = NFSV3WRITE_FILESYNC;
0c530ab8 3094 else if ((bp->nb_flags & (NB_ASYNC | NB_NEEDCOMMIT | NB_STABLE)) == NB_ASYNC)
1c79356b
A
3095 iomode = NFSV3WRITE_UNSTABLE;
3096 else
3097 iomode = NFSV3WRITE_FILESYNC;
55e303ae
A
3098
3099 /* write the dirty range */
91447636
A
3100 io.iov_len = dend - doff;
3101 uio_uio_resid_set(uiop, io.iov_len);
55e303ae 3102 uiop->uio_offset = NBOFF(bp) + doff;
91447636 3103 io.iov_base = (uintptr_t) bp->nb_data + doff;
55e303ae
A
3104 uiop->uio_rw = UIO_WRITE;
3105
91447636 3106 OSAddAtomic(1, (SInt32*)&nfsstats.write_bios);
55e303ae
A
3107
3108 SET(bp->nb_flags, NB_WRITEINPROG);
8f6c56a5 3109 error = nfs_writerpc(vp, uiop, cr, p, &iomode, &bp->nb_verf);
55e303ae
A
3110 /* clear dirty bits for pages we've written */
3111 if (!error)
3112 bp->nb_dirty &= ~pagemask;
3113 /* set/clear needcommit flag */
3114 if (!error && iomode == NFSV3WRITE_UNSTABLE) {
3115 if (!ISSET(bp->nb_flags, NB_NEEDCOMMIT))
3116 np->n_needcommitcnt++;
3117 SET(bp->nb_flags, NB_NEEDCOMMIT);
3118 /* make sure nb_dirtyoff/nb_dirtyend reflect actual range written */
3119 bp->nb_dirtyoff = doff;
3120 bp->nb_dirtyend = dend;
3121 } else {
3122 if (ISSET(bp->nb_flags, NB_NEEDCOMMIT)) {
3123 np->n_needcommitcnt--;
3124 CHECK_NEEDCOMMITCNT(np);
3125 }
3126 CLR(bp->nb_flags, NB_NEEDCOMMIT);
3127 }
3128 CLR(bp->nb_flags, NB_WRITEINPROG);
1c79356b 3129 /*
55e303ae
A
3130 * For an interrupted write, the buffer is still valid and the write
3131 * hasn't been pushed to the server yet, so we can't set NB_ERROR and
3132 * report the interruption by setting NB_EINTR. For the NB_ASYNC case,
3133 * NB_EINTR is not relevant.
3134 *
3135 * For the case of a V3 write rpc not being committed to stable
3136 * storage, the block is still dirty and requires either a commit rpc
3137 * or another write rpc with iomode == NFSV3WRITE_FILESYNC before the
3138 * block is reused. This is indicated by setting the NB_DELWRI and
3139 * NB_NEEDCOMMIT flags.
1c79356b 3140 */
55e303ae 3141 if (error == EINTR || (!error && bp->nb_flags & NB_NEEDCOMMIT)) {
0c530ab8 3142 CLR(bp->nb_flags, NB_INVAL);
55e303ae
A
3143 if (!ISSET(bp->nb_flags, NB_DELWRI)) {
3144 SET(bp->nb_flags, NB_DELWRI);
91447636
A
3145 OSAddAtomic(1, (SInt32*)&nfs_nbdwrite);
3146 NFSBUFCNTCHK(0);
55e303ae
A
3147 }
3148 FSDBG(261, bp->nb_validoff, bp->nb_validend,
3149 bp->nb_bufsize, 0);
3150 /*
3151 * Since for the NB_ASYNC case, nfs_bwrite() has
3152 * reassigned the buffer to the clean list, we have to
3153 * reassign it back to the dirty one. Ugh.
3154 */
3155 if (ISSET(bp->nb_flags, NB_ASYNC)) {
3156 /* move to dirty list */
91447636 3157 lck_mtx_lock(nfs_buf_mutex);
55e303ae
A
3158 if (bp->nb_vnbufs.le_next != NFSNOLIST)
3159 LIST_REMOVE(bp, nb_vnbufs);
3160 LIST_INSERT_HEAD(&np->n_dirtyblkhd, bp, nb_vnbufs);
91447636 3161 lck_mtx_unlock(nfs_buf_mutex);
55e303ae
A
3162 } else {
3163 SET(bp->nb_flags, NB_EINTR);
3164 }
1c79356b 3165 } else {
55e303ae 3166 /* either there's an error or we don't need to commit */
1c79356b 3167 if (error) {
55e303ae
A
3168 SET(bp->nb_flags, NB_ERROR);
3169 bp->nb_error = np->n_error = error;
3170 np->n_flag |= NWRITEERR;
91447636
A
3171 /*
3172 * There was a write error and we need to
3173 * invalidate attrs and flush buffers in
3174 * order to sync up with the server.
3175 * (if this write was extending the file,
3176 * we may no longer know the correct size)
3177 *
3178 * But we can't call vinvalbuf while holding
3179 * this buffer busy. Set a flag to do it after
3180 * releasing the buffer.
3181 *
3182 * Note we can only invalidate in this function
3183 * if this is an async write and so the iodone
3184 * below will release the buffer. Also, we
3185 * shouldn't call vinvalbuf from nfsiod because
3186 * that may deadlock waiting for the completion
3187 * of writes that are queued up behind this one.
3188 */
3189 if (ISSET(bp->nb_flags, NB_ASYNC) &&
3190 !ISSET(bp->nb_flags, NB_IOD)) {
3191 invalidate = 1;
3192 } else {
3193 /* invalidate later */
3194 np->n_flag |= NNEEDINVALIDATE;
3195 }
3196 NATTRINVALIDATE(np);
1c79356b 3197 }
55e303ae
A
3198 /* clear the dirty range */
3199 bp->nb_dirtyoff = bp->nb_dirtyend = 0;
1c79356b 3200 }
55e303ae
A
3201 }
3202
3203 if (!error && bp->nb_dirty) {
3204 /* there are pages marked dirty that need to be written out */
91447636 3205 int pg, count, npages, off;
55e303ae 3206
91447636 3207 OSAddAtomic(1, (SInt32*)&nfsstats.write_bios);
1c79356b 3208
55e303ae
A
3209 NFS_BUF_MAP(bp);
3210
3211 /*
3212 * we do these writes synchronously because we can't really
3213 * support the unstable/needommit method. We could write
3214 * them unstable, clear the dirty bits, and then commit the
3215 * whole block later, but if we need to rewrite the data, we
3216 * won't have any idea which pages were written because that
3217 * info can't be stored in the nb_dirtyoff/nb_dirtyend. We
3218 * also can't leave the dirty bits set because then we wouldn't
3219 * be able to tell if the pages were re-dirtied between the end
3220 * of the write and the commit.
3221 */
3222 iomode = NFSV3WRITE_FILESYNC;
3223 uiop->uio_rw = UIO_WRITE;
3224
3225 SET(bp->nb_flags, NB_WRITEINPROG);
3226 npages = bp->nb_bufsize/PAGE_SIZE;
3227 for (pg=0; pg < npages; pg++) {
3228 if (!NBPGDIRTY(bp,pg))
3229 continue;
91447636
A
3230 count = 1;
3231 while (((pg+count) < npages) && NBPGDIRTY(bp,pg+count))
3232 count++;
3233 /* write count pages starting with page pg */
55e303ae 3234 off = pg * PAGE_SIZE;
91447636 3235 len = count * PAGE_SIZE;
55e303ae
A
3236
3237 /* clip writes to EOF */
91447636 3238 if (NBOFF(bp) + off + len > (off_t)np->n_size)
55e303ae
A
3239 len -= (NBOFF(bp) + off + len) - np->n_size;
3240 if (len > 0) {
91447636
A
3241 io.iov_len = len;
3242 uio_uio_resid_set(uiop, io.iov_len);
55e303ae 3243 uiop->uio_offset = NBOFF(bp) + off;
91447636 3244 io.iov_base = (uintptr_t) bp->nb_data + off;
8f6c56a5 3245 error = nfs_writerpc(vp, uiop, cr, p, &iomode, &bp->nb_verf);
55e303ae
A
3246 if (error)
3247 break;
3248 }
3249 /* clear dirty bits */
91447636 3250 while (count--) {
55e303ae
A
3251 bp->nb_dirty &= ~(1 << pg);
3252 /* leave pg on last page */
91447636 3253 if (count) pg++;
55e303ae 3254 }
fa4905b1 3255 }
55e303ae
A
3256 if (!error) {
3257 if (ISSET(bp->nb_flags, NB_NEEDCOMMIT)) {
3258 np->n_needcommitcnt--;
3259 CHECK_NEEDCOMMITCNT(np);
3260 }
3261 CLR(bp->nb_flags, NB_NEEDCOMMIT);
fa4905b1 3262 }
55e303ae
A
3263 CLR(bp->nb_flags, NB_WRITEINPROG);
3264 FSDBG_BOT(256, bp->nb_validoff, bp->nb_validend, bp->nb_bufsize,
fa4905b1 3265 np->n_size);
1c79356b 3266 }
1c79356b 3267
55e303ae
A
3268 if (error) {
3269 SET(bp->nb_flags, NB_ERROR);
3270 bp->nb_error = error;
3271 }
1c79356b 3272 }
1c79356b 3273
55e303ae
A
3274 FSDBG_BOT(256, bp->nb_validoff, bp->nb_validend, bp->nb_bufsize, error);
3275
3276 nfs_buf_iodone(bp);
91447636
A
3277
3278 if (invalidate) {
3279 /*
3280 * There was a write error and we need to
3281 * invalidate attrs and flush buffers in
3282 * order to sync up with the server.
3283 * (if this write was extending the file,
3284 * we may no longer know the correct size)
3285 *
3286 * But we couldn't call vinvalbuf while holding
3287 * the buffer busy. So we call vinvalbuf() after
3288 * releasing the buffer.
3289 *
3290 * Note: we don't bother calling nfs_vinvalbuf() if
3291 * there's already a flush in progress.
3292 */
3293 if (!(np->n_flag & NFLUSHINPROG))
3294 nfs_vinvalbuf(vp, V_SAVE|V_IGNORE_WRITEERR, cr, p, 1);
3295 }
3296
1c79356b
A
3297 return (error);
3298}