Whamcloud - gitweb
b=16098
[fs/lustre-release.git] / lustre / obdclass / darwin / darwin-module.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
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.
11  *
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).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see [sun.com URL with a
20  * copy of GPLv2].
21  *
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
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
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_CLASS
38 #ifndef EXPORT_SYMTAB
39 # define EXPORT_SYMTAB
40 #endif
41
42 #include <mach/mach_types.h>
43 #include <string.h>
44 #include <sys/file.h>
45 #include <sys/conf.h>
46 #include <miscfs/devfs/devfs.h>
47
48 #include <libcfs/libcfs.h>
49 #include <obd_support.h>
50 #include <obd_class.h>
51 #include <lprocfs_status.h>
52
53 #ifndef OBD_MAX_IOCTL_BUFFER
54 #define OBD_MAX_IOCTL_BUFFER 8192
55 #endif
56
57 /* buffer MUST be at least the size of obd_ioctl_hdr */
58 int obd_ioctl_getdata(char **buf, int *len, void *arg)
59 {
60         struct obd_ioctl_hdr *hdr;
61         struct obd_ioctl_data *data;
62         int err = 0;
63         int offset = 0;
64         ENTRY;
65
66         hdr = (struct obd_ioctl_hdr *)arg;
67         if (hdr->ioc_version != OBD_IOCTL_VERSION) {
68                 CERROR("Version mismatch kernel vs application\n");
69                 RETURN(-EINVAL);
70         }
71
72         if (hdr->ioc_len > OBD_MAX_IOCTL_BUFFER) {
73                 CERROR("User buffer len %d exceeds %d max buffer\n",
74                        hdr->ioc_len, OBD_MAX_IOCTL_BUFFER);
75                 RETURN(-EINVAL);
76         }
77
78         if (hdr->ioc_len < sizeof(struct obd_ioctl_data)) {
79                 CERROR("OBD: user buffer too small for ioctl (%d)\n", hdr->ioc_len);
80                 RETURN(-EINVAL);
81         }
82
83         /* XXX allocate this more intelligently, using kmalloc when
84          * appropriate */
85         OBD_VMALLOC(*buf, hdr->ioc_len);
86         if (*buf == NULL) {
87                 CERROR("Cannot allocate control buffer of len %d\n",
88                        hdr->ioc_len);
89                 RETURN(-EINVAL);
90         }
91         *len = hdr->ioc_len;
92         data = (struct obd_ioctl_data *)*buf;
93
94         bzero(data, hdr->ioc_len);
95         memcpy(data, (void *)arg, sizeof(struct obd_ioctl_data));
96         if (data->ioc_inlbuf1)
97                 err = copy_from_user(&data->ioc_bulk[0], (void *)data->ioc_inlbuf1,
98                                      hdr->ioc_len - ((void *)&data->ioc_bulk[0] - (void *)data));
99
100         if (obd_ioctl_is_invalid(data)) {
101                 CERROR("ioctl not correctly formatted\n");
102                 return -EINVAL;
103         }
104
105         if (data->ioc_inllen1) {
106                 data->ioc_inlbuf1 = &data->ioc_bulk[0];
107                 offset += size_round(data->ioc_inllen1);
108         }
109
110         if (data->ioc_inllen2) {
111                 data->ioc_inlbuf2 = &data->ioc_bulk[0] + offset;
112                 offset += size_round(data->ioc_inllen2);
113         }
114
115         if (data->ioc_inllen3) {
116                 data->ioc_inlbuf3 = &data->ioc_bulk[0] + offset;
117                 offset += size_round(data->ioc_inllen3);
118         }
119
120         if (data->ioc_inllen4) {
121                 data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset;
122         }
123
124         EXIT;
125         return 0;
126 }
127
128 int obd_ioctl_popdata(void *arg, void *data, int len)
129 {
130         /* 
131          * Xnu ioctl copyout(uaddr, arg, sizeof(struct obd_ioctl_data)),
132          * we have to copyout data exceed sizeof(struct obd_ioctl_data)
133          * by ourself.
134          */
135         if (len <= sizeof(struct obd_ioctl_data)) {
136                 memcpy(arg, data, len);
137                 return 0;
138         } else {
139                 int err;
140                 struct obd_ioctl_data *u = (struct obd_ioctl_data *)arg;
141                 struct obd_ioctl_data *k = (struct obd_ioctl_data *)data;
142                 err = copy_to_user((void *)u->ioc_inlbuf1, &k->ioc_bulk[0],
143                                     len -((void *)&k->ioc_bulk[0] -(void *)k));
144                 memcpy(arg, data, sizeof(struct obd_ioctl_data));
145                 return err;
146         }
147 }
148 /*
149  * cfs pseudo device
150  */
151 extern struct cfs_psdev_ops          obd_psdev_ops;
152
153 static int
154 obd_class_open(dev_t dev, int flags, int devtype, struct proc *p)
155 {
156         if (obd_psdev_ops.p_open != NULL)
157                 return -obd_psdev_ops.p_open(0, NULL);
158         return EPERM;
159 }
160
161 /*  closing /dev/obd */
162 static int
163 obd_class_release(dev_t dev, int flags, int mode, struct proc *p)
164 {
165         if (obd_psdev_ops.p_close != NULL)
166                 return -obd_psdev_ops.p_close(0, NULL);
167         return EPERM;
168 }
169
170 static int
171 obd_class_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
172 {
173         int err = 0;
174         ENTRY;
175
176         if (!is_suser())
177                 RETURN (EPERM);
178         if (obd_psdev_ops.p_ioctl != NULL)
179                 err = -obd_psdev_ops.p_ioctl(NULL, cmd, (void *)arg);
180         else
181                 err = EPERM;
182
183         RETURN(err);
184 }
185
186 static struct cdevsw obd_psdevsw = {
187         obd_class_open,
188         obd_class_release,
189         NULL,
190         NULL,
191         obd_class_ioctl,
192         NULL,
193         NULL,
194         NULL,
195         NULL,
196         NULL,
197         NULL,
198         NULL,
199         NULL,
200 };
201
202 cfs_psdev_t obd_psdev = {
203         -1,
204         NULL,
205         "obd",
206         &obd_psdevsw
207 };
208
209 int class_procfs_init(void)
210 {
211         return 0;
212 }
213
214 int class_procfs_clean(void)
215 {
216         return 0;
217 }