+ /*
+ * Since the read path is a hot path, if we already have
+ * read access, lets go and try and do the read, without
+ * busying the mount and open file node for this open owner.
+ *
+ * N.B. This is inherently racy w.r.t. an execve using
+ * an already open file, in that the read at the end of
+ * this routine will be racing with a potential close.
+ * The code below ultimately has the same problem. In practice
+ * this does not seem to be an issue.
+ */
+ if (nofp->nof_access & NFS_OPEN_SHARE_ACCESS_READ) {
+ nfs_open_owner_rele(noop);
+ goto do_read;
+ }
+ error = nfs_mount_state_in_use_start(nmp, vfs_context_thread(ctx));
+ if (error) {
+ nfs_open_owner_rele(noop);
+ return error;
+ }
+ /*
+ * If we don't have a file already open with the access we need (read) then
+ * we need to open one. Otherwise we just co-opt an open. We might not already
+ * have access because we're trying to read the first page of the
+ * file for execve.
+ */
+ error = nfs_open_file_set_busy(nofp, vfs_context_thread(ctx));
+ if (error) {
+ nfs_mount_state_in_use_end(nmp, 0);
+ nfs_open_owner_rele(noop);
+ return error;
+ }
+ if (!(nofp->nof_access & NFS_OPEN_SHARE_ACCESS_READ)) {
+ /* we don't have the file open, so open it for read access if we're not denied */
+ if (nofp->nof_flags & NFS_OPEN_FILE_NEEDCLOSE) {
+ NP(np, "nfs_vnop_read: File already needs close access: 0x%x, cred: %d thread: %lld",
+ nofp->nof_access, kauth_cred_getuid(nofp->nof_owner->noo_cred), thread_tid(vfs_context_thread(ctx)));
+ }
+ if (nofp->nof_deny & NFS_OPEN_SHARE_DENY_READ) {
+ nfs_open_file_clear_busy(nofp);
+ nfs_mount_state_in_use_end(nmp, 0);