Whamcloud - gitweb
LU-1346 libcfs: cleanup libcfs primitive (linux-prim.h)
[fs/lustre-release.git] / libcfs / libcfs / darwin / darwin-module.c
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 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  */
34
35 #include <mach/mach_types.h>
36 #include <string.h>
37 #include <sys/file.h>
38 #include <sys/conf.h>
39 #include <miscfs/devfs/devfs.h>
40
41 #define DEBUG_SUBSYSTEM S_LNET
42 #include <libcfs/libcfs.h>
43
44 int libcfs_ioctl_getdata(char *buf, char *end, void *arg)
45 {
46         struct libcfs_ioctl_hdr *hdr;
47         struct libcfs_ioctl_data *data;
48         int err = 0;
49         ENTRY;
50
51         hdr = (struct libcfs_ioctl_hdr *)buf;
52         data = (struct libcfs_ioctl_data *)buf;
53         /* libcfs_ioctl_data has been copied in by ioctl of osx */
54         memcpy(buf, arg, sizeof(struct libcfs_ioctl_data));
55
56         if (hdr->ioc_version != LIBCFS_IOCTL_VERSION) {
57                 CERROR("LIBCFS: version mismatch kernel vs application\n");
58                 RETURN(-EINVAL);
59         }
60
61         if (hdr->ioc_len + buf >= end) {
62                 CERROR("LIBCFS: user buffer exceeds kernel buffer\n");
63                 RETURN(-EINVAL);
64         }
65
66         if (hdr->ioc_len < sizeof(struct libcfs_ioctl_data)) {
67                 CERROR("LIBCFS: user buffer too small for ioctl\n");
68                 RETURN(-EINVAL);
69         }
70         buf += size_round(sizeof(*data));
71
72         if (data->ioc_inllen1) {
73                 err = copy_from_user(buf, data->ioc_inlbuf1, size_round(data->ioc_inllen1));
74                 if (err)
75                         RETURN(err);
76                 data->ioc_inlbuf1 = buf;
77                 buf += size_round(data->ioc_inllen1);
78         }
79
80         if (data->ioc_inllen2) {
81                 copy_from_user(buf, data->ioc_inlbuf2, size_round(data->ioc_inllen2));
82                 if (err)
83                         RETURN(err);
84                 data->ioc_inlbuf2 = buf;
85         }
86
87         RETURN(err);
88 }
89
90 int libcfs_ioctl_popdata(void *arg, void *data, int size)
91 {
92         /* 
93          * system call will copy out ioctl arg to user space
94          */
95         memcpy(arg, data, size);
96         return 0;
97 }
98
99 extern struct cfs_psdev_ops             libcfs_psdev_ops;
100 struct libcfs_device_userstate          *mdev_state[16];
101
102 static int
103 libcfs_psdev_open(dev_t dev, int flags, int devtype, struct proc *p)
104 {
105         struct  libcfs_device_userstate *mstat = NULL;
106         int     rc = 0;
107         int     devid;
108         devid = minor(dev);
109
110         if (devid > 16) return (ENXIO);
111
112         if (libcfs_psdev_ops.p_open != NULL)
113                 rc = -libcfs_psdev_ops.p_open(0, &mstat);
114         else
115                 rc = EPERM;
116         if (rc == 0)
117                 mdev_state[devid] = mstat;
118         return rc;
119 }
120
121 static int
122 libcfs_psdev_close(dev_t dev, int flags, int mode, struct proc *p)
123 {
124         int     devid;
125         devid = minor(dev);
126         int     rc = 0;
127
128         if (devid > 16) return (ENXIO);
129
130         if (libcfs_psdev_ops.p_close != NULL)
131                 rc = -libcfs_psdev_ops.p_close(0, mdev_state[devid]);
132         else
133                 rc = EPERM;
134         if (rc == 0)
135                 mdev_state[devid] = NULL;
136         return rc;
137 }
138
139 static int
140 libcfs_ioctl (dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
141 {
142         int rc = 0;
143         struct cfs_psdev_file    pfile;
144         int     devid;
145         devid = minor(dev);
146         
147         if (devid > 16) return (ENXIO);
148
149         if (!is_suser())
150                 return (EPERM);
151         
152         pfile.off = 0;
153         pfile.private_data = mdev_state[devid];
154
155         if (libcfs_psdev_ops.p_ioctl != NULL)
156                 rc = -libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void *)arg);
157         else
158                 rc = EPERM;
159         return rc;
160 }
161
162 static struct cdevsw libcfs_devsw =
163 {
164         .d_open     = libcfs_psdev_open,
165         .d_close    = libcfs_psdev_close,
166         .d_read     = eno_rdwrt,
167         .d_write    = eno_rdwrt,
168         .d_ioctl    = libcfs_ioctl,
169         .d_stop     = eno_stop,
170         .d_reset    = eno_reset,
171         .d_ttys     = NULL,
172         .d_select   = eno_select,
173         .d_mmap     = eno_mmap,
174         .d_strategy = eno_strat,
175         .d_getc     = eno_getc,
176         .d_putc     = eno_putc,
177         .d_type     = 0
178 };
179
180 struct miscdevice libcfs_dev = {
181         -1,
182         NULL,
183         "lnet",
184         &libcfs_devsw,
185         NULL
186 };
187
188 extern spinlock_t trace_cpu_serializer;
189 extern void cfs_sync_init(void);
190 extern void cfs_sync_fini(void);
191 extern int cfs_sysctl_init(void);
192 extern void cfs_sysctl_fini(void);
193 extern int cfs_mem_init(void);
194 extern int cfs_mem_fini(void);
195 extern void raw_page_death_row_clean(void);
196 extern void cfs_thread_agent_init(void);
197 extern void cfs_thread_agent_fini(void);
198 extern void cfs_symbol_init(void);
199 extern void cfs_symbol_fini(void);
200
201 int libcfs_arch_init(void)
202 {
203         cfs_sync_init();
204         cfs_sysctl_init();
205         cfs_mem_init();
206         cfs_thread_agent_init();
207         cfs_symbol_init();
208
209         spin_lock_init(&trace_cpu_serializer);
210
211         return 0;
212 }
213
214 void libcfs_arch_cleanup(void)
215 {
216         spin_lock_done(&trace_cpu_serializer);
217
218         cfs_symbol_fini();
219         cfs_thread_agent_fini();
220         cfs_mem_fini();
221         cfs_sysctl_fini();
222         cfs_sync_fini();
223 }