]>
Commit | Line | Data |
---|---|---|
d7e09d03 PT |
1 | /* |
2 | * GPL HEADER START | |
3 | * | |
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
5 | * | |
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. | |
9 | * | |
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). | |
15 | * | |
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 | |
19 | * | |
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 | |
22 | * have any questions. | |
23 | * | |
24 | * GPL HEADER END | |
25 | */ | |
26 | /* | |
27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | |
28 | * Use is subject to license terms. | |
29 | * | |
30 | * Copyright (c) 2012, Intel Corporation. | |
31 | */ | |
32 | /* | |
33 | * This file is part of Lustre, http://www.lustre.org/ | |
34 | * Lustre is a trademark of Sun Microsystems, Inc. | |
35 | */ | |
36 | ||
37 | #define DEBUG_SUBSYSTEM S_LNET | |
38 | ||
9fdaf8c0 | 39 | #include "../../../include/linux/libcfs/libcfs.h" |
d7e09d03 PT |
40 | |
41 | #define LNET_MINOR 240 | |
42 | ||
43 | int libcfs_ioctl_getdata(char *buf, char *end, void *arg) | |
44 | { | |
45 | struct libcfs_ioctl_hdr *hdr; | |
46 | struct libcfs_ioctl_data *data; | |
2e5ed7fd | 47 | int orig_len; |
d7e09d03 PT |
48 | |
49 | hdr = (struct libcfs_ioctl_hdr *)buf; | |
50 | data = (struct libcfs_ioctl_data *)buf; | |
51 | ||
a12aaa92 | 52 | if (copy_from_user(buf, arg, sizeof(*hdr))) |
a9c08b0a | 53 | return -EFAULT; |
d7e09d03 PT |
54 | |
55 | if (hdr->ioc_version != LIBCFS_IOCTL_VERSION) { | |
56 | CERROR("PORTALS: version mismatch kernel vs application\n"); | |
0a3bdb00 | 57 | return -EINVAL; |
d7e09d03 PT |
58 | } |
59 | ||
faec8ab4 | 60 | if (hdr->ioc_len >= end - buf) { |
d7e09d03 | 61 | CERROR("PORTALS: user buffer exceeds kernel buffer\n"); |
0a3bdb00 | 62 | return -EINVAL; |
d7e09d03 PT |
63 | } |
64 | ||
65 | ||
66 | if (hdr->ioc_len < sizeof(struct libcfs_ioctl_data)) { | |
67 | CERROR("PORTALS: user buffer too small for ioctl\n"); | |
0a3bdb00 | 68 | return -EINVAL; |
d7e09d03 PT |
69 | } |
70 | ||
2e5ed7fd | 71 | orig_len = hdr->ioc_len; |
a12aaa92 | 72 | if (copy_from_user(buf, arg, hdr->ioc_len)) |
a9c08b0a | 73 | return -EFAULT; |
2e5ed7fd DC |
74 | if (orig_len != data->ioc_len) |
75 | return -EINVAL; | |
d7e09d03 PT |
76 | |
77 | if (libcfs_ioctl_is_invalid(data)) { | |
78 | CERROR("PORTALS: ioctl not correctly formatted\n"); | |
0a3bdb00 | 79 | return -EINVAL; |
d7e09d03 PT |
80 | } |
81 | ||
82 | if (data->ioc_inllen1) | |
83 | data->ioc_inlbuf1 = &data->ioc_bulk[0]; | |
84 | ||
85 | if (data->ioc_inllen2) | |
86 | data->ioc_inlbuf2 = &data->ioc_bulk[0] + | |
87 | cfs_size_round(data->ioc_inllen1); | |
88 | ||
0a3bdb00 | 89 | return 0; |
d7e09d03 PT |
90 | } |
91 | ||
92 | int libcfs_ioctl_popdata(void *arg, void *data, int size) | |
93 | { | |
94 | if (copy_to_user((char *)arg, data, size)) | |
95 | return -EFAULT; | |
96 | return 0; | |
97 | } | |
98 | ||
d7e09d03 | 99 | static int |
fb574144 | 100 | libcfs_psdev_open(struct inode *inode, struct file *file) |
d7e09d03 PT |
101 | { |
102 | struct libcfs_device_userstate **pdu = NULL; | |
103 | int rc = 0; | |
104 | ||
105 | if (!inode) | |
fbe7c6c7 | 106 | return -EINVAL; |
d7e09d03 PT |
107 | pdu = (struct libcfs_device_userstate **)&file->private_data; |
108 | if (libcfs_psdev_ops.p_open != NULL) | |
109 | rc = libcfs_psdev_ops.p_open(0, (void *)pdu); | |
110 | else | |
fbe7c6c7 | 111 | return -EPERM; |
d7e09d03 PT |
112 | return rc; |
113 | } | |
114 | ||
115 | /* called when closing /dev/device */ | |
116 | static int | |
fb574144 | 117 | libcfs_psdev_release(struct inode *inode, struct file *file) |
d7e09d03 PT |
118 | { |
119 | struct libcfs_device_userstate *pdu; | |
120 | int rc = 0; | |
121 | ||
122 | if (!inode) | |
fbe7c6c7 | 123 | return -EINVAL; |
d7e09d03 PT |
124 | pdu = file->private_data; |
125 | if (libcfs_psdev_ops.p_close != NULL) | |
126 | rc = libcfs_psdev_ops.p_close(0, (void *)pdu); | |
127 | else | |
128 | rc = -EPERM; | |
129 | return rc; | |
130 | } | |
131 | ||
132 | static long libcfs_ioctl(struct file *file, | |
133 | unsigned int cmd, unsigned long arg) | |
134 | { | |
135 | struct cfs_psdev_file pfile; | |
136 | int rc = 0; | |
137 | ||
4b1a25f0 | 138 | if (!capable(CAP_SYS_ADMIN)) |
d7e09d03 PT |
139 | return -EACCES; |
140 | ||
91a002c7 | 141 | if (_IOC_TYPE(cmd) != IOC_LIBCFS_TYPE || |
d7e09d03 | 142 | _IOC_NR(cmd) < IOC_LIBCFS_MIN_NR || |
91a002c7 | 143 | _IOC_NR(cmd) > IOC_LIBCFS_MAX_NR) { |
d7e09d03 PT |
144 | CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n", |
145 | _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd)); | |
fbe7c6c7 | 146 | return -EINVAL; |
d7e09d03 PT |
147 | } |
148 | ||
149 | /* Handle platform-dependent IOC requests */ | |
150 | switch (cmd) { | |
151 | case IOC_LIBCFS_PANIC: | |
2eb90a75 | 152 | if (!capable(CFS_CAP_SYS_BOOT)) |
fbe7c6c7 | 153 | return -EPERM; |
d7e09d03 | 154 | panic("debugctl-invoked panic"); |
18e2e99b | 155 | return 0; |
d7e09d03 | 156 | case IOC_LIBCFS_MEMHOG: |
2eb90a75 | 157 | if (!capable(CFS_CAP_SYS_ADMIN)) |
d7e09d03 PT |
158 | return -EPERM; |
159 | /* go thought */ | |
160 | } | |
161 | ||
162 | pfile.off = 0; | |
163 | pfile.private_data = file->private_data; | |
164 | if (libcfs_psdev_ops.p_ioctl != NULL) | |
165 | rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void *)arg); | |
166 | else | |
167 | rc = -EPERM; | |
18e2e99b | 168 | return rc; |
d7e09d03 PT |
169 | } |
170 | ||
d81f9f51 | 171 | static const struct file_operations libcfs_fops = { |
805e517a EG |
172 | .unlocked_ioctl = libcfs_ioctl, |
173 | .open = libcfs_psdev_open, | |
174 | .release = libcfs_psdev_release, | |
d7e09d03 PT |
175 | }; |
176 | ||
c0426cf7 GKH |
177 | struct miscdevice libcfs_dev = { |
178 | .minor = LNET_MINOR, | |
179 | .name = "lnet", | |
180 | .fops = &libcfs_fops, | |
d7e09d03 | 181 | }; |