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