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