2 * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
4 * Copyright (c) 2014, Intel Corporation.
6 * This file is part of Lustre, https://wiki.hpdd.intel.com/
8 * Portals is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Portals is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Portals; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #define __USE_FILE_OFFSET64
30 #include <sys/ioctl.h>
32 #include <sys/types.h>
35 #include <linux/types.h>
37 #include <libcfs/util/ioctl.h>
38 #include <lnet/lnetctl.h>
41 const char * dev_name;
47 static struct ioc_dev ioc_dev_list[10];
55 /* Catamount has no <linux/kdev_t.h>, so just define it here */
57 # define MKDEV(a,b) (((a) << 8) | (b))
61 open_ioc_dev(int dev_id)
63 const char * dev_name;
66 dev_id >= sizeof(ioc_dev_list) / sizeof(ioc_dev_list[0]))
69 dev_name = ioc_dev_list[dev_id].dev_name;
70 if (dev_name == NULL) {
71 fprintf(stderr, "unknown device id: %d\n", dev_id);
75 if (ioc_dev_list[dev_id].dev_fd < 0) {
76 int fd = open(dev_name, O_RDWR);
78 /* Make the /dev/ node if we need to */
79 if (fd < 0 && errno == ENOENT) {
80 if (mknod(dev_name, S_IFCHR|S_IWUSR|S_IRUSR,
81 MKDEV(ioc_dev_list[dev_id].dev_major,
82 ioc_dev_list[dev_id].dev_minor)) == 0)
83 fd = open(dev_name, O_RDWR);
85 fprintf(stderr, "mknod %s failed: %s\n",
86 dev_name, strerror(errno));
90 fprintf(stderr, "opening %s failed: %s\n"
91 "hint: the kernel modules may not be loaded\n",
92 dev_name, strerror(errno));
95 ioc_dev_list[dev_id].dev_fd = fd;
98 return ioc_dev_list[dev_id].dev_fd;
102 int l_ioctl(int dev_id, unsigned int opc, void *buf)
106 fd = open_ioc_dev(dev_id);
110 rc = ioctl(fd, opc, buf);
115 /* register a device to send ioctls to. */
117 register_ioc_dev(int dev_id, const char *dev_name, int major, int minor)
121 dev_id >= sizeof(ioc_dev_list) / sizeof(ioc_dev_list[0]))
124 unregister_ioc_dev(dev_id);
126 ioc_dev_list[dev_id].dev_name = dev_name;
127 ioc_dev_list[dev_id].dev_fd = -1;
128 ioc_dev_list[dev_id].dev_major = major;
129 ioc_dev_list[dev_id].dev_minor = minor;
135 unregister_ioc_dev(int dev_id)
138 dev_id >= sizeof(ioc_dev_list) / sizeof(ioc_dev_list[0]))
141 if (ioc_dev_list[dev_id].dev_name != NULL &&
142 ioc_dev_list[dev_id].dev_fd >= 0)
143 close(ioc_dev_list[dev_id].dev_fd);
145 ioc_dev_list[dev_id].dev_name = NULL;
146 ioc_dev_list[dev_id].dev_fd = -1;
149 int libcfs_ioctl_pack(struct libcfs_ioctl_data *data, char **pbuf,
153 struct libcfs_ioctl_data *overlay;
154 data->ioc_hdr.ioc_len = libcfs_ioctl_packlen(data);
155 data->ioc_hdr.ioc_version = LIBCFS_IOCTL_VERSION;
157 if (*pbuf != NULL && libcfs_ioctl_packlen(data) > max)
160 *pbuf = malloc(data->ioc_hdr.ioc_len);
163 overlay = (struct libcfs_ioctl_data *)*pbuf;
164 memcpy(*pbuf, data, sizeof(*data));
166 ptr = overlay->ioc_bulk;
167 if (data->ioc_inlbuf1 != NULL) {
168 memcpy((char *)ptr, (const char *)data->ioc_inlbuf1,
170 ptr += ((data->ioc_inllen1 + 7) & ~7);
172 if (data->ioc_inlbuf2 != NULL) {
173 memcpy((char *)ptr, (const char *)data->ioc_inlbuf2,
175 ptr += ((data->ioc_inllen2 + 7) & ~7);
178 if (libcfs_ioctl_is_invalid(overlay))
185 libcfs_ioctl_unpack(struct libcfs_ioctl_data *data, char *pbuf)
187 struct libcfs_ioctl_data *overlay = (struct libcfs_ioctl_data *)pbuf;
190 /* Preserve the caller's buffer pointers */
191 overlay->ioc_inlbuf1 = data->ioc_inlbuf1;
192 overlay->ioc_inlbuf2 = data->ioc_inlbuf2;
194 memcpy(data, pbuf, sizeof(*data));
195 ptr = &overlay->ioc_bulk[0];
197 if (data->ioc_inlbuf1 != NULL) {
198 memcpy((char *)data->ioc_inlbuf1, (const char *)ptr,
200 ptr += ((data->ioc_inllen1 + 7) & ~7);
202 if (data->ioc_inlbuf2 != NULL) {
203 memcpy((char *)data->ioc_inlbuf2, (const char *)ptr,
205 ptr += ((data->ioc_inllen2 + 7) & ~7);