4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
31 * This file is part of Lustre, http://www.lustre.org/
32 * Lustre is a trademark of Sun Microsystems, Inc.
35 # define DEBUG_SUBSYSTEM S_LNET
40 #include <libcfs/libcfs.h>
41 #include <libcfs/user-bitops.h>
42 #include <lustre_lib.h>
45 * Native API definitions
55 NtReadFile(HANDLE FileHandle,
56 HANDLE Event OPTIONAL,
57 PIO_APC_ROUTINE ApcRoutine OPTIONAL,
58 PVOID ApcContext OPTIONAL,
59 PIO_STATUS_BLOCK IoStatusBlock,
62 PLARGE_INTEGER ByteOffset OPTIONAL,
68 NtWriteFile(HANDLE FileHandle,
69 HANDLE Event OPTIONAL,
70 PIO_APC_ROUTINE ApcRoutine OPTIONAL,
71 PVOID ApcContext OPTIONAL,
72 PIO_STATUS_BLOCK IoStatusBlock,
75 PLARGE_INTEGER ByteOffset OPTIONAL,
81 NtClose(HANDLE Handle);
86 NtCreateFile(PHANDLE FileHandle,
87 ACCESS_MASK DesiredAccess,
88 POBJECT_ATTRIBUTES ObjectAttributes,
89 PIO_STATUS_BLOCK IoStatusBlock,
90 PLARGE_INTEGER AllocationSize OPTIONAL,
93 ULONG CreateDisposition,
95 PVOID EaBuffer OPTIONAL,
102 NtDeviceIoControlFile(
103 IN HANDLE FileHandle,
105 IN PIO_APC_ROUTINE ApcRoutine,
107 OUT PIO_STATUS_BLOCK IoStatusBlock,
108 IN ULONG IoControlCode,
109 IN PVOID InputBuffer,
110 IN ULONG InputBufferLength,
111 OUT PVOID OutputBuffer,
112 OUT ULONG OutputBufferLength
119 IN HANDLE FileHandle,
120 IN HANDLE Event OPTIONAL,
121 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
122 IN PVOID ApcContext OPTIONAL,
123 OUT PIO_STATUS_BLOCK IoStatusBlock,
124 IN ULONG FsControlCode,
125 IN PVOID InputBuffer OPTIONAL,
126 IN ULONG InputBufferLength,
127 OUT PVOID OutputBuffer OPTIONAL,
128 IN ULONG OutputBufferLength
135 NtQueryInformationFile(
136 IN HANDLE FileHandle,
137 OUT PIO_STATUS_BLOCK IoStatusBlock,
138 OUT PVOID FileInformation,
140 IN FILE_INFORMATION_CLASS FileInformationClass
144 // Random routines ...
162 OUT PLARGE_INTEGER CurrentTime
169 RtlTimeToSecondsSince1970(
170 IN PLARGE_INTEGER Time,
171 OUT PULONG ElapsedSeconds
178 RtlSecondsSince1970ToTime(
179 IN ULONG ElapsedSeconds,
180 OUT PLARGE_INTEGER Time
187 IN BOOLEAN Alertable,
188 IN PLARGE_INTEGER Interval
192 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
195 LARGE_INTEGER Interval;
196 Interval.QuadPart = rqtp->tv_sec * 10000000 + rqtp->tv_nsec / 100;
197 status = ZwDelayExecution(TRUE, &Interval);
202 if (status == STATUS_ALERTED || status == STATUS_USER_APC) {
209 void do_gettimeofday(struct timeval *tv)
213 NtQuerySystemTime(&Time);
215 tv->tv_sec = (long_ptr_t) (Time.QuadPart / 10000000);
216 tv->tv_usec = (suseconds_t) (Time.QuadPart % 10000000) / 10;
219 int gettimeofday(struct timeval *tv, void * tz)
226 * proc process routines of user space
229 struct idr_context *cfs_proc_idp = NULL;
231 int cfs_proc_open (char * filename, int oflag)
234 IO_STATUS_BLOCK iosb;
237 HANDLE Handle = INVALID_HANDLE_VALUE;
238 OBJECT_ATTRIBUTES ObjectAttributes;
239 ACCESS_MASK DesiredAccess;
240 ULONG CreateDisposition;
243 UNICODE_STRING UnicodeName;
246 PFILE_FULL_EA_INFORMATION Ea = NULL;
248 PUCHAR EaBuffer = NULL;
250 /* Check the filename: should start with "/proc" or "/dev" */
251 NameLength = (USHORT)strlen(filename);
252 if (NameLength > 0x05) {
253 if (_strnicmp(filename, "/proc/", 6) == 0) {
254 if (NameLength <= 6) {
258 } else if (_strnicmp(filename, "/dev/", 5) == 0) {
268 /* Analyze the flags settings */
270 if (cfs_is_flag_set(oflag, O_WRONLY)) {
271 DesiredAccess = (GENERIC_WRITE | SYNCHRONIZE);
273 } else if (cfs_is_flag_set(oflag, O_RDWR)) {
274 DesiredAccess = (GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE);
275 ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
277 DesiredAccess = (GENERIC_READ | SYNCHRONIZE);
278 ShareAccess = FILE_SHARE_READ;
281 if (cfs_is_flag_set(oflag, O_CREAT)) {
282 if (cfs_is_flag_set(oflag, O_EXCL)) {
283 CreateDisposition = FILE_CREATE;
287 CreateDisposition = FILE_OPEN_IF;
290 CreateDisposition = FILE_OPEN;
293 if (cfs_is_flag_set(oflag, O_TRUNC)) {
294 if (cfs_is_flag_set(oflag, O_EXCL)) {
295 CreateDisposition = FILE_OVERWRITE;
297 CreateDisposition = FILE_OVERWRITE_IF;
303 if (cfs_is_flag_set(oflag, O_DIRECTORY)) {
304 cfs_set_flag(CreateOptions, FILE_DIRECTORY_FILE);
307 if (cfs_is_flag_set(oflag, O_SYNC)) {
308 cfs_set_flag(CreateOptions, FILE_WRITE_THROUGH);
311 if (cfs_is_flag_set(oflag, O_DIRECT)) {
312 cfs_set_flag(CreateOptions, FILE_NO_INTERMEDIATE_BUFFERING);
315 /* Initialize the unicode path name for the specified file */
316 RtlInitUnicodeString(&UnicodeName, LUSTRE_PROC_SYMLNK);
318 /* Setup the object attributes structure for the file. */
319 InitializeObjectAttributes(
322 OBJ_CASE_INSENSITIVE,
326 /* building EA for the proc entry ... */
327 EaBuffer = malloc(NameLength + sizeof(FILE_FULL_EA_INFORMATION));
332 memset(EaBuffer, 0, NameLength + sizeof(FILE_FULL_EA_INFORMATION));
333 Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
334 Ea->NextEntryOffset = 0;
336 Ea->EaNameLength = (UCHAR)NameLength;
337 Ea->EaValueLength = 0;
343 EaLength = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
344 Ea->EaNameLength + 1;
346 /* Now to open or create the file now */
347 status = NtCreateFile(
353 FILE_ATTRIBUTE_NORMAL,
360 /* Check the returned status of Iosb ... */
362 if (!NT_SUCCESS(status)) {
363 rc = cfs_error_code(status);
370 rc = cfs_idr_get_new(cfs_proc_idp, Handle);
383 int cfs_proc_close(int fd)
385 HANDLE handle = cfs_idr_find(cfs_proc_idp, fd);
391 cfs_idr_remove(cfs_proc_idp, fd);
396 int cfs_proc_read_internal(
397 int fd, void *buffer,
404 IO_STATUS_BLOCK iosb;
405 LARGE_INTEGER offset;
407 HANDLE handle = cfs_idr_find(cfs_proc_idp, fd);
408 offset.HighPart = offhigh;
409 offset.LowPart = offlow;
423 /* check the return status */
424 if (!NT_SUCCESS(status)) {
425 printf("NtReadFile request failed with status: 0x%0x\n", status);
431 if (NT_SUCCESS(status)) {
432 return (int)(iosb.Information);
435 return cfs_error_code(status);
439 int fd, void *buffer,
443 return cfs_proc_read_internal(fd, buffer, count, 0, 0);
446 int cfs_proc_write_internal(
447 int fd, void *buffer,
454 IO_STATUS_BLOCK iosb;
455 LARGE_INTEGER offset;
457 HANDLE handle = cfs_idr_find(cfs_proc_idp, fd);
458 offset.HighPart = offhigh;
459 offset.LowPart = offlow;
461 /* write buffer to the opened file */
462 status = NtWriteFile(
473 /* check the return status */
474 if (!NT_SUCCESS(status)) {
475 printf("NtWriteFile request failed 0x%0x\n", status);
481 if (NT_SUCCESS(status)) {
482 return (int)(iosb.Information);
485 return cfs_error_code(status);
489 int fd, void *buffer,
493 return cfs_proc_write_internal(fd, buffer, count, 0, 0);
496 int cfs_proc_ioctl(int fd, int cmd, void *buffer)
498 PUCHAR procdat = NULL;
499 CFS_PROC_IOCTL procctl;
504 NTSTATUS status = STATUS_UNSUCCESSFUL;
505 IO_STATUS_BLOCK iosb;
507 struct libcfs_ioctl_data * portal = buffer;
508 struct obd_ioctl_data * obd = buffer;
509 struct obd_ioctl_data * data;
511 HANDLE handle = cfs_idr_find(cfs_proc_idp, fd);
513 CLASSERT(sizeof(struct obd_ioctl_data) == 528);
515 CLASSERT(sizeof(struct obd_ioctl_data) == 576);
517 memset(&procctl, 0, sizeof(CFS_PROC_IOCTL));
520 if(_IOC_TYPE(cmd) == IOC_LIBCFS_TYPE) {
521 length = portal->ioc_len;
522 } else if (_IOC_TYPE(cmd) == 'f') {
523 length = obd->ioc_len;
524 extra = cfs_size_round(obd->ioc_plen1) + cfs_size_round(obd->ioc_plen2);
525 } else if(_IOC_TYPE(cmd) == 'u') {
528 } else if(_IOC_TYPE(cmd) == 'i') {
529 length = obd->ioc_len;
532 printf("cfs_proc_ioctl: un-supported ioctl type ...\n");
533 cfs_enter_debugger();
534 status = STATUS_INVALID_PARAMETER;
538 procctl.len = length + extra;
539 procdat = malloc(length + extra + sizeof(CFS_PROC_IOCTL));
541 if (NULL == procdat) {
542 printf("user:winnt-proc:cfs_proc_ioctl: no enough memory ...\n");
543 status = STATUS_INSUFFICIENT_RESOURCES;
544 cfs_enter_debugger();
547 memset(procdat, 0, length + extra + sizeof(CFS_PROC_IOCTL));
548 memcpy(procdat, &procctl, sizeof(CFS_PROC_IOCTL));
549 memcpy(&procdat[sizeof(CFS_PROC_IOCTL)], buffer, length);
550 length += sizeof(CFS_PROC_IOCTL);
552 if (_IOC_TYPE(cmd) == 'f') {
554 data = (struct obd_ioctl_data *) (procdat + sizeof(CFS_PROC_IOCTL));
555 if ( cmd != (ULONG)OBD_IOC_BRW_WRITE &&
556 cmd != (ULONG)OBD_IOC_BRW_READ ) {
558 if (obd->ioc_pbuf1 && data->ioc_plen1) {
559 data->ioc_pbuf1 = &procdat[length];
560 memcpy(data->ioc_pbuf1, obd->ioc_pbuf1, obd->ioc_plen1);
561 length += cfs_size_round(obd->ioc_plen1);
564 data->ioc_pbuf1 = NULL;
567 if (obd->ioc_pbuf2 && obd->ioc_plen2) {
568 data->ioc_pbuf2 = &procdat[length];
569 memcpy(data->ioc_pbuf2, obd->ioc_pbuf2, obd->ioc_plen2);
570 length += cfs_size_round(obd->ioc_plen2);
573 data->ioc_pbuf2 = NULL;
579 ASSERT(length == extra + sizeof(CFS_PROC_IOCTL) + data->ioc_len);
580 if (obd_ioctl_is_invalid(obd)) {
581 cfs_enter_debugger();
585 status = NtDeviceIoControlFile(
593 if (_IOC_TYPE(cmd) == 'f') {
595 length = sizeof(CFS_PROC_IOCTL);
596 ASSERT(data == (struct obd_ioctl_data *) (procdat + sizeof(CFS_PROC_IOCTL)));
597 if ( cmd != (ULONG)OBD_IOC_BRW_WRITE &&
598 cmd != (ULONG)OBD_IOC_BRW_READ ) {
600 if (obd->ioc_pbuf1) {
601 ASSERT(obd->ioc_plen1 == data->ioc_plen1);
602 data->ioc_pbuf1 = &procdat[length];
603 memcpy(obd->ioc_pbuf1, data->ioc_pbuf1, obd->ioc_plen1);
604 length += cfs_size_round(obd->ioc_plen1);
606 if (obd->ioc_pbuf2) {
607 ASSERT(obd->ioc_plen2 == data->ioc_plen2);
608 data->ioc_pbuf2 = &procdat[length];
609 memcpy(obd->ioc_pbuf2, data->ioc_pbuf2, obd->ioc_plen2);
610 length += cfs_size_round(obd->ioc_plen2);
613 data->ioc_inlbuf1 = obd->ioc_inlbuf1;
614 data->ioc_inlbuf2 = obd->ioc_inlbuf2;
615 data->ioc_inlbuf3 = obd->ioc_inlbuf3;
616 data->ioc_inlbuf4 = obd->ioc_inlbuf4;
617 data->ioc_pbuf1 = obd->ioc_pbuf1;
618 data->ioc_pbuf2 = obd->ioc_pbuf2;
619 memcpy(obd, data, obd->ioc_len);
623 memcpy(buffer, &procdat[sizeof(CFS_PROC_IOCTL)], procctl.len);
628 if (STATUS_SUCCESS == status) {
629 rc = ((CFS_PROC_IOCTL *)procdat)->rc;
631 rc = cfs_error_code(status);
642 int cfs_proc_mknod(const char *path, mode_t mode, dev_t dev)
647 FILE *cfs_proc_fopen(char *path, char * mode)
649 int fp = cfs_proc_open(path, O_RDWR);
651 return (FILE *)(LONG_PTR)fp;
657 char *cfs_proc_fgets(char * buf, int len, FILE *fp)
665 rc = cfs_proc_read_internal((int)(LONG_PTR)fp,
674 int cfs_proc_fclose(FILE *fp)
680 return cfs_proc_close((int)(LONG_PTR)fp);
683 void cfs_libc_init();
686 libcfs_arch_init(void)
689 cfs_proc_idp = cfs_idr_init();
699 libcfs_arch_cleanup(void)
702 cfs_idr_exit(cfs_proc_idp);
707 #endif /* __KERNEL__ */