Whamcloud - gitweb
land b1_5 onto HEAD
[fs/lustre-release.git] / lustre / obdclass / darwin / darwin-module.c
1 #define DEBUG_SUBSYSTEM S_CLASS
2 #ifndef EXPORT_SYMTAB
3 # define EXPORT_SYMTAB
4 #endif
5
6 #include <mach/mach_types.h>
7 #include <string.h>
8 #include <sys/file.h>
9 #include <sys/conf.h>
10 #include <miscfs/devfs/devfs.h>
11
12 #include <libcfs/libcfs.h>
13 #include <obd_support.h>
14 #include <obd_class.h>
15 #include <lprocfs_status.h>
16
17 #ifndef OBD_MAX_IOCTL_BUFFER
18 #define OBD_MAX_IOCTL_BUFFER 8192
19 #endif
20
21 /* buffer MUST be at least the size of obd_ioctl_hdr */
22 int obd_ioctl_getdata(char **buf, int *len, void *arg)
23 {
24         struct obd_ioctl_hdr *hdr;
25         struct obd_ioctl_data *data;
26         int err = 0;
27         int offset = 0;
28         ENTRY;
29
30         hdr = (struct obd_ioctl_hdr *)arg;
31         if (hdr->ioc_version != OBD_IOCTL_VERSION) {
32                 CERROR("Version mismatch kernel vs application\n");
33                 RETURN(-EINVAL);
34         }
35
36         if (hdr->ioc_len > OBD_MAX_IOCTL_BUFFER) {
37                 CERROR("User buffer len %d exceeds %d max buffer\n",
38                        hdr->ioc_len, OBD_MAX_IOCTL_BUFFER);
39                 RETURN(-EINVAL);
40         }
41
42         if (hdr->ioc_len < sizeof(struct obd_ioctl_data)) {
43                 CERROR("OBD: user buffer too small for ioctl (%d)\n", hdr->ioc_len);
44                 RETURN(-EINVAL);
45         }
46
47         /* XXX allocate this more intelligently, using kmalloc when
48          * appropriate */
49         OBD_VMALLOC(*buf, hdr->ioc_len);
50         if (*buf == NULL) {
51                 CERROR("Cannot allocate control buffer of len %d\n",
52                        hdr->ioc_len);
53                 RETURN(-EINVAL);
54         }
55         *len = hdr->ioc_len;
56         data = (struct obd_ioctl_data *)*buf;
57
58         bzero(data, hdr->ioc_len);
59         memcpy(data, (void *)arg, sizeof(struct obd_ioctl_data));
60         if (data->ioc_inlbuf1)
61                 err = copy_from_user(&data->ioc_bulk[0], (void *)data->ioc_inlbuf1,
62                                      hdr->ioc_len - ((void *)&data->ioc_bulk[0] - (void *)data));
63
64         if (obd_ioctl_is_invalid(data)) {
65                 CERROR("ioctl not correctly formatted\n");
66                 return -EINVAL;
67         }
68
69         if (data->ioc_inllen1) {
70                 data->ioc_inlbuf1 = &data->ioc_bulk[0];
71                 offset += size_round(data->ioc_inllen1);
72         }
73
74         if (data->ioc_inllen2) {
75                 data->ioc_inlbuf2 = &data->ioc_bulk[0] + offset;
76                 offset += size_round(data->ioc_inllen2);
77         }
78
79         if (data->ioc_inllen3) {
80                 data->ioc_inlbuf3 = &data->ioc_bulk[0] + offset;
81                 offset += size_round(data->ioc_inllen3);
82         }
83
84         if (data->ioc_inllen4) {
85                 data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset;
86         }
87
88         EXIT;
89         return 0;
90 }
91
92 int obd_ioctl_popdata(void *arg, void *data, int len)
93 {
94         /* 
95          * Xnu ioctl copyout(uaddr, arg, sizeof(struct obd_ioctl_data)),
96          * we have to copyout data exceed sizeof(struct obd_ioctl_data)
97          * by ourself.
98          */
99         if (len <= sizeof(struct obd_ioctl_data)) {
100                 memcpy(arg, data, len);
101                 return 0;
102         } else {
103                 int err;
104                 struct obd_ioctl_data *u = (struct obd_ioctl_data *)arg;
105                 struct obd_ioctl_data *k = (struct obd_ioctl_data *)data;
106                 err = copy_to_user((void *)u->ioc_inlbuf1, &k->ioc_bulk[0],
107                                     len -((void *)&k->ioc_bulk[0] -(void *)k));
108                 memcpy(arg, data, sizeof(struct obd_ioctl_data));
109                 return err;
110         }
111 }
112 /*
113  * cfs pseudo device
114  */
115 extern struct cfs_psdev_ops          obd_psdev_ops;
116
117 static int
118 obd_class_open(dev_t dev, int flags, int devtype, struct proc *p)
119 {
120         if (obd_psdev_ops.p_open != NULL)
121                 return -obd_psdev_ops.p_open(0, NULL);
122         return EPERM;
123 }
124
125 /*  closing /dev/obd */
126 static int
127 obd_class_release(dev_t dev, int flags, int mode, struct proc *p)
128 {
129         if (obd_psdev_ops.p_close != NULL)
130                 return -obd_psdev_ops.p_close(0, NULL);
131         return EPERM;
132 }
133
134 static int
135 obd_class_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
136 {
137         int err = 0;
138         ENTRY;
139
140         if (!is_suser())
141                 RETURN (EPERM);
142         if (obd_psdev_ops.p_ioctl != NULL)
143                 err = -obd_psdev_ops.p_ioctl(NULL, cmd, (void *)arg);
144         else
145                 err = EPERM;
146
147         RETURN(err);
148 }
149
150 static struct cdevsw obd_psdevsw = {
151         obd_class_open,
152         obd_class_release,
153         NULL,
154         NULL,
155         obd_class_ioctl,
156         NULL,
157         NULL,
158         NULL,
159         NULL,
160         NULL,
161         NULL,
162         NULL,
163         NULL,
164 };
165
166 cfs_psdev_t obd_psdev = {
167         -1,
168         NULL,
169         "obd",
170         &obd_psdevsw
171 };
172
173 int class_procfs_init(void)
174 {
175         return 0;
176 }
177
178 int class_procfs_clean(void)
179 {
180         return 0;
181 }