X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=libcfs%2Flibcfs%2Futil%2Fl_ioctl.c;h=f1676aa8f7a4d74279fa972c68fbf147a8c884fe;hp=9570253869b5f462205c671339bbba5bda4c55d1;hb=605a139a193e4ef212560673b4bb93eec763d088;hpb=e3a7c58aebafce40323db54bf6056029e5af4a70 diff --git a/libcfs/libcfs/util/l_ioctl.c b/libcfs/libcfs/util/l_ioctl.c index 9570253..f1676aa 100644 --- a/libcfs/libcfs/util/l_ioctl.c +++ b/libcfs/libcfs/util/l_ioctl.c @@ -1,7 +1,9 @@ /* * Copyright (C) 2001, 2002 Cluster File Systems, Inc. * - * This file is part of Portals, http://www.sf.net/projects/lustre/ + * Copyright (c) 2014, 2017, Intel Corporation. + * + * This file is part of Lustre, https://wiki.whamcloud.com/ * * Portals is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -20,50 +22,34 @@ #define __USE_FILE_OFFSET64 -#include -#include -#include - -static ioc_handler_t do_ioctl; /* forward ref */ -static ioc_handler_t *current_ioc_handler = &do_ioctl; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include struct ioc_dev { - const char * dev_name; - int dev_fd; - int dev_major; - int dev_minor; + const char *dev_name; + int dev_fd; }; static struct ioc_dev ioc_dev_list[10]; -struct dump_hdr { - int magic; - int dev_id; - unsigned int opc; -}; - -char *dump_filename; - -void -set_ioc_handler (ioc_handler_t *handler) -{ - if (handler == NULL) - current_ioc_handler = do_ioctl; - else - current_ioc_handler = handler; -} - -/* Catamount has no , so just define it here */ -#ifndef MKDEV -# define MKDEV(a,b) (((a) << 8) | (b)) -#endif - static int -open_ioc_dev(int dev_id) +open_ioc_dev(int dev_id) { const char * dev_name; - if (dev_id < 0 || + if (dev_id < 0 || dev_id >= sizeof(ioc_dev_list) / sizeof(ioc_dev_list[0])) return -EINVAL; @@ -74,19 +60,7 @@ open_ioc_dev(int dev_id) } if (ioc_dev_list[dev_id].dev_fd < 0) { - int fd = cfs_proc_open((char *)dev_name, O_RDWR); - - /* Make the /dev/ node if we need to */ - if (fd < 0 && errno == ENOENT) { - if (cfs_proc_mknod(dev_name, - S_IFCHR|S_IWUSR|S_IRUSR, - MKDEV(ioc_dev_list[dev_id].dev_major, - ioc_dev_list[dev_id].dev_minor)) == 0) - fd = cfs_proc_open((char *)dev_name, O_RDWR); - else - fprintf(stderr, "mknod %s failed: %s\n", - dev_name, strerror(errno)); - } + int fd = open(dev_name, O_RDWR); if (fd < 0) { fprintf(stderr, "opening %s failed: %s\n" @@ -101,77 +75,24 @@ open_ioc_dev(int dev_id) } -static int -do_ioctl(int dev_id, unsigned int opc, void *buf) +int l_ioctl(int dev_id, unsigned int opc, void *buf) { int fd, rc; - + fd = open_ioc_dev(dev_id); - if (fd < 0) + if (fd < 0) return fd; - rc = cfs_proc_ioctl(fd, opc, buf); - return rc; - -} + rc = ioctl(fd, opc, buf); -static FILE * -get_dump_file() -{ - FILE *fp = NULL; - - if (!dump_filename) { - fprintf(stderr, "no dump filename\n"); - } else - fp = fopen(dump_filename, "a"); - return fp; -} - -/* - * The dump file should start with a description of which devices are - * used, but for now it will assumed whatever app reads the file will - * know what to do. */ -int -dump(int dev_id, unsigned int opc, void *buf) -{ - FILE *fp; - struct dump_hdr dump_hdr; - struct libcfs_ioctl_hdr * ioc_hdr = (struct libcfs_ioctl_hdr *) buf; - int rc; - - printf("dumping opc %x to %s\n", opc, dump_filename); - - - dump_hdr.magic = 0xdeadbeef; - dump_hdr.dev_id = dev_id; - dump_hdr.opc = opc; - - fp = get_dump_file(); - if (fp == NULL) { - fprintf(stderr, "%s: %s\n", dump_filename, - strerror(errno)); - return -EINVAL; - } - - rc = fwrite(&dump_hdr, sizeof(dump_hdr), 1, fp); - if (rc == 1) - rc = fwrite(buf, ioc_hdr->ioc_len, 1, fp); - fclose(fp); - if (rc != 1) { - fprintf(stderr, "%s: %s\n", dump_filename, - strerror(errno)); - return -EINVAL; - } - - return 0; + return rc; } /* register a device to send ioctls to. */ -int -register_ioc_dev(int dev_id, const char * dev_name, int major, int minor) +int +register_ioc_dev(int dev_id, const char *dev_name) { - - if (dev_id < 0 || + if (dev_id < 0 || dev_id >= sizeof(ioc_dev_list) / sizeof(ioc_dev_list[0])) return -EINVAL; @@ -179,216 +100,87 @@ register_ioc_dev(int dev_id, const char * dev_name, int major, int minor) ioc_dev_list[dev_id].dev_name = dev_name; ioc_dev_list[dev_id].dev_fd = -1; - ioc_dev_list[dev_id].dev_major = major; - ioc_dev_list[dev_id].dev_minor = minor; - + return dev_id; } void -unregister_ioc_dev(int dev_id) +unregister_ioc_dev(int dev_id) { + if (dev_id < 0 || + dev_id >= sizeof(ioc_dev_list) / sizeof(ioc_dev_list[0])) + return; - if (dev_id < 0 || - dev_id >= sizeof(ioc_dev_list) / sizeof(ioc_dev_list[0])) - return; - if (ioc_dev_list[dev_id].dev_name != NULL && - ioc_dev_list[dev_id].dev_fd >= 0) - cfs_proc_close(ioc_dev_list[dev_id].dev_fd); + if (ioc_dev_list[dev_id].dev_name != NULL && + ioc_dev_list[dev_id].dev_fd >= 0) + close(ioc_dev_list[dev_id].dev_fd); - ioc_dev_list[dev_id].dev_name = NULL; - ioc_dev_list[dev_id].dev_fd = -1; + ioc_dev_list[dev_id].dev_name = NULL; + ioc_dev_list[dev_id].dev_fd = -1; } -/* If this file is set, then all ioctl buffers will be - appended to the file. */ -int -set_ioctl_dump(char * file) +static inline size_t libcfs_ioctl_packlen(struct libcfs_ioctl_data *data) { - if (dump_filename) - free(dump_filename); - - dump_filename = strdup(file); - if (dump_filename == NULL) - abort(); - - set_ioc_handler(&dump); - return 0; -} + size_t len = sizeof(*data); -int -l_ioctl(int dev_id, unsigned int opc, void *buf) -{ - return current_ioc_handler(dev_id, opc, buf); -} - -/* Read an ioctl dump file, and call the ioc_func for each ioctl buffer - * in the file. For example: - * - * parse_dump("lctl.dump", l_ioctl); - * - * Note: if using l_ioctl, then you also need to register_ioc_dev() for - * each device used in the dump. - */ -int -parse_dump(char * dump_file, ioc_handler_t ioc_func) -{ - int line =0; - char *start, *buf, *end; - -#if defined(__CYGWIN__) || defined(__WINNT__) - - HANDLE fd, hmap; - DWORD size; - - fd = CreateFile(dump_file, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (fd == INVALID_HANDLE_VALUE) { - fprintf(stderr, "couldn't open %s (error code: %u)\n", - dump_file, GetLastError()); - exit(1); - } - size = GetFileSize(fd, NULL); - if (size < 1 || size == 0xFFFFFFFF) { - fprintf(stderr, "KML is empty\n"); - CloseHandle(fd); - exit(1); - } - - hmap = CreateFileMapping(fd, NULL, PAGE_READONLY, 0,0, NULL); - if (hmap == NULL) { - fprintf(stderr, "can't create file mapping\n"); - CloseHandle(fd); - exit(1); - } - start = buf = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0); - if (start == NULL) { - fprintf(stderr, "can't map file content\n"); - CloseHandle(hmap); - CloseHandle(fd); - exit(1); - } - end = buf + size; - CloseHandle(fd); - if (start == NULL) { - fprintf(stderr, "can't create file mapping\n"); - UnmapViewOfFile(start); - CloseHandle(hmap); - exit(1); - } -#else - - struct stat st; - int fd; - - fd = open(dump_file, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "couldn't open %s: %s\n", dump_file, - strerror(errno)); - exit(1); - } - - if (fstat(fd, &st)) { - perror("stat fails"); - exit(1); - } - - if (st.st_size < 1) { - fprintf(stderr, "KML is empty\n"); - exit(1); - } - - start = buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE , fd, 0); - end = start + st.st_size; - close(fd); - if (start == MAP_FAILED) { - fprintf(stderr, "can't create file mapping\n"); - exit(1); - } -#endif - - while (buf < end) { - struct dump_hdr *dump_hdr = (struct dump_hdr *) buf; - struct libcfs_ioctl_hdr * data; - char tmp[8096]; - int rc; - - line++; - - data = (struct libcfs_ioctl_hdr *) (buf + sizeof(*dump_hdr)); - if (buf + data->ioc_len > end ) { - fprintf(stderr, "dump file overflow, %p + %d > %p\n", buf, - data->ioc_len, end); - return -1; - } -#if 0 - printf ("dump_hdr: %lx data: %lx\n", - (unsigned long)dump_hdr - (unsigned long)buf, (unsigned long)data - (unsigned long)buf); - - printf("%d: opcode %x len: %d ver: %x ", line, dump_hdr->opc, - data->ioc_len, data->ioc_version); -#endif - - memcpy(tmp, data, data->ioc_len); - - rc = ioc_func(dump_hdr->dev_id, dump_hdr->opc, tmp); - if (rc) { - printf("failed: %d\n", rc); - exit(1); - } - - buf += data->ioc_len + sizeof(*dump_hdr); - } - -#if defined(__CYGWIN__) || defined(__WINNT__) - UnmapViewOfFile(start); - CloseHandle(hmap); -#else - munmap(start, end - start); -#endif - - return 0; -} - -int -jt_ioc_dump(int argc, char **argv) -{ - if (argc > 2) { - fprintf(stderr, "usage: %s [hostname]\n", argv[0]); - return 0; - } - printf("setting dumpfile to: %s\n", argv[1]); - - set_ioctl_dump(argv[1]); - return 0; + len += (data->ioc_inllen1 + 7) & ~7; + len += (data->ioc_inllen2 + 7) & ~7; + return len; } int libcfs_ioctl_pack(struct libcfs_ioctl_data *data, char **pbuf, int max) { - char *ptr; - struct libcfs_ioctl_data *overlay; - data->ioc_len = libcfs_ioctl_packlen(data); - data->ioc_version = LIBCFS_IOCTL_VERSION; - - if (*pbuf && libcfs_ioctl_packlen(data) > max) - return 1; - if (*pbuf == NULL) { - *pbuf = malloc(data->ioc_len); - } - if (!*pbuf) - return 1; - overlay = (struct libcfs_ioctl_data *)*pbuf; - memcpy(*pbuf, data, sizeof(*data)); - - ptr = overlay->ioc_bulk; - if (data->ioc_inlbuf1) - LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr); - if (data->ioc_inlbuf2) - LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr); - if (libcfs_ioctl_is_invalid(overlay)) - return 1; - - return 0; + char *ptr; + struct libcfs_ioctl_data *overlay; + data->ioc_hdr.ioc_len = libcfs_ioctl_packlen(data); + data->ioc_hdr.ioc_version = LIBCFS_IOCTL_VERSION; + + if (*pbuf != NULL && libcfs_ioctl_packlen(data) > max) + return 1; + if (*pbuf == NULL) + *pbuf = malloc(data->ioc_hdr.ioc_len); + if (*pbuf == NULL) + return 1; + overlay = (struct libcfs_ioctl_data *)*pbuf; + memcpy(*pbuf, data, sizeof(*data)); + + ptr = overlay->ioc_bulk; + if (data->ioc_inlbuf1 != NULL) { + memcpy((char *)ptr, (const char *)data->ioc_inlbuf1, + data->ioc_inllen1); + ptr += ((data->ioc_inllen1 + 7) & ~7); + } + if (data->ioc_inlbuf2 != NULL) { + memcpy((char *)ptr, (const char *)data->ioc_inlbuf2, + data->ioc_inllen2); + ptr += ((data->ioc_inllen2 + 7) & ~7); + } + + return 0; } +void +libcfs_ioctl_unpack(struct libcfs_ioctl_data *data, char *pbuf) +{ + struct libcfs_ioctl_data *overlay = (struct libcfs_ioctl_data *)pbuf; + char *ptr; + + /* Preserve the caller's buffer pointers */ + overlay->ioc_inlbuf1 = data->ioc_inlbuf1; + overlay->ioc_inlbuf2 = data->ioc_inlbuf2; + + memcpy(data, pbuf, sizeof(*data)); + ptr = &overlay->ioc_bulk[0]; + + if (data->ioc_inlbuf1 != NULL) { + memcpy((char *)data->ioc_inlbuf1, (const char *)ptr, + data->ioc_inllen1); + ptr += ((data->ioc_inllen1 + 7) & ~7); + } + if (data->ioc_inlbuf2 != NULL) { + memcpy((char *)data->ioc_inlbuf2, (const char *)ptr, + data->ioc_inllen2); + ptr += ((data->ioc_inllen2 + 7) & ~7); + } +}