X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6d2010ae8f7a6078e10b361c6962983bab233e0f..c18c124eaa464aaaa5549e99e5a70fc9cbb50944:/bsd/nfs/nfs4_vnops.c diff --git a/bsd/nfs/nfs4_vnops.c b/bsd/nfs/nfs4_vnops.c index ca874aa7c..2682d94be 100644 --- a/bsd/nfs/nfs4_vnops.c +++ b/bsd/nfs/nfs4_vnops.c @@ -80,7 +80,7 @@ #include int -nfs4_access_rpc(nfsnode_t np, u_int32_t *access, vfs_context_t ctx) +nfs4_access_rpc(nfsnode_t np, u_int32_t *access, int rpcflags, vfs_context_t ctx) { int error = 0, lockerror = ENOENT, status, numops, slot; u_int64_t xid; @@ -115,7 +115,9 @@ nfs4_access_rpc(nfsnode_t np, u_int32_t *access, vfs_context_t ctx) nfsm_chain_build_done(error, &nmreq); nfsm_assert(error, (numops == 0), EPROTO); nfsmout_if(error); - error = nfs_request(np, NULL, &nmreq, NFSPROC4_COMPOUND, ctx, &si, &nmrep, &xid, &status); + error = nfs_request2(np, NULL, &nmreq, NFSPROC4_COMPOUND, + vfs_context_thread(ctx), vfs_context_ucred(ctx), + &si, rpcflags, &nmrep, &xid, &status); if ((lockerror = nfs_node_lock(np))) error = lockerror; @@ -189,7 +191,7 @@ nfs4_getattr_rpc( struct nfsm_chain nmreq, nmrep; struct nfsreq_secinfo_args si; - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; acls = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_ACL); @@ -202,6 +204,9 @@ nfs4_getattr_rpc( if (flags & NGA_MONITOR) /* vnode monitor requests should be soft */ rpcflags = R_RECOVER; + if (flags & NGA_SOFT) /* Return ETIMEDOUT if server not responding */ + rpcflags |= R_SOFT; + NFSREQ_SECINFO_SET(&si, np, NULL, 0, NULL, 0); nfsm_chain_null(&nmreq); nfsm_chain_null(&nmrep); @@ -255,7 +260,7 @@ nfs4_readlink_rpc(nfsnode_t np, char *buf, uint32_t *buflenp, vfs_context_t ctx) struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) return (EINVAL); @@ -324,7 +329,7 @@ nfs4_read_rpc_async( struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) @@ -373,7 +378,7 @@ nfs4_read_rpc_async_finish( struct nfsm_chain nmrep; nmp = NFSTONMP(np); - if (!nmp) { + if (nfs_mount_gone(nmp)) { nfs_request_async_cancel(req); return (ENXIO); } @@ -431,7 +436,7 @@ nfs4_write_rpc_async( struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) @@ -491,7 +496,7 @@ nfs4_write_rpc_async_finish( struct nfsm_chain nmrep; nmp = NFSTONMP(np); - if (!nmp) { + if (nfs_mount_gone(nmp)) { nfs_request_async_cancel(req); return (ENXIO); } @@ -503,7 +508,7 @@ nfs4_write_rpc_async_finish( if (error == EINPROGRESS) /* async request restarted */ return (error); nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) error = ENXIO; if (!error && (lockerror = nfs_node_lock(np))) error = lockerror; @@ -560,7 +565,7 @@ nfs4_remove_rpc( struct nfsreq_secinfo_args si; nmp = NFSTONMP(dnp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; if (dnp->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) @@ -634,7 +639,7 @@ nfs4_rename_rpc( struct nfsreq_secinfo_args si; nmp = NFSTONMP(fdnp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; if (fdnp->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) @@ -733,7 +738,7 @@ nfs4_readdir_rpc(nfsnode_t dnp, struct nfsbuf *bp, vfs_context_t ctx) struct nfsreq_secinfo_args si; nmp = NFSTONMP(dnp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; nmreaddirsize = nmp->nm_readdirsize; @@ -778,7 +783,7 @@ nfs4_readdir_rpc(nfsnode_t dnp, struct nfsbuf *bp, vfs_context_t ctx) } else { cookie = bp->nb_lblkno; /* increment with every buffer read */ - OSAddAtomic(1, &nfsstats.readdir_bios); + OSAddAtomic64(1, &nfsstats.readdir_bios); } lastcookie = cookie; @@ -946,7 +951,7 @@ nextbuffer: space_free = nfs_dir_buf_freespace(bp, rdirplus); dp = NFS_DIR_BUF_FIRST_DIRENTRY(bp); /* increment with every buffer read */ - OSAddAtomic(1, &nfsstats.readdir_bios); + OSAddAtomic64(1, &nfsstats.readdir_bios); } nmrepsave = nmrep; dp->d_fileno = cookie; /* placeholder */ @@ -1081,7 +1086,7 @@ nfs4_lookup_rpc_async( struct nfsreq_secinfo_args si; nmp = NFSTONMP(dnp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; if (dnp->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) @@ -1230,7 +1235,7 @@ nfs4_commit_rpc( nmp = NFSTONMP(np); FSDBG(521, np, offset, count, nmp ? nmp->nm_state : 0); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) return (EINVAL); @@ -1305,7 +1310,7 @@ nfs4_pathconf_rpc( struct nfs_vattr nvattr; struct nfsreq_secinfo_args si; - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) @@ -1373,7 +1378,8 @@ nfs4_vnop_getattr( struct nfs_vattr nva; int error, acls, ngaflags; - if (!(nmp = VTONMP(ap->a_vp))) + nmp = VTONMP(ap->a_vp); + if (nfs_mount_gone(nmp)) return (ENXIO); acls = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_ACL); @@ -1484,7 +1490,7 @@ nfs4_setattr_rpc( nfs_stateid stateid; struct nfsreq_secinfo_args si; - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) @@ -1647,7 +1653,7 @@ nfs_mount_state_in_use_start(struct nfsmount *nmp, thread_t thd) struct timespec ts = { 1, 0 }; int error = 0, slpflag = (NMFLAG(nmp, INTR) && thd) ? PCATCH : 0; - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); lck_mtx_lock(&nmp->nm_lock); if (nmp->nm_state & (NFSSTA_FORCE|NFSSTA_DEAD)) { @@ -1678,7 +1684,7 @@ nfs_mount_state_in_use_end(struct nfsmount *nmp, int error) { int restart = nfs_mount_state_error_should_restart(error); - if (!nmp) + if (nfs_mount_gone(nmp)) return (restart); lck_mtx_lock(&nmp->nm_lock); if (restart && (error != NFSERR_OLD_STATEID) && (error != NFSERR_GRACE)) { @@ -1759,7 +1765,7 @@ nfs_open_state_set_busy(nfsnode_t np, thread_t thd) int error = 0, slpflag; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); slpflag = (NMFLAG(nmp, INTR) && thd) ? PCATCH : 0; @@ -1902,7 +1908,7 @@ nfs_open_owner_set_busy(struct nfs_open_owner *noop, thread_t thd) int error = 0, slpflag; nmp = noop->noo_mount; - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); slpflag = (NMFLAG(nmp, INTR) && thd) ? PCATCH : 0; @@ -2083,7 +2089,7 @@ nfs_open_file_set_busy(struct nfs_open_file *nofp, thread_t thd) int error = 0, slpflag; nmp = nofp->nof_owner->noo_mount; - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); slpflag = (NMFLAG(nmp, INTR) && thd) ? PCATCH : 0; @@ -2669,7 +2675,7 @@ nfs_vnop_mmap( struct nfs_open_file *nofp = NULL; nmp = VTONMP(vp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (!vnode_isreg(vp) || !(ap->a_fflags & (PROT_READ|PROT_WRITE))) @@ -2830,6 +2836,26 @@ out: } if (noop) nfs_open_owner_rele(noop); + + if (!error) { + int ismapped = 0; + nfs_node_lock_force(np); + if ((np->n_flag & NISMAPPED) == 0) { + np->n_flag |= NISMAPPED; + ismapped = 1; + } + nfs_node_unlock(np); + if (ismapped) { + lck_mtx_lock(&nmp->nm_lock); + nmp->nm_state &= ~NFSSTA_SQUISHY; + nmp->nm_curdeadtimeout = nmp->nm_deadtimeout; + if (nmp->nm_curdeadtimeout <= 0) + nmp->nm_deadto_start = 0; + nmp->nm_mappers++; + lck_mtx_unlock(&nmp->nm_lock); + } + } + return (error); } @@ -2849,11 +2875,27 @@ nfs_vnop_mnomap( struct nfs_open_file *nofp = NULL; off_t size; int error; - + int is_mapped_flag = 0; + nmp = VTONMP(vp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); + nfs_node_lock_force(np); + if (np->n_flag & NISMAPPED) { + is_mapped_flag = 1; + np->n_flag &= ~NISMAPPED; + } + nfs_node_unlock(np); + if (is_mapped_flag) { + lck_mtx_lock(&nmp->nm_lock); + if (nmp->nm_mappers) + nmp->nm_mappers--; + else + NP(np, "nfs_vnop_mnomap: removing mmap reference from mount, but mount has no files mmapped"); + lck_mtx_unlock(&nmp->nm_lock); + } + /* flush buffers/ubc before we drop the open (in case it's our last open) */ nfs_flush(np, MNT_WAIT, vfs_context_thread(ctx), V_IGNORE_WRITEERR); if (UBCINFOEXISTS(vp) && (size = ubc_getsize(vp))) @@ -3019,7 +3061,7 @@ nfs_lock_owner_set_busy(struct nfs_lock_owner *nlop, thread_t thd) int error = 0, slpflag; nmp = nlop->nlo_open_owner->noo_mount; - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); slpflag = (NMFLAG(nmp, INTR) && thd) ? PCATCH : 0; @@ -3179,7 +3221,7 @@ nfs4_setlock_rpc( struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) return (EINVAL); @@ -3302,7 +3344,7 @@ nfs4_unlock_rpc( struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) return (EINVAL); @@ -3379,7 +3421,7 @@ nfs4_getlock_rpc( struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) return (EINVAL); @@ -3463,7 +3505,7 @@ nfs_advlock_getlock( int error = 0, answered = 0; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); restart: @@ -3539,7 +3581,7 @@ nfs_advlock_setlock( struct timespec ts = {1, 0}; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); slpflag = NMFLAG(nmp, INTR) ? PCATCH : 0; @@ -3797,7 +3839,8 @@ error_out: wakeup(newnflp); } else { /* remove newnflp from lock list and destroy */ - TAILQ_REMOVE(&np->n_locks, newnflp, nfl_link); + if (inqueue) + TAILQ_REMOVE(&np->n_locks, newnflp, nfl_link); nfs_file_lock_destroy(newnflp); } lck_mtx_unlock(&np->n_openlock); @@ -3950,7 +3993,7 @@ nfs_advlock_unlock( int error = 0, willsplit = 0, send_unlock_rpcs = 1; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); restart: @@ -4205,7 +4248,7 @@ nfs_vnop_advlock( #define OFF_MAX QUAD_MAX nmp = VTONMP(ap->a_vp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); lck_mtx_lock(&nmp->nm_lock); if ((nmp->nm_vers <= NFS_VER3) && (nmp->nm_lockmode == NFS_LOCK_MODE_DISABLED)) { @@ -4616,7 +4659,7 @@ nfs4_open_rpc_internal( return (EINVAL); nmp = VTONMP(dvp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; namedattrs = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR); @@ -4953,7 +4996,7 @@ nfs4_claim_delegated_open_rpc( struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; @@ -5205,7 +5248,7 @@ nfs4_open_reclaim_rpc( struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; @@ -5392,7 +5435,7 @@ nfs4_open_downgrade_rpc( struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; @@ -5462,7 +5505,7 @@ nfs4_close_rpc( struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; @@ -5753,6 +5796,7 @@ nfs_release_open_state_for_node(nfsnode_t np, int force) lck_mtx_lock(&nofp->nof_lock); nofp->nof_flags &= ~NFS_OPEN_FILE_REOPEN; nofp->nof_flags |= NFS_OPEN_FILE_LOST; + lck_mtx_unlock(&nofp->nof_lock); if (!force && nmp && (nmp->nm_vers >= NFS_VER4)) nfs4_close_rpc(np, nofp, NULL, nofp->nof_owner->noo_cred, R_RECOVER); @@ -5836,7 +5880,7 @@ nfs4_delegation_return_enqueue(nfsnode_t np) struct nfsmount *nmp; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return; lck_mtx_lock(&np->n_openlock); @@ -5862,7 +5906,7 @@ nfs4_delegation_return(nfsnode_t np, int flags, thread_t thd, kauth_cred_t cred) int error; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); /* first, make sure the node's marked for delegation return */ @@ -5993,11 +6037,11 @@ nfs_vnop_read( int error; if (vnode_vtype(ap->a_vp) != VREG) - return (EPERM); + return (vnode_vtype(vp) == VDIR) ? EISDIR : EPERM; np = VTONFS(vp); nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (np->n_flag & NREVOKE) return (EIO); @@ -6088,7 +6132,7 @@ nfs4_vnop_create( struct nfs_open_file *newnofp = NULL, *nofp = NULL; nmp = VTONMP(dvp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (vap) @@ -6258,7 +6302,7 @@ nfs4_create_rpc( struct nfsreq_secinfo_args si; nmp = NFSTONMP(dnp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; namedattrs = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR); @@ -6445,7 +6489,7 @@ nfs4_vnop_mknod( int error; nmp = VTONMP(ap->a_dvp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (!VATTR_IS_ACTIVE(ap->a_vap, va_type)) @@ -6537,7 +6581,7 @@ nfs4_vnop_link( return (EXDEV); nmp = VTONMP(vp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); nfsvers = nmp->nm_vers; if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) @@ -6653,7 +6697,7 @@ nfs4_vnop_rmdir( return (EINVAL); nmp = NFSTONMP(dnp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); namedattrs = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR); @@ -6737,7 +6781,7 @@ nfs4_named_attr_dir_get(nfsnode_t np, int fetch, vfs_context_t ctx) struct nfsreq_secinfo_args si; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (NULL); if (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL) return (NULL); @@ -6905,7 +6949,7 @@ nfs4_named_attr_get( slen = sizeof(sbuf); nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); NVATTR_INIT(&nvattr); negnamecache = !NMFLAG(nmp, NONEGNAMECACHE); @@ -6984,7 +7028,7 @@ nfs4_named_attr_get( /* FALLTHROUGH */ case -1: /* cache hit, not really an error */ - OSAddAtomic(1, &nfsstats.lookupcache_hits); + OSAddAtomic64(1, &nfsstats.lookupcache_hits); if (!anp && avp) *anpp = anp = VTONFS(avp); @@ -7524,7 +7568,7 @@ nfsmout: /* don't save the data if dirty or potential I/O conflict */ if (!error && bp && !bp->nb_dirtyoff && !(bp->nb_dirty & pagemask) && timevalcmp(&anp->n_lastio, &now, <)) { - OSAddAtomic(1, &nfsstats.read_bios); + OSAddAtomic64(1, &nfsstats.read_bios); CLR(bp->nb_flags, (NB_DONE|NB_ASYNC)); SET(bp->nb_flags, NB_READ); NFS_BUF_MAP(bp); @@ -7590,7 +7634,7 @@ nfs4_named_attr_remove(nfsnode_t np, nfsnode_t anp, const char *name, vfs_contex int error, putanp = 0; nmp = NFSTONMP(np); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); bzero(&cn, sizeof(cn)); @@ -7658,7 +7702,7 @@ nfs4_vnop_getxattr( int error = 0, isrsrcfork; nmp = VTONMP(ap->a_vp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR)) @@ -7722,7 +7766,7 @@ nfs4_vnop_setxattr( struct vnop_write_args vwa; nmp = VTONMP(ap->a_vp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR)) @@ -7860,7 +7904,7 @@ nfs4_vnop_removexattr( struct nfsmount *nmp = VTONMP(ap->a_vp); int error; - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR)) return (ENOTSUP); @@ -7895,7 +7939,7 @@ nfs4_vnop_listxattr( struct direntry *dp; nmp = VTONMP(ap->a_vp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR)) @@ -7951,7 +7995,7 @@ nfs4_vnop_listxattr( nextcookie = lbn = 0; while (!error && !done) { - OSAddAtomic(1, &nfsstats.biocache_readdirs); + OSAddAtomic64(1, &nfsstats.biocache_readdirs); cookie = nextcookie; getbuffer: error = nfs_buf_get(adnp, lbn, NFS_DIRBLKSIZ, vfs_context_thread(ctx), NBLK_READ, &bp); @@ -8041,7 +8085,7 @@ nfs4_vnop_getnamedstream( int error = 0; nmp = VTONMP(ap->a_vp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR)) @@ -8088,7 +8132,7 @@ nfs4_vnop_makenamedstream( int error = 0; nmp = VTONMP(ap->a_vp); - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR)) @@ -8126,7 +8170,7 @@ nfs4_vnop_removenamedstream( nfsnode_t np = ap->a_vp ? VTONFS(ap->a_vp) : NULL; nfsnode_t anp = ap->a_svp ? VTONFS(ap->a_svp) : NULL; - if (!nmp) + if (nfs_mount_gone(nmp)) return (ENXIO); /*