Whamcloud - gitweb
3a6cf5d3eb3803258a655f7b5ee38b453b228909
[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
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
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 (c) 2007, 2010, Oracle and/or its affiliates. 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         OBD_ALLOC_LARGE(*buf, hdr->ioc_len);
84         if (*buf == NULL) {
85                 CERROR("Cannot allocate control buffer of len %d\n",
86                        hdr->ioc_len);
87                 RETURN(-EINVAL);
88         }
89         *len = hdr->ioc_len;
90         data = (struct obd_ioctl_data *)*buf;
91
92         bzero(data, hdr->ioc_len);
93         memcpy(data, (void *)arg, sizeof(struct obd_ioctl_data));
94         if (data->ioc_inlbuf1)
95                 err = copy_from_user(&data->ioc_bulk[0], (void *)data->ioc_inlbuf1,
96                                      hdr->ioc_len - ((void *)&data->ioc_bulk[0] - (void *)data));
97
98         if (obd_ioctl_is_invalid(data)) {
99                 CERROR("ioctl not correctly formatted\n");
100                 OBD_FREE_LARGE(*buf, hdr->ioc_len);
101                 return -EINVAL;
102         }
103
104         if (data->ioc_inllen1) {
105                 data->ioc_inlbuf1 = &data->ioc_bulk[0];
106                 offset += size_round(data->ioc_inllen1);
107         }
108
109         if (data->ioc_inllen2) {
110                 data->ioc_inlbuf2 = &data->ioc_bulk[0] + offset;
111                 offset += size_round(data->ioc_inllen2);
112         }
113
114         if (data->ioc_inllen3) {
115                 data->ioc_inlbuf3 = &data->ioc_bulk[0] + offset;
116                 offset += size_round(data->ioc_inllen3);
117         }
118
119         if (data->ioc_inllen4) {
120                 data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset;
121         }
122
123         EXIT;
124         return 0;
125 }
126
127 int obd_ioctl_popdata(void *arg, void *data, int len)
128 {
129         /* 
130          * Xnu ioctl copyout(uaddr, arg, sizeof(struct obd_ioctl_data)),
131          * we have to copyout data exceed sizeof(struct obd_ioctl_data)
132          * by ourself.
133          */
134         if (len <= sizeof(struct obd_ioctl_data)) {
135                 memcpy(arg, data, len);
136                 return 0;
137         } else {
138                 int err;
139                 struct obd_ioctl_data *u = (struct obd_ioctl_data *)arg;
140                 struct obd_ioctl_data *k = (struct obd_ioctl_data *)data;
141                 err = copy_to_user((void *)u->ioc_inlbuf1, &k->ioc_bulk[0],
142                                     len -((void *)&k->ioc_bulk[0] -(void *)k));
143                 memcpy(arg, data, sizeof(struct obd_ioctl_data));
144                 return err;
145         }
146 }
147
148 static int
149 obd_class_open(dev_t dev, int flags, int devtype, struct proc *p)
150 {
151         ENTRY;
152
153         RETURN(0);
154 }
155
156 /*  closing /dev/obd */
157 static int
158 obd_class_release(dev_t dev, int flags, int mode, struct proc *p)
159 {
160         ENTRY;
161
162         RETURN(0);
163 }
164
165 static int
166 obd_class_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
167 {
168         int err = 0;
169         ENTRY;
170
171         if (!is_suser())
172                 RETURN (EPERM);
173
174         err = class_handle_ioctl(cmd, (unsigned long)arg);
175
176         RETURN(err);
177 }
178
179 static struct cdevsw obd_psdevsw = {
180         obd_class_open,
181         obd_class_release,
182         NULL,
183         NULL,
184         obd_class_ioctl,
185         NULL,
186         NULL,
187         NULL,
188         NULL,
189         NULL,
190         NULL,
191         NULL,
192         NULL,
193 };
194
195 cfs_psdev_t obd_psdev = {
196         -1,
197         NULL,
198         "obd",
199         &obd_psdevsw
200 };
201
202 int class_procfs_init(void)
203 {
204         return 0;
205 }
206
207 int class_procfs_clean(void)
208 {
209         return 0;
210 }