1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
6 * This file is part of Portals, http://www.sf.net/projects/lustre/
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
25 #include <libcfs/libcfsutil.h>
26 #include <lnet/api-support.h>
27 #include <lnet/lnetctl.h>
29 static ioc_handler_t do_ioctl; /* forward ref */
30 static ioc_handler_t *current_ioc_handler = &do_ioctl;
33 const char * dev_name;
39 static struct ioc_dev ioc_dev_list[10];
50 set_ioc_handler (ioc_handler_t *handler)
53 current_ioc_handler = do_ioctl;
55 current_ioc_handler = handler;
58 /* Catamount has no <linux/kdev_t.h>, so just define it here */
60 # define MKDEV(a,b) (((a) << 8) | (b))
64 open_ioc_dev(int dev_id)
66 const char * dev_name;
69 dev_id >= sizeof(ioc_dev_list) / sizeof(ioc_dev_list[0]))
72 dev_name = ioc_dev_list[dev_id].dev_name;
73 if (dev_name == NULL) {
74 fprintf(stderr, "unknown device id: %d\n", dev_id);
78 if (ioc_dev_list[dev_id].dev_fd < 0) {
79 int fd = cfs_proc_open((char *)dev_name, O_RDWR);
81 /* Make the /dev/ node if we need to */
82 if (fd < 0 && errno == ENOENT) {
83 if (cfs_proc_mknod(dev_name,
84 S_IFCHR|S_IWUSR|S_IRUSR,
85 MKDEV(ioc_dev_list[dev_id].dev_major,
86 ioc_dev_list[dev_id].dev_minor)) == 0)
87 fd = cfs_proc_open((char *)dev_name, O_RDWR);
89 fprintf(stderr, "mknod %s failed: %s\n",
90 dev_name, strerror(errno));
94 fprintf(stderr, "opening %s failed: %s\n"
95 "hint: the kernel modules may not be loaded\n",
96 dev_name, strerror(errno));
99 ioc_dev_list[dev_id].dev_fd = fd;
102 return ioc_dev_list[dev_id].dev_fd;
107 do_ioctl(int dev_id, unsigned int opc, void *buf)
111 fd = open_ioc_dev(dev_id);
115 rc = cfs_proc_ioctl(fd, opc, buf);
125 if (!dump_filename) {
126 fprintf(stderr, "no dump filename\n");
128 fp = fopen(dump_filename, "a");
133 * The dump file should start with a description of which devices are
134 * used, but for now it will assumed whatever app reads the file will
135 * know what to do. */
137 dump(int dev_id, unsigned int opc, void *buf)
140 struct dump_hdr dump_hdr;
141 struct libcfs_ioctl_hdr * ioc_hdr = (struct libcfs_ioctl_hdr *) buf;
144 printf("dumping opc %x to %s\n", opc, dump_filename);
147 dump_hdr.magic = 0xdeadbeef;
148 dump_hdr.dev_id = dev_id;
151 fp = get_dump_file();
153 fprintf(stderr, "%s: %s\n", dump_filename,
158 rc = fwrite(&dump_hdr, sizeof(dump_hdr), 1, fp);
160 rc = fwrite(buf, ioc_hdr->ioc_len, 1, fp);
163 fprintf(stderr, "%s: %s\n", dump_filename,
171 /* register a device to send ioctls to. */
173 register_ioc_dev(int dev_id, const char * dev_name, int major, int minor)
177 dev_id >= sizeof(ioc_dev_list) / sizeof(ioc_dev_list[0]))
180 unregister_ioc_dev(dev_id);
182 ioc_dev_list[dev_id].dev_name = dev_name;
183 ioc_dev_list[dev_id].dev_fd = -1;
184 ioc_dev_list[dev_id].dev_major = major;
185 ioc_dev_list[dev_id].dev_minor = minor;
191 unregister_ioc_dev(int dev_id)
195 dev_id >= sizeof(ioc_dev_list) / sizeof(ioc_dev_list[0]))
197 if (ioc_dev_list[dev_id].dev_name != NULL &&
198 ioc_dev_list[dev_id].dev_fd >= 0)
199 cfs_proc_close(ioc_dev_list[dev_id].dev_fd);
201 ioc_dev_list[dev_id].dev_name = NULL;
202 ioc_dev_list[dev_id].dev_fd = -1;
205 /* If this file is set, then all ioctl buffers will be
206 appended to the file. */
208 set_ioctl_dump(char * file)
213 dump_filename = strdup(file);
214 if (dump_filename == NULL)
217 set_ioc_handler(&dump);
222 l_ioctl(int dev_id, unsigned int opc, void *buf)
224 return current_ioc_handler(dev_id, opc, buf);
227 /* Read an ioctl dump file, and call the ioc_func for each ioctl buffer
228 * in the file. For example:
230 * parse_dump("lctl.dump", l_ioctl);
232 * Note: if using l_ioctl, then you also need to register_ioc_dev() for
233 * each device used in the dump.
236 parse_dump(char * dump_file, ioc_handler_t ioc_func)
239 char *start, *buf, *end;
241 #if defined(__CYGWIN__) || defined(__WINNT__)
246 fd = CreateFile(dump_file, GENERIC_READ, FILE_SHARE_READ, NULL,
247 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
248 if (fd == INVALID_HANDLE_VALUE) {
249 fprintf(stderr, "couldn't open %s (error code: %u)\n",
250 dump_file, GetLastError());
253 size = GetFileSize(fd, NULL);
254 if (size < 1 || size == 0xFFFFFFFF) {
255 fprintf(stderr, "KML is empty\n");
260 hmap = CreateFileMapping(fd, NULL, PAGE_READONLY, 0,0, NULL);
262 fprintf(stderr, "can't create file mapping\n");
266 start = buf = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0);
268 fprintf(stderr, "can't map file content\n");
276 fprintf(stderr, "can't create file mapping\n");
277 UnmapViewOfFile(start);
286 fd = open(dump_file, O_RDONLY);
288 fprintf(stderr, "couldn't open %s: %s\n", dump_file,
293 if (fstat(fd, &st)) {
294 perror("stat fails");
298 if (st.st_size < 1) {
299 fprintf(stderr, "KML is empty\n");
303 start = buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE , fd, 0);
304 end = start + st.st_size;
306 if (start == MAP_FAILED) {
307 fprintf(stderr, "can't create file mapping\n");
313 struct dump_hdr *dump_hdr = (struct dump_hdr *) buf;
314 struct libcfs_ioctl_hdr * data;
320 data = (struct libcfs_ioctl_hdr *) (buf + sizeof(*dump_hdr));
321 if (buf + data->ioc_len > end ) {
322 fprintf(stderr, "dump file overflow, %p + %d > %p\n", buf,
327 printf ("dump_hdr: %lx data: %lx\n",
328 (unsigned long)dump_hdr - (unsigned long)buf, (unsigned long)data - (unsigned long)buf);
330 printf("%d: opcode %x len: %d ver: %x ", line, dump_hdr->opc,
331 data->ioc_len, data->ioc_version);
334 memcpy(tmp, data, data->ioc_len);
336 rc = ioc_func(dump_hdr->dev_id, dump_hdr->opc, tmp);
338 printf("failed: %d\n", rc);
342 buf += data->ioc_len + sizeof(*dump_hdr);
345 #if defined(__CYGWIN__) || defined(__WINNT__)
346 UnmapViewOfFile(start);
349 munmap(start, end - start);
356 jt_ioc_dump(int argc, char **argv)
359 fprintf(stderr, "usage: %s [hostname]\n", argv[0]);
362 printf("setting dumpfile to: %s\n", argv[1]);
364 set_ioctl_dump(argv[1]);
368 int libcfs_ioctl_pack(struct libcfs_ioctl_data *data, char **pbuf,
372 struct libcfs_ioctl_data *overlay;
373 data->ioc_len = libcfs_ioctl_packlen(data);
374 data->ioc_version = LIBCFS_IOCTL_VERSION;
376 if (*pbuf && libcfs_ioctl_packlen(data) > max)
379 *pbuf = malloc(data->ioc_len);
383 overlay = (struct libcfs_ioctl_data *)*pbuf;
384 memcpy(*pbuf, data, sizeof(*data));
386 ptr = overlay->ioc_bulk;
387 if (data->ioc_inlbuf1)
388 LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr);
389 if (data->ioc_inlbuf2)
390 LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr);
391 if (libcfs_ioctl_is_invalid(overlay))