From 827a1b73681dd6481b322952808bfc6272b36194 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Tue, 12 Oct 2010 09:51:06 -0400 Subject: [PATCH] volume: cache volume attr results with vnetroot moved the FileSystemName definition back down to the kernel, so the daemon is no longer responsible for setting it. the driver uses the string length to calculate the buffer size needed for NFS41_V_NET_ROOT_EXTENSION.FsAttrs, and copies in the FileSystemName after the first successful volume attributes upcall Signed-off-by: Casey Bodley --- daemon/nfs41_const.h | 4 ---- daemon/upcall.h | 6 ------ daemon/volume.c | 22 ++++----------------- sys/nfs41_driver.c | 46 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 29 deletions(-) diff --git a/daemon/nfs41_const.h b/daemon/nfs41_const.h index 0a74cad..27bb361 100644 --- a/daemon/nfs41_const.h +++ b/daemon/nfs41_const.h @@ -41,10 +41,6 @@ #define UPCALL_BUF_SIZE 1024 -/* FileSystemName reported for FileFsAttributeInformation */ -#define NFS41_FILESYSTEM_NAME L"NFS" -#define NFS41_FILESYSTEM_NAME_LEN (sizeof(NFS41_FILESYSTEM_NAME)-sizeof(WCHAR)) - /* MaximumComponentNameLength reported for FileFsAttributeInformation */ #define NFS41_MAX_COMPONENT_LEN 64 #define NFS41_MAX_PATH_LEN MAX_PATH diff --git a/daemon/upcall.h b/daemon/upcall.h index 40f62f9..45fb941 100644 --- a/daemon/upcall.h +++ b/daemon/upcall.h @@ -141,12 +141,6 @@ typedef struct __volume_upcall_args { FILE_FS_SIZE_INFORMATION size; FILE_FS_FULL_SIZE_INFORMATION fullsize; FILE_FS_ATTRIBUTE_INFORMATION attribute; - - /* attribute.FileSystemName is WCHAR[1], so even though there's - * some extra space in the union from other members, reserve - * enough space for an arbitrary NFS41_FILESYSTEM_NAME_LEN */ - unsigned char buffer[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + - NFS41_FILESYSTEM_NAME_LEN]; } info; } volume_upcall_args; diff --git a/daemon/volume.c b/daemon/volume.c index 064b95d..508309b 100644 --- a/daemon/volume.c +++ b/daemon/volume.c @@ -98,7 +98,6 @@ static int handle_volume_attributes( bitmap4 attr_request = { 1, { FATTR4_WORD0_CASE_INSENSITIVE | FATTR4_WORD0_CASE_PRESERVING } }; PFILE_FS_ATTRIBUTE_INFORMATION attr = &args->info.attribute; - size_t max_length; int status = NO_ERROR; status = nfs41_getattr(session, NULL, &attr_request, &info); @@ -117,27 +116,14 @@ static int handle_volume_attributes( attr->MaximumComponentNameLength = NFS41_MAX_COMPONENT_LEN; - /* calculate how much space we have for FileSystemName; args.info.buffer - * should guarantee us enough room for NFS41_FILESYSTEM_NAME */ - max_length = sizeof(args->info) - - FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName); + /* let the driver fill in FileSystemName/Len */ - if (FAILED(StringCbCopyNW(attr->FileSystemName, max_length, - NFS41_FILESYSTEM_NAME, NFS41_FILESYSTEM_NAME_LEN))) { - status = ERROR_BUFFER_OVERFLOW; - eprintf("FileSystemName '%S' truncated to '%S'! returning %d\n", - NFS41_FILESYSTEM_NAME, attr->FileSystemName, status); - goto out; - } - - attr->FileSystemNameLength = NFS41_FILESYSTEM_NAME_LEN; - args->len = sizeof(args->info.attribute) + NFS41_FILESYSTEM_NAME_LEN; + args->len = sizeof(args->info.attribute); dprintf(2, "FileFsAttributeInformation: case_preserving %u, " - "case_insensitive %u, max component %u, name '%S', length %u\n", + "case_insensitive %u, max component %u\n", info.case_preserving, info.case_insensitive, - attr->MaximumComponentNameLength, - attr->FileSystemName, attr->FileSystemNameLength); + attr->MaximumComponentNameLength); out: return status; } diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c index 8887117..67ce84e 100644 --- a/sys/nfs41_driver.c +++ b/sys/nfs41_driver.c @@ -278,10 +278,17 @@ typedef struct _NFS41_NETROOT_EXTENSION { #define NFS41GetNetRootExtension(pNetRoot) \ (((pNetRoot) == NULL) ? NULL : (PNFS41_NETROOT_EXTENSION)((pNetRoot)->Context)) +/* FileSystemName as reported by FileFsAttributeInfo query */ +#define FS_NAME L"NFS" +#define FS_NAME_LEN (sizeof(FS_NAME) - sizeof(WCHAR)) +#define FS_ATTR_LEN (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + FS_NAME_LEN) + typedef struct _NFS41_V_NET_ROOT_EXTENSION { NODE_TYPE_CODE NodeTypeCode; NODE_BYTE_SIZE NodeByteSize; HANDLE session; + BYTE FsAttrs[FS_ATTR_LEN]; + LONG FsAttrsLen; } NFS41_V_NET_ROOT_EXTENSION, *PNFS41_V_NET_ROOT_EXTENSION; #define NFS41GetVNetRootExtension(pVNetRoot) \ (((pVNetRoot) == NULL) ? NULL : \ @@ -3039,8 +3046,23 @@ NTSTATUS nfs41_QueryVolumeInformation ( goto out; } - case FileFsSizeInformation: case FileFsAttributeInformation: + /* used cached fs attributes if available */ + if (pVNetRootContext->FsAttrsLen) { + const LONG len = pVNetRootContext->FsAttrsLen; + if (RxContext->Info.LengthRemaining < len) { + RxContext->InformationToReturn = len; + status = STATUS_BUFFER_TOO_SMALL; + goto out; + } + RtlCopyMemory(RxContext->Info.Buffer, + pVNetRootContext->FsAttrs, len); + RxContext->Info.LengthRemaining -= len; + status = STATUS_SUCCESS; + goto out; + } + /* else fall through and send the upcall */ + case FileFsSizeInformation: case FileFsFullSizeInformation: break; @@ -3067,6 +3089,28 @@ NTSTATUS nfs41_QueryVolumeInformation ( RxContext->InformationToReturn = entry->u.Volume.buf_len; status = STATUS_BUFFER_TOO_SMALL; } else if (entry->status == STATUS_SUCCESS) { + if (InfoClass == FileFsAttributeInformation) { + /* fill in the FileSystemName */ + PFILE_FS_ATTRIBUTE_INFORMATION attrs = + (PFILE_FS_ATTRIBUTE_INFORMATION)RxContext->Info.Buffer; + DECLARE_CONST_UNICODE_STRING(FsName, FS_NAME); + entry->u.Volume.buf_len += FsName.Length; + if (entry->u.Volume.buf_len > RxContext->Info.LengthRemaining) { + RxContext->InformationToReturn = entry->u.Volume.buf_len; + status = STATUS_BUFFER_TOO_SMALL; + goto out; + } + RtlCopyMemory(attrs->FileSystemName, FsName.Buffer, + FsName.MaximumLength); /* 'MaximumLength' to include null */ + attrs->FileSystemNameLength = FsName.Length; + + /* save fs attributes with the vnetroot */ + if (entry->u.Volume.buf_len <= FS_ATTR_LEN) { + RtlCopyMemory(&pVNetRootContext->FsAttrs, + RxContext->Info.Buffer, entry->u.Volume.buf_len); + pVNetRootContext->FsAttrsLen = entry->u.Volume.buf_len; + } + } RxContext->Info.LengthRemaining -= entry->u.Volume.buf_len; status = STATUS_SUCCESS; } else {