| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: nfs_bio.c,v 1.188 2011/09/27 01:07:38 christos Exp $ */ | | 1 | /* $NetBSD: nfs_bio.c,v 1.188.22.1 2013/09/07 16:08:28 bouyer Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1989, 1993 | | 4 | * Copyright (c) 1989, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Rick Macklem at The University of Guelph. | | 8 | * Rick Macklem at The University of Guelph. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -25,27 +25,27 @@ | | | @@ -25,27 +25,27 @@ |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | * | | 33 | * |
34 | * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95 | | 34 | * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95 |
35 | */ | | 35 | */ |
36 | | | 36 | |
37 | #include <sys/cdefs.h> | | 37 | #include <sys/cdefs.h> |
38 | __KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.188 2011/09/27 01:07:38 christos Exp $"); | | 38 | __KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.188.22.1 2013/09/07 16:08:28 bouyer Exp $"); |
39 | | | 39 | |
40 | #ifdef _KERNEL_OPT | | 40 | #ifdef _KERNEL_OPT |
41 | #include "opt_nfs.h" | | 41 | #include "opt_nfs.h" |
42 | #include "opt_ddb.h" | | 42 | #include "opt_ddb.h" |
43 | #endif | | 43 | #endif |
44 | | | 44 | |
45 | #include <sys/param.h> | | 45 | #include <sys/param.h> |
46 | #include <sys/systm.h> | | 46 | #include <sys/systm.h> |
47 | #include <sys/resourcevar.h> | | 47 | #include <sys/resourcevar.h> |
48 | #include <sys/signalvar.h> | | 48 | #include <sys/signalvar.h> |
49 | #include <sys/proc.h> | | 49 | #include <sys/proc.h> |
50 | #include <sys/buf.h> | | 50 | #include <sys/buf.h> |
51 | #include <sys/vnode.h> | | 51 | #include <sys/vnode.h> |
| @@ -604,27 +604,27 @@ nfs_getcacheblk(struct vnode *vp, daddr_ | | | @@ -604,27 +604,27 @@ nfs_getcacheblk(struct vnode *vp, daddr_ |
604 | return (bp); | | 604 | return (bp); |
605 | } | | 605 | } |
606 | | | 606 | |
607 | /* | | 607 | /* |
608 | * Flush and invalidate all dirty buffers. If another process is already | | 608 | * Flush and invalidate all dirty buffers. If another process is already |
609 | * doing the flush, just wait for completion. | | 609 | * doing the flush, just wait for completion. |
610 | */ | | 610 | */ |
611 | int | | 611 | int |
612 | nfs_vinvalbuf(struct vnode *vp, int flags, kauth_cred_t cred, | | 612 | nfs_vinvalbuf(struct vnode *vp, int flags, kauth_cred_t cred, |
613 | struct lwp *l, int intrflg) | | 613 | struct lwp *l, int intrflg) |
614 | { | | 614 | { |
615 | struct nfsnode *np = VTONFS(vp); | | 615 | struct nfsnode *np = VTONFS(vp); |
616 | struct nfsmount *nmp = VFSTONFS(vp->v_mount); | | 616 | struct nfsmount *nmp = VFSTONFS(vp->v_mount); |
617 | int error = 0, slptimeo; | | 617 | int error = 0, allerror = 0, slptimeo; |
618 | bool catch; | | 618 | bool catch; |
619 | | | 619 | |
620 | if ((nmp->nm_flag & NFSMNT_INT) == 0) | | 620 | if ((nmp->nm_flag & NFSMNT_INT) == 0) |
621 | intrflg = 0; | | 621 | intrflg = 0; |
622 | if (intrflg) { | | 622 | if (intrflg) { |
623 | catch = true; | | 623 | catch = true; |
624 | slptimeo = 2 * hz; | | 624 | slptimeo = 2 * hz; |
625 | } else { | | 625 | } else { |
626 | catch = false; | | 626 | catch = false; |
627 | slptimeo = 0; | | 627 | slptimeo = 0; |
628 | } | | 628 | } |
629 | /* | | 629 | /* |
630 | * First wait for any other process doing a flush to complete. | | 630 | * First wait for any other process doing a flush to complete. |
| @@ -637,33 +637,42 @@ nfs_vinvalbuf(struct vnode *vp, int flag | | | @@ -637,33 +637,42 @@ nfs_vinvalbuf(struct vnode *vp, int flag |
637 | if (error && intrflg && nfs_sigintr(nmp, NULL, l)) { | | 637 | if (error && intrflg && nfs_sigintr(nmp, NULL, l)) { |
638 | mutex_exit(vp->v_interlock); | | 638 | mutex_exit(vp->v_interlock); |
639 | return EINTR; | | 639 | return EINTR; |
640 | } | | 640 | } |
641 | } | | 641 | } |
642 | | | 642 | |
643 | /* | | 643 | /* |
644 | * Now, flush as required. | | 644 | * Now, flush as required. |
645 | */ | | 645 | */ |
646 | np->n_flag |= NFLUSHINPROG; | | 646 | np->n_flag |= NFLUSHINPROG; |
647 | mutex_exit(vp->v_interlock); | | 647 | mutex_exit(vp->v_interlock); |
648 | error = vinvalbuf(vp, flags, cred, l, catch, 0); | | 648 | error = vinvalbuf(vp, flags, cred, l, catch, 0); |
649 | while (error) { | | 649 | while (error) { |
| | | 650 | if (allerror == 0) |
| | | 651 | allerror = error; |
650 | if (intrflg && nfs_sigintr(nmp, NULL, l)) { | | 652 | if (intrflg && nfs_sigintr(nmp, NULL, l)) { |
651 | error = EINTR; | | 653 | error = EINTR; |
652 | break; | | 654 | break; |
653 | } | | 655 | } |
654 | error = vinvalbuf(vp, flags, cred, l, 0, slptimeo); | | 656 | error = vinvalbuf(vp, flags, cred, l, 0, slptimeo); |
655 | } | | 657 | } |
656 | mutex_enter(vp->v_interlock); | | 658 | mutex_enter(vp->v_interlock); |
| | | 659 | if (allerror != 0) { |
| | | 660 | /* |
| | | 661 | * Keep error from vinvalbuf so fsync/close will know. |
| | | 662 | */ |
| | | 663 | np->n_error = allerror; |
| | | 664 | np->n_flag |= NWRITEERR; |
| | | 665 | } |
657 | if (error == 0) | | 666 | if (error == 0) |
658 | np->n_flag &= ~NMODIFIED; | | 667 | np->n_flag &= ~NMODIFIED; |
659 | np->n_flag &= ~NFLUSHINPROG; | | 668 | np->n_flag &= ~NFLUSHINPROG; |
660 | if (np->n_flag & NFLUSHWANT) { | | 669 | if (np->n_flag & NFLUSHWANT) { |
661 | np->n_flag &= ~NFLUSHWANT; | | 670 | np->n_flag &= ~NFLUSHWANT; |
662 | wakeup(&np->n_flag); | | 671 | wakeup(&np->n_flag); |
663 | } | | 672 | } |
664 | mutex_exit(vp->v_interlock); | | 673 | mutex_exit(vp->v_interlock); |
665 | return error; | | 674 | return error; |
666 | } | | 675 | } |
667 | | | 676 | |
668 | /* | | 677 | /* |
669 | * nfs_flushstalebuf: flush cache if it's stale. | | 678 | * nfs_flushstalebuf: flush cache if it's stale. |