From f6e02ff4a0d7023896e16b08bdaf422c49d0dc8f Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Fri, 4 May 2012 11:32:31 -0400 Subject: [PATCH] driver: make mount upcalls for shared mounts even if CreateVNetRoot() finds an existing compatible mount, make a MOUNT upcall and pass that session to the daemon. the daemon can avoid creating a new root/client/seession, but still has a chance to verify the mount path with LOOKUPs and fetch fs attributes for the new VNetRoot when the daemon is given an existing root, handle_mount() avoids any extra reference counting on it. while we can make multiple MOUNT upcalls on a shared mount, we'll still only send the one UNMOUNT upcall on FinalizeNetRoot() Signed-off-by: Casey Bodley --- daemon/mount.c | 35 ++++++++++++++++++++++------------- sys/nfs41_driver.c | 32 +++++++++++++++----------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/daemon/mount.c b/daemon/mount.c index 8c4efe8..55345f6 100644 --- a/daemon/mount.c +++ b/daemon/mount.c @@ -69,17 +69,24 @@ static int handle_mount(nfs41_upcall *upcall) eprintf("nfs41_server_resolve() failed with %d\n", status); goto out; } - // create root - status = nfs41_root_create(args->hostname, args->sec_flavor, - args->wsize + WRITE_OVERHEAD, args->rsize + READ_OVERHEAD, &root); - if (status) { - eprintf("nfs41_root_create() failed %d\n", status); - goto out; - } - // add a mount - root->uid = upcall->uid; - root->gid = upcall->gid; + if (upcall->root_ref != INVALID_HANDLE_VALUE) { + /* use an existing root from a previous mount, but don't take an + * extra reference; we'll only get one UNMOUNT upcall for each root */ + root = upcall->root_ref; + } else { + // create root + status = nfs41_root_create(args->hostname, args->sec_flavor, + args->wsize + WRITE_OVERHEAD, args->rsize + READ_OVERHEAD, &root); + if (status) { + eprintf("nfs41_root_create() failed %d\n", status); + goto out; + } + root->uid = upcall->uid; + root->gid = upcall->gid; + } + + // find or create the client/session status = nfs41_root_mount_addrs(root, &addrs, 0, 0, &client); if (status) { eprintf("nfs41_root_mount_addrs() failed with %d\n", status); @@ -89,7 +96,7 @@ static int handle_mount(nfs41_upcall *upcall) // make a copy of the path for nfs41_lookup() InitializeSRWLock(&path.lock); if (FAILED(StringCchCopyA(path.path, NFS41_MAX_PATH_LEN, args->path))) { - status = ERROR_BUFFER_OVERFLOW; + status = ERROR_FILENAME_EXCED_RANGE; goto out_err; } path.len = (unsigned short)strlen(path.path); @@ -105,14 +112,16 @@ static int handle_mount(nfs41_upcall *upcall) nfs41_superblock_fs_attributes(file.fh.superblock, &args->FsAttrs); + if (upcall->root_ref == INVALID_HANDLE_VALUE) + nfs41_root_ref(root); upcall->root_ref = root; - nfs41_root_ref(upcall->root_ref); args->lease_time = client->session->lease_time; out: return status; out_err: - nfs41_root_deref(root); + if (upcall->root_ref == INVALID_HANDLE_VALUE) + nfs41_root_deref(root); goto out; } diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c index 641cbfd..392247b 100644 --- a/sys/nfs41_driver.c +++ b/sys/nfs41_driver.c @@ -2619,7 +2619,7 @@ NTSTATUS nfs41_mount( DbgP("Server Name %wZ Mount Point %wZ SecFlavor %d\n", &config->SrvName, &config->MntPt, sec_flavor); #endif - status = nfs41_UpcallCreate(NFS41_MOUNT, NULL, INVALID_HANDLE_VALUE, + status = nfs41_UpcallCreate(NFS41_MOUNT, NULL, *session, INVALID_HANDLE_VALUE, *version, &config->MntPt, &entry); if (status) goto out; @@ -3050,23 +3050,21 @@ NTSTATUS nfs41_CreateVNetRoot( #endif } - if (!found_existing_mount || !found_matching_flavor) { - /* send the mount upcall */ - status = nfs41_mount(Config, pVNetRootContext->sec_flavor, - &pVNetRootContext->session, &nfs41d_version, - &pVNetRootContext->FsAttrs); - if (status != STATUS_SUCCESS) { - if (!found_existing_mount && - IsListEmpty(&pNetRootContext->mounts.head)) { - pNetRootContext->mounts_init = FALSE; - pVNetRootContext->session = INVALID_HANDLE_VALUE; - } - goto out_free; + /* send the mount upcall */ + status = nfs41_mount(Config, pVNetRootContext->sec_flavor, + &pVNetRootContext->session, &nfs41d_version, + &pVNetRootContext->FsAttrs); + if (status != STATUS_SUCCESS) { + if (!found_existing_mount && + IsListEmpty(&pNetRootContext->mounts.head)) { + pNetRootContext->mounts_init = FALSE; } - pVNetRootContext->timeout = Config->timeout; - RtlCopyMemory(&pNetRootContext->FsAttrs, &pVNetRootContext->FsAttrs, - sizeof(pVNetRootContext->FsAttrs)); - } + pVNetRootContext->session = INVALID_HANDLE_VALUE; + goto out_free; + } + pVNetRootContext->timeout = Config->timeout; + RtlCopyMemory(&pNetRootContext->FsAttrs, &pVNetRootContext->FsAttrs, + sizeof(pVNetRootContext->FsAttrs)); if (!found_existing_mount) { /* create a new mount entry and add it to the list */