removing copies from readdir path
This commit is contained in:
parent
7e52f53097
commit
27030b1764
4 changed files with 66 additions and 30 deletions
|
|
@ -85,7 +85,7 @@ static unsigned int WINAPI thread_main(void *args)
|
|||
// buffer used to send downcall content, need to dynamically allocated
|
||||
// as we don't know the length of the buffer (ie. size of directory listing
|
||||
unsigned char *inbuf = NULL;
|
||||
DWORD inbuf_len, outbuf_len;
|
||||
DWORD inbuf_len = UPCALL_BUF_SIZE, outbuf_len;
|
||||
nfs41_upcall upcall;
|
||||
|
||||
pipe = CreateFile(NFS41_USER_DEVICE_NAME_A, GENERIC_READ | GENERIC_WRITE,
|
||||
|
|
@ -130,11 +130,6 @@ write_downcall:
|
|||
"get_last_error=%d\n", upcall.xid, opcode2string(upcall.opcode),
|
||||
upcall.status, upcall.last_error);
|
||||
|
||||
if (upcall.opcode == NFS41_DIR_QUERY)
|
||||
inbuf_len = UPCALL_BUF_SIZE + upcall.args.readdir.query_reply_len;
|
||||
else
|
||||
inbuf_len = UPCALL_BUF_SIZE;
|
||||
|
||||
inbuf = malloc(inbuf_len);
|
||||
if (inbuf == NULL) {
|
||||
upcall.status = GetLastError();
|
||||
|
|
|
|||
|
|
@ -63,13 +63,15 @@ static int parse_readdir(unsigned char *buffer, uint32_t length, nfs41_upcall *u
|
|||
if (status) goto out;
|
||||
status = safe_read(&buffer, &length, &args->single, sizeof(args->single));
|
||||
if (status) goto out;
|
||||
status = safe_read(&buffer, &length, &args->kbuf, sizeof(args->kbuf));
|
||||
if (status) goto out;
|
||||
args->root = upcall->root_ref;
|
||||
args->state = upcall->state_ref;
|
||||
|
||||
dprintf(1, "parsing NFS41_DIR_QUERY: info_class=%d buf_len=%d "
|
||||
"filter='%s'\n\tInitial\\Restart\\Single %d\\%d\\%d\n",
|
||||
"filter='%s'\n\tInitial\\Restart\\Single %d\\%d\\%d buf=%p\n",
|
||||
args->query_class, args->buf_len, args->filter,
|
||||
args->initial, args->restart, args->single);
|
||||
args->initial, args->restart, args->single, args->kbuf);
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
|
@ -479,13 +481,13 @@ static int handle_readdir(nfs41_upcall *upcall)
|
|||
goto out;
|
||||
}
|
||||
|
||||
entry_buf = malloc(max(args->buf_len, 4096));
|
||||
entry_buf = malloc(args->buf_len);
|
||||
if (entry_buf == NULL) {
|
||||
status = GetLastError();
|
||||
goto out_free_cookie;
|
||||
}
|
||||
fetch_entries:
|
||||
entry_buf_len = max(args->buf_len, 4096);
|
||||
entry_buf_len = args->buf_len;
|
||||
|
||||
init_getattr_request(&attr_request);
|
||||
attr_request.arr[0] |= FATTR4_WORD0_RDATTR_ERROR;
|
||||
|
|
@ -550,20 +552,11 @@ fetch_entries:
|
|||
|
||||
if (entry_buf_len) {
|
||||
unsigned char *entry_pos = entry_buf;
|
||||
unsigned char *dst_pos;
|
||||
unsigned char *dst_pos = args->kbuf;
|
||||
uint32_t dst_len = args->buf_len;
|
||||
nfs41_readdir_entry *entry;
|
||||
PULONG offset, last_offset = NULL;
|
||||
|
||||
if (args->buf == NULL) {
|
||||
args->buf = malloc(args->buf_len);
|
||||
if (args->buf == NULL) {
|
||||
status = GetLastError();
|
||||
goto out_free_cookie;
|
||||
}
|
||||
}
|
||||
dst_pos = args->buf;
|
||||
|
||||
for (;;) {
|
||||
entry = (nfs41_readdir_entry*)entry_pos;
|
||||
offset = (PULONG)dst_pos; /* ULONG NextEntryOffset */
|
||||
|
|
@ -625,7 +618,6 @@ out:
|
|||
dprintf(1, "error code %d.\n", status);
|
||||
break;
|
||||
}
|
||||
free(args->buf);
|
||||
args->buf = NULL;
|
||||
} else {
|
||||
dprintf(1, "success!\n");
|
||||
|
|
@ -642,10 +634,6 @@ static int marshall_readdir(unsigned char *buffer, uint32_t *length, nfs41_upcal
|
|||
readdir_upcall_args *args = &upcall->args.readdir;
|
||||
|
||||
status = safe_write(&buffer, length, &args->query_reply_len, sizeof(args->query_reply_len));
|
||||
if (status) goto out;
|
||||
status = safe_write(&buffer, length, args->buf, args->query_reply_len);
|
||||
out:
|
||||
free(args->buf);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ typedef struct __readdir_upcall_args {
|
|||
BOOLEAN initial;
|
||||
BOOLEAN restart;
|
||||
BOOLEAN single;
|
||||
unsigned char *kbuf;
|
||||
} readdir_upcall_args;
|
||||
|
||||
typedef struct __symlink_upcall_args {
|
||||
|
|
|
|||
|
|
@ -186,6 +186,8 @@ typedef struct _updowncall_entry {
|
|||
BOOLEAN restart_scan;
|
||||
BOOLEAN return_single;
|
||||
BOOLEAN initial_query;
|
||||
PMDL mdl;
|
||||
PVOID mdl_buf;
|
||||
} QueryFile;
|
||||
struct {
|
||||
PUNICODE_STRING filename;
|
||||
|
|
@ -831,7 +833,7 @@ NTSTATUS marshal_nfs41_dirquery(nfs41_updowncall_entry *entry,
|
|||
else
|
||||
tmp += *len;
|
||||
|
||||
header_len = *len + 2 * sizeof(ULONG) +
|
||||
header_len = *len + 2 * sizeof(ULONG) + sizeof(HANDLE) +
|
||||
length_as_ansi(entry->u.QueryFile.filter) + 3 * sizeof(BOOLEAN);
|
||||
if (header_len > buf_len) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
|
@ -849,13 +851,34 @@ NTSTATUS marshal_nfs41_dirquery(nfs41_updowncall_entry *entry,
|
|||
RtlCopyMemory(tmp, &entry->u.QueryFile.restart_scan, sizeof(BOOLEAN));
|
||||
tmp += sizeof(BOOLEAN);
|
||||
RtlCopyMemory(tmp, &entry->u.QueryFile.return_single, sizeof(BOOLEAN));
|
||||
|
||||
tmp += sizeof(BOOLEAN);
|
||||
__try {
|
||||
MmProbeAndLockPages(entry->u.QueryFile.mdl, KernelMode, IoModifyAccess);
|
||||
entry->u.QueryFile.mdl_buf =
|
||||
MmMapLockedPagesSpecifyCache(entry->u.QueryFile.mdl,
|
||||
UserMode, MmNonCached, NULL, TRUE, NormalPagePriority);
|
||||
if (entry->u.QueryFile.mdl_buf == NULL) {
|
||||
print_error("MmMapLockedPagesSpecifyCache failed to map pages\n");
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto out;
|
||||
}
|
||||
DbgP("MdlAddress=%p Userspace=%p\n", entry->u.QueryFile.mdl,
|
||||
entry->u.QueryFile.mdl_buf);
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
NTSTATUS code;
|
||||
code = GetExceptionCode();
|
||||
print_error("Call to MmMapLocked failed due to exception 0x%x\n", code);
|
||||
status = STATUS_ACCESS_DENIED;
|
||||
goto out;
|
||||
}
|
||||
RtlCopyMemory(tmp, &entry->u.QueryFile.mdl_buf, sizeof(HANDLE));
|
||||
*len = header_len;
|
||||
|
||||
DbgP("marshal_nfs41_dirquery: filter='%wZ'class=%d "
|
||||
DbgP("marshal_nfs41_dirquery: filter='%wZ'class=%d len=%d "
|
||||
"1st\\restart\\single=%d\\%d\\%d\n", entry->u.QueryFile.filter,
|
||||
entry->u.QueryFile.InfoClass, entry->u.QueryFile.initial_query,
|
||||
entry->u.QueryFile.restart_scan, entry->u.QueryFile.return_single);
|
||||
entry->u.QueryFile.InfoClass, entry->u.QueryFile.buf_len,
|
||||
entry->u.QueryFile.initial_query, entry->u.QueryFile.restart_scan,
|
||||
entry->u.QueryFile.return_single);
|
||||
out:
|
||||
DbgEx();
|
||||
return status;
|
||||
|
|
@ -1568,6 +1591,26 @@ nfs41_downcall (
|
|||
cur->open_state, cur->u.Open.mode, cur->u.Open.changeattr);
|
||||
break;
|
||||
case NFS41_DIR_QUERY:
|
||||
RtlCopyMemory(&tmp->u.QueryFile.buf_len, buf, sizeof(ULONG));
|
||||
DbgP("readdir reply size %d\n", tmp->u.QueryFile.buf_len);
|
||||
buf += sizeof(ULONG);
|
||||
__try {
|
||||
MmUnmapLockedPages(cur->u.QueryFile.mdl_buf, cur->u.QueryFile.mdl);
|
||||
MmUnlockPages(cur->u.QueryFile.mdl);
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
NTSTATUS code;
|
||||
code = GetExceptionCode();
|
||||
print_error("Call to MmUnmapLockedPages failed due to"
|
||||
" exception 0x%0x\n", code);
|
||||
status = STATUS_ACCESS_DENIED;
|
||||
}
|
||||
if (tmp->u.QueryFile.buf_len > cur->u.QueryFile.buf_len) {
|
||||
cur->status = STATUS_BUFFER_TOO_SMALL;
|
||||
cur->u.QueryFile.buf_len = tmp->u.QueryFile.buf_len;
|
||||
break;
|
||||
}
|
||||
cur->u.QueryFile.buf_len = tmp->u.QueryFile.buf_len;
|
||||
break;
|
||||
case NFS41_FILE_QUERY:
|
||||
RtlCopyMemory(&tmp->u.QueryFile.buf_len, buf, sizeof(ULONG));
|
||||
buf += sizeof(ULONG);
|
||||
|
|
@ -3428,6 +3471,14 @@ NTSTATUS nfs41_QueryDirectory (
|
|||
entry->u.QueryFile.InfoClass = InfoClass;
|
||||
entry->u.QueryFile.buf_len = RxContext->Info.LengthRemaining;
|
||||
entry->u.QueryFile.buf = RxContext->Info.Buffer;
|
||||
entry->u.QueryFile.mdl = IoAllocateMdl(RxContext->Info.Buffer,
|
||||
RxContext->Info.LengthRemaining, FALSE, FALSE, NULL);
|
||||
if (entry->u.QueryFile.mdl == NULL) {
|
||||
status = STATUS_INTERNAL_ERROR;
|
||||
RxFreePool(entry);
|
||||
goto out;
|
||||
}
|
||||
|
||||
entry->u.QueryFile.filter = Filter;
|
||||
entry->u.QueryFile.initial_query = RxContext->QueryDirectory.InitialQuery;
|
||||
entry->u.QueryFile.restart_scan = RxContext->QueryDirectory.RestartScan;
|
||||
|
|
@ -3454,6 +3505,7 @@ NTSTATUS nfs41_QueryDirectory (
|
|||
/* map windows ERRORs to NTSTATUS */
|
||||
status = map_querydir_errors(entry->status);
|
||||
}
|
||||
IoFreeMdl(entry->u.QueryFile.mdl);
|
||||
RxFreePool(entry);
|
||||
out:
|
||||
#ifdef ENABLE_TIMINGS
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue