1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=4:tabstop=4:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 # define DEBUG_SUBSYSTEM S_LNET
42 #include <libcfs/libcfs.h>
43 #include <libcfs/user-bitops.h>
44 #include <lustre_lib.h>
47 * Native API definitions
57 NtReadFile(HANDLE FileHandle,
58 HANDLE Event OPTIONAL,
59 PIO_APC_ROUTINE ApcRoutine OPTIONAL,
60 PVOID ApcContext OPTIONAL,
61 PIO_STATUS_BLOCK IoStatusBlock,
64 PLARGE_INTEGER ByteOffset OPTIONAL,
70 NtWriteFile(HANDLE FileHandle,
71 HANDLE Event OPTIONAL,
72 PIO_APC_ROUTINE ApcRoutine OPTIONAL,
73 PVOID ApcContext OPTIONAL,
74 PIO_STATUS_BLOCK IoStatusBlock,
77 PLARGE_INTEGER ByteOffset OPTIONAL,
83 NtClose(HANDLE Handle);
88 NtCreateFile(PHANDLE FileHandle,
89 ACCESS_MASK DesiredAccess,
90 POBJECT_ATTRIBUTES ObjectAttributes,
91 PIO_STATUS_BLOCK IoStatusBlock,
92 PLARGE_INTEGER AllocationSize OPTIONAL,
95 ULONG CreateDisposition,
97 PVOID EaBuffer OPTIONAL,
104 NtDeviceIoControlFile(
105 IN HANDLE FileHandle,
107 IN PIO_APC_ROUTINE ApcRoutine,
109 OUT PIO_STATUS_BLOCK IoStatusBlock,
110 IN ULONG IoControlCode,
111 IN PVOID InputBuffer,
112 IN ULONG InputBufferLength,
113 OUT PVOID OutputBuffer,
114 OUT ULONG OutputBufferLength
121 IN HANDLE FileHandle,
122 IN HANDLE Event OPTIONAL,
123 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
124 IN PVOID ApcContext OPTIONAL,
125 OUT PIO_STATUS_BLOCK IoStatusBlock,
126 IN ULONG FsControlCode,
127 IN PVOID InputBuffer OPTIONAL,
128 IN ULONG InputBufferLength,
129 OUT PVOID OutputBuffer OPTIONAL,
130 IN ULONG OutputBufferLength
137 NtQueryInformationFile(
138 IN HANDLE FileHandle,
139 OUT PIO_STATUS_BLOCK IoStatusBlock,
140 OUT PVOID FileInformation,
142 IN FILE_INFORMATION_CLASS FileInformationClass
146 // Random routines ...
164 OUT PLARGE_INTEGER CurrentTime
171 RtlTimeToSecondsSince1970(
172 IN PLARGE_INTEGER Time,
173 OUT PULONG ElapsedSeconds
180 RtlSecondsSince1970ToTime(
181 IN ULONG ElapsedSeconds,
182 OUT PLARGE_INTEGER Time
189 IN BOOLEAN Alertable,
190 IN PLARGE_INTEGER Interval
194 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
197 LARGE_INTEGER Interval;
198 Interval.QuadPart = rqtp->tv_sec * 10000000 + rqtp->tv_nsec / 100;
199 status = ZwDelayExecution(TRUE, &Interval);
204 if (status == STATUS_ALERTED || status == STATUS_USER_APC) {
211 void cfs_gettimeofday(struct timeval *tv)
215 NtQuerySystemTime(&Time);
217 tv->tv_sec = (long_ptr_t) (Time.QuadPart / 10000000);
218 tv->tv_usec = (suseconds_t) (Time.QuadPart % 10000000) / 10;
221 int gettimeofday(struct timeval *tv, void * tz)
223 cfs_gettimeofday(tv);
228 * proc process routines of user space
231 struct idr_context *cfs_proc_idp = NULL;
233 int cfs_proc_open (char * filename, int oflag)
236 IO_STATUS_BLOCK iosb;
239 HANDLE Handle = INVALID_HANDLE_VALUE;
240 OBJECT_ATTRIBUTES ObjectAttributes;
241 ACCESS_MASK DesiredAccess;
242 ULONG CreateDisposition;
245 UNICODE_STRING UnicodeName;
248 PFILE_FULL_EA_INFORMATION Ea = NULL;
250 PUCHAR EaBuffer = NULL;
252 /* Check the filename: should start with "/proc" or "/dev" */
253 NameLength = (USHORT)strlen(filename);
254 if (NameLength > 0x05) {
255 if (_strnicmp(filename, "/proc/", 6) == 0) {
256 if (NameLength <= 6) {
260 } else if (_strnicmp(filename, "/dev/", 5) == 0) {
270 /* Analyze the flags settings */
272 if (cfs_is_flag_set(oflag, O_WRONLY)) {
273 DesiredAccess = (GENERIC_WRITE | SYNCHRONIZE);
275 } else if (cfs_is_flag_set(oflag, O_RDWR)) {
276 DesiredAccess = (GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE);
277 ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
279 DesiredAccess = (GENERIC_READ | SYNCHRONIZE);
280 ShareAccess = FILE_SHARE_READ;
283 if (cfs_is_flag_set(oflag, O_CREAT)) {
284 if (cfs_is_flag_set(oflag, O_EXCL)) {
285 CreateDisposition = FILE_CREATE;
289 CreateDisposition = FILE_OPEN_IF;
292 CreateDisposition = FILE_OPEN;
295 if (cfs_is_flag_set(oflag, O_TRUNC)) {
296 if (cfs_is_flag_set(oflag, O_EXCL)) {
297 CreateDisposition = FILE_OVERWRITE;
299 CreateDisposition = FILE_OVERWRITE_IF;
305 if (cfs_is_flag_set(oflag, O_DIRECTORY)) {
306 cfs_set_flag(CreateOptions, FILE_DIRECTORY_FILE);
309 if (cfs_is_flag_set(oflag, O_SYNC)) {
310 cfs_set_flag(CreateOptions, FILE_WRITE_THROUGH);
313 if (cfs_is_flag_set(oflag, O_DIRECT)) {
314 cfs_set_flag(CreateOptions, FILE_NO_INTERMEDIATE_BUFFERING);
317 /* Initialize the unicode path name for the specified file */
318 RtlInitUnicodeString(&UnicodeName, LUSTRE_PROC_SYMLNK);
320 /* Setup the object attributes structure for the file. */
321 InitializeObjectAttributes(
324 OBJ_CASE_INSENSITIVE,
328 /* building EA for the proc entry ... */
329 EaBuffer = malloc(NameLength + sizeof(FILE_FULL_EA_INFORMATION));
334 memset(EaBuffer, 0, NameLength + sizeof(FILE_FULL_EA_INFORMATION));
335 Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
336 Ea->NextEntryOffset = 0;
338 Ea->EaNameLength = (UCHAR)NameLength;
339 Ea->EaValueLength = 0;
345 EaLength = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
346 Ea->EaNameLength + 1;
348 /* Now to open or create the file now */
349 status = NtCreateFile(
355 FILE_ATTRIBUTE_NORMAL,
362 /* Check the returned status of Iosb ... */
364 if (!NT_SUCCESS(status)) {
365 rc = cfs_error_code(status);
372 rc = cfs_idr_get_new(cfs_proc_idp, Handle);
385 int cfs_proc_close(int fd)
387 HANDLE handle = cfs_idr_find(cfs_proc_idp, fd);
393 cfs_idr_remove(cfs_proc_idp, fd);
398 int cfs_proc_read_internal(
399 int fd, void *buffer,
406 IO_STATUS_BLOCK iosb;
407 LARGE_INTEGER offset;
409 HANDLE handle = cfs_idr_find(cfs_proc_idp, fd);
410 offset.HighPart = offhigh;
411 offset.LowPart = offlow;
425 /* check the return status */
426 if (!NT_SUCCESS(status)) {
427 printf("NtReadFile request failed with status: 0x%0x\n", status);
433 if (NT_SUCCESS(status)) {
434 return (int)(iosb.Information);
437 return cfs_error_code(status);
441 int fd, void *buffer,
445 return cfs_proc_read_internal(fd, buffer, count, 0, 0);
448 int cfs_proc_write_internal(
449 int fd, void *buffer,
456 IO_STATUS_BLOCK iosb;
457 LARGE_INTEGER offset;
459 HANDLE handle = cfs_idr_find(cfs_proc_idp, fd);
460 offset.HighPart = offhigh;
461 offset.LowPart = offlow;
463 /* write buffer to the opened file */
464 status = NtWriteFile(
475 /* check the return status */
476 if (!NT_SUCCESS(status)) {
477 printf("NtWriteFile request failed 0x%0x\n", status);
483 if (NT_SUCCESS(status)) {
484 return (int)(iosb.Information);
487 return cfs_error_code(status);
491 int fd, void *buffer,
495 return cfs_proc_write_internal(fd, buffer, count, 0, 0);
498 int cfs_proc_ioctl(int fd, int cmd, void *buffer)
500 PUCHAR procdat = NULL;
501 CFS_PROC_IOCTL procctl;
506 NTSTATUS status = STATUS_UNSUCCESSFUL;
507 IO_STATUS_BLOCK iosb;
509 struct libcfs_ioctl_data * portal = buffer;
510 struct obd_ioctl_data * obd = buffer;
511 struct obd_ioctl_data * data;
513 HANDLE handle = cfs_idr_find(cfs_proc_idp, fd);
515 CLASSERT(sizeof(struct obd_ioctl_data) == 528);
517 CLASSERT(sizeof(struct obd_ioctl_data) == 576);
519 memset(&procctl, 0, sizeof(CFS_PROC_IOCTL));
522 if(_IOC_TYPE(cmd) == IOC_LIBCFS_TYPE) {
523 length = portal->ioc_len;
524 } else if (_IOC_TYPE(cmd) == 'f') {
525 length = obd->ioc_len;
526 extra = cfs_size_round(obd->ioc_plen1) + cfs_size_round(obd->ioc_plen2);
527 } else if(_IOC_TYPE(cmd) == 'u') {
530 } else if(_IOC_TYPE(cmd) == 'i') {
531 length = obd->ioc_len;
534 printf("cfs_proc_ioctl: un-supported ioctl type ...\n");
535 cfs_enter_debugger();
536 status = STATUS_INVALID_PARAMETER;
540 procctl.len = length + extra;
541 procdat = malloc(length + extra + sizeof(CFS_PROC_IOCTL));
543 if (NULL == procdat) {
544 printf("user:winnt-proc:cfs_proc_ioctl: no enough memory ...\n");
545 status = STATUS_INSUFFICIENT_RESOURCES;
546 cfs_enter_debugger();
549 memset(procdat, 0, length + extra + sizeof(CFS_PROC_IOCTL));
550 memcpy(procdat, &procctl, sizeof(CFS_PROC_IOCTL));
551 memcpy(&procdat[sizeof(CFS_PROC_IOCTL)], buffer, length);
552 length += sizeof(CFS_PROC_IOCTL);
554 if (_IOC_TYPE(cmd) == 'f') {
556 data = (struct obd_ioctl_data *) (procdat + sizeof(CFS_PROC_IOCTL));
557 if ( cmd != (ULONG)OBD_IOC_BRW_WRITE &&
558 cmd != (ULONG)OBD_IOC_BRW_READ ) {
560 if (obd->ioc_pbuf1 && data->ioc_plen1) {
561 data->ioc_pbuf1 = &procdat[length];
562 memcpy(data->ioc_pbuf1, obd->ioc_pbuf1, obd->ioc_plen1);
563 length += cfs_size_round(obd->ioc_plen1);
566 data->ioc_pbuf1 = NULL;
569 if (obd->ioc_pbuf2 && obd->ioc_plen2) {
570 data->ioc_pbuf2 = &procdat[length];
571 memcpy(data->ioc_pbuf2, obd->ioc_pbuf2, obd->ioc_plen2);
572 length += cfs_size_round(obd->ioc_plen2);
575 data->ioc_pbuf2 = NULL;
581 ASSERT(length == extra + sizeof(CFS_PROC_IOCTL) + data->ioc_len);
582 if (obd_ioctl_is_invalid(obd)) {
583 cfs_enter_debugger();
587 status = NtDeviceIoControlFile(
595 if (_IOC_TYPE(cmd) == 'f') {
597 length = sizeof(CFS_PROC_IOCTL);
598 ASSERT(data == (struct obd_ioctl_data *) (procdat + sizeof(CFS_PROC_IOCTL)));
599 if ( cmd != (ULONG)OBD_IOC_BRW_WRITE &&
600 cmd != (ULONG)OBD_IOC_BRW_READ ) {
602 if (obd->ioc_pbuf1) {
603 ASSERT(obd->ioc_plen1 == data->ioc_plen1);
604 data->ioc_pbuf1 = &procdat[length];
605 memcpy(obd->ioc_pbuf1, data->ioc_pbuf1, obd->ioc_plen1);
606 length += cfs_size_round(obd->ioc_plen1);
608 if (obd->ioc_pbuf2) {
609 ASSERT(obd->ioc_plen2 == data->ioc_plen2);
610 data->ioc_pbuf2 = &procdat[length];
611 memcpy(obd->ioc_pbuf2, data->ioc_pbuf2, obd->ioc_plen2);
612 length += cfs_size_round(obd->ioc_plen2);
615 data->ioc_inlbuf1 = obd->ioc_inlbuf1;
616 data->ioc_inlbuf2 = obd->ioc_inlbuf2;
617 data->ioc_inlbuf3 = obd->ioc_inlbuf3;
618 data->ioc_inlbuf4 = obd->ioc_inlbuf4;
619 data->ioc_pbuf1 = obd->ioc_pbuf1;
620 data->ioc_pbuf2 = obd->ioc_pbuf2;
621 memcpy(obd, data, obd->ioc_len);
625 memcpy(buffer, &procdat[sizeof(CFS_PROC_IOCTL)], procctl.len);
630 if (STATUS_SUCCESS == status) {
631 rc = ((CFS_PROC_IOCTL *)procdat)->rc;
633 rc = cfs_error_code(status);
644 int cfs_proc_mknod(const char *path, mode_t mode, dev_t dev)
649 FILE *cfs_proc_fopen(char *path, char * mode)
651 int fp = cfs_proc_open(path, O_RDWR);
653 return (FILE *)(LONG_PTR)fp;
659 char *cfs_proc_fgets(char * buf, int len, FILE *fp)
667 rc = cfs_proc_read_internal((int)(LONG_PTR)fp,
676 int cfs_proc_fclose(FILE *fp)
682 return cfs_proc_close((int)(LONG_PTR)fp);
685 void cfs_libc_init();
688 libcfs_arch_init(void)
691 cfs_proc_idp = cfs_idr_init();
701 libcfs_arch_cleanup(void)
704 cfs_idr_exit(cfs_proc_idp);
709 #endif /* __KERNEL__ */