Whamcloud - gitweb
Changes to request processing:
[fs/lustre-release.git] / lustre / osc / osc_request.c
1 /*
2  * Copryright (C) 2001 Cluster File Systems, Inc.
3  *
4  */
5
6 #define EXPORT_SYMTAB
7
8 #include <linux/config.h>
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/mm.h>
12 #include <linux/string.h>
13 #include <linux/stat.h>
14 #include <linux/errno.h>
15 #include <linux/locks.h>
16 #include <linux/unistd.h>
17
18 #include <asm/system.h>
19 #include <asm/uaccess.h>
20
21 #include <linux/fs.h>
22 #include <linux/stat.h>
23 #include <asm/uaccess.h>
24 #include <linux/vmalloc.h>
25 #include <asm/segment.h>
26 #include <linux/miscdevice.h>
27
28 #include <linux/obd_support.h>
29 #include <linux/obd_class.h>
30 #include <linux/lustre_lib.h>
31 #include <linux/lustre_idl.h>
32
33 extern int ost_queue_req(struct obd_device *, struct ptlrpc_request *);
34
35 struct ptlrpc_request *ost_prep_req(int opcode, int buflen1, char *buf1, 
36                                  int buflen2, char *buf2)
37 {
38         struct ptlrpc_request *request;
39         int rc;
40         ENTRY; 
41
42         request = (struct ptlrpc_request *)kmalloc(sizeof(*request), GFP_KERNEL); 
43         if (!request) { 
44                 printk("osc_prep_req: request allocation out of memory\n");
45                 return NULL;
46         }
47
48         rc = ost_pack_req(buf1, buflen1,  buf2, buflen2,
49                           &request->rq_reqhdr, &request->rq_req.ost, 
50                           &request->rq_reqlen, &request->rq_reqbuf);
51         if (rc) { 
52                 printk("llight request: cannot pack request %d\n", rc); 
53                 return NULL;
54         }
55         request->rq_reqhdr->opc = opcode;
56
57         EXIT;
58         return request;
59 }
60
61 extern int osc_queue_wait(struct obd_conn *conn, struct ptlrpc_request *req)
62 {
63         struct obd_device *client = conn->oc_dev;
64         struct obd_device *target = client->u.osc.osc_tgt;
65         int rc;
66
67         ENTRY;
68         /* set the connection id */
69         req->rq_req.ost->connid = conn->oc_id;
70
71         CDEBUG(D_INODE, "tgt at %p, conn id %d, opcode %d request at: %p\n", 
72                &conn->oc_dev->u.osc.osc_tgt->u.ost, 
73                conn->oc_id, req->rq_reqhdr->opc, req);
74
75         /* XXX fix the race here (wait_for_event?)*/
76         /* hand the packet over to the server */
77         rc =  ost_queue_req(target, req); 
78         if (rc) { 
79                 printk("osc_queue_wait: error %d, opcode %d\n", rc, 
80                        req->rq_reqhdr->opc); 
81                 return -rc;
82         }
83
84         /* wait for the reply */
85         init_waitqueue_head(&req->rq_wait_for_rep);
86         interruptible_sleep_on(&req->rq_wait_for_rep);
87
88         ost_unpack_rep(req->rq_repbuf, req->rq_replen, &req->rq_rephdr, 
89                        &req->rq_rep.ost); 
90         printk("-->osc_queue_wait: buf %p len %d status %d\n", 
91                req->rq_repbuf, req->rq_replen, req->rq_rephdr->status); 
92
93         EXIT;
94         return req->rq_rephdr->status;
95 }
96
97 void osc_free_req(struct ptlrpc_request *request)
98 {
99         if (request->rq_repbuf)
100                 kfree(request->rq_repbuf);
101         kfree(request);
102 }
103
104
105 int osc_connect(struct obd_conn *conn)
106 {
107         struct ptlrpc_request *request;
108         int rc; 
109         ENTRY;
110         
111         request = ost_prep_req(OST_CONNECT, 0, NULL, 0, NULL);
112         if (!request) { 
113                 printk("osc_connect: cannot pack req!\n"); 
114                 return -ENOMEM;
115         }
116
117         rc = osc_queue_wait(conn, request);
118         if (rc) { 
119                 EXIT;
120                 goto out;
121         }
122       
123         CDEBUG(D_INODE, "received connid %d\n", request->rq_rep.ost->connid); 
124
125         conn->oc_id = request->rq_rep.ost->connid;
126  out:
127         osc_free_req(request);
128         EXIT;
129         return rc;
130 }
131
132 int osc_disconnect(struct obd_conn *conn)
133 {
134         struct ptlrpc_request *request;
135         int rc; 
136         ENTRY;
137         
138         request = ost_prep_req(OST_DISCONNECT, 0, NULL, 0, NULL);
139         if (!request) { 
140                 printk("osc_connect: cannot pack req!\n"); 
141                 return -ENOMEM;
142         }
143
144         rc = osc_queue_wait(conn, request);
145         if (rc) { 
146                 EXIT;
147                 goto out;
148         }
149  out:
150         osc_free_req(request);
151         EXIT;
152         return rc;
153 }
154
155
156 int osc_getattr(struct obd_conn *conn, struct obdo *oa)
157 {
158         struct ptlrpc_request *request;
159         int rc; 
160
161         request = ost_prep_req(OST_GETATTR, 0, NULL, 0, NULL);
162         if (!request) { 
163                 printk("osc_connect: cannot pack req!\n"); 
164                 return -ENOMEM;
165         }
166         
167         memcpy(&request->rq_req.ost->oa, oa, sizeof(*oa));
168         request->rq_req.ost->oa.o_valid = ~0;
169         
170         rc = osc_queue_wait(conn, request);
171         if (rc) { 
172                 EXIT;
173                 goto out;
174         }
175
176         CDEBUG(D_INODE, "mode: %o\n", request->rq_rep.ost->oa.o_mode); 
177         if (oa) { 
178                 memcpy(oa, &request->rq_rep.ost->oa, sizeof(*oa));
179         }
180
181  out:
182         osc_free_req(request);
183         return 0;
184 }
185
186 int osc_create(struct obd_conn *conn, struct obdo *oa)
187 {
188         struct ptlrpc_request *request;
189         int rc; 
190
191         if (!oa) { 
192                 printk(__FUNCTION__ ": oa NULL\n"); 
193         }
194         request = ost_prep_req(OST_CREATE, 0, NULL, 0, NULL);
195         if (!request) { 
196                 printk("osc_connect: cannot pack req!\n"); 
197                 return -ENOMEM;
198         }
199         
200         memcpy(&request->rq_req.ost->oa, oa, sizeof(*oa));
201         request->rq_req.ost->oa.o_valid = ~0;
202         
203         rc = osc_queue_wait(conn, request);
204         if (rc) { 
205                 EXIT;
206                 goto out;
207         }
208         memcpy(oa, &request->rq_rep.ost->oa, sizeof(*oa));
209
210  out:
211         osc_free_req(request);
212         return 0;
213 }
214
215
216 /* mount the file system (secretly) */
217 static int osc_setup(struct obd_device *obddev, obd_count len,
218                         void *buf)
219                         
220 {
221         struct obd_ioctl_data* data = buf;
222         struct osc_obd *osc = &obddev->u.osc;
223         ENTRY;
224
225         if (data->ioc_dev  < 0 || data->ioc_dev > MAX_OBD_DEVICES) { 
226                 EXIT;
227                 return -ENODEV;
228         }
229
230         osc->osc_tgt = &obd_dev[data->ioc_dev];
231         printk("OSC: tgt %d ost at %p\n", data->ioc_dev, &osc->osc_tgt->u.ost); 
232         if ( ! (osc->osc_tgt->obd_flags & OBD_ATTACHED) || 
233              ! (osc->osc_tgt->obd_flags & OBD_SET_UP) ){
234                 printk("device not attached or not set up (%d)\n", 
235                        data->ioc_dev);
236                 EXIT;
237                 return -EINVAL;
238         } 
239
240         MOD_INC_USE_COUNT;
241         EXIT; 
242         return 0;
243
244
245 void osc_sendpage(struct niobuf *dst, struct niobuf *src)
246 {
247         memcpy((char *)(unsigned long)dst->addr,  
248                (char *)(unsigned long)src->addr, 
249                src->len);
250         return;
251 }
252
253
254 int osc_brw(int rw, struct obd_conn *conn, obd_count num_oa,
255               struct obdo **oa, obd_count *oa_bufs, struct page **buf,
256               obd_size *count, obd_off *offset, obd_flag *flags)
257 {
258         struct ptlrpc_request *request;
259         int rc; 
260         struct obd_ioobj ioo;
261         struct niobuf src;
262         int size1, size2 = 0; 
263         void *ptr1, *ptr2;
264         int i, j, n;
265
266         size1 = num_oa * sizeof(ioo); 
267         for (i = 0; i < num_oa; i++) { 
268                 size2 += oa_bufs[i] * sizeof(src);
269         }
270
271         request = ost_prep_req(OST_PREPW, size1, NULL, size2, NULL);
272         if (!request) { 
273                 printk("osc_connect: cannot pack req!\n"); 
274                 return -ENOMEM;
275         }
276
277         n = 0;
278         ptr1 = ost_req_buf1(request->rq_req.ost);
279         ptr2 = ost_req_buf2(request->rq_req.ost);
280         for (i=0; i < num_oa; i++) { 
281                 ost_pack_ioo(&ptr1, oa[i], oa_bufs[i]); 
282                 for (j = 0 ; j < oa_bufs[i] ; j++) { 
283                         ost_pack_niobuf(&ptr2, kmap(buf[n]), offset[n],
284                                         count[n], flags[n]); 
285                         n++;
286                 }
287         }
288
289         rc = osc_queue_wait(conn, request);
290         if (rc) { 
291                 EXIT;
292                 goto out;
293         }
294
295         ptr2 = ost_rep_buf2(request->rq_rep.ost); 
296         if (request->rq_rep.ost->buflen2 != n * sizeof(struct niobuf)) { 
297                 printk(__FUNCTION__ ": buffer length wrong\n"); 
298                 goto out;
299         }
300
301         for (i=0; i < num_oa; i++) { 
302                 for (j = 0 ; j < oa_bufs[i] ; j++) { 
303                         struct niobuf *dst;
304                         src.addr = (__u64)(unsigned long)buf[n];
305                         src.len = count[n];
306                         ost_unpack_niobuf(&ptr2, &dst);
307                         osc_sendpage(dst, &src);
308                         n++;
309                 }
310         }
311         //ost_complete_brw(rep); 
312
313  out:
314         if (request->rq_rephdr)
315                 kfree(request->rq_rephdr);
316         n = 0;
317         for (i=0; i < num_oa; i++) { 
318                 for (j = 0 ; j < oa_bufs[i] ; j++) { 
319                         kunmap(buf[n]);
320                         n++;
321                 }
322         }
323
324         osc_free_req(request);
325         return 0;
326
327
328
329 }
330
331
332 static int osc_cleanup(struct obd_device * obddev)
333 {
334         ENTRY;
335
336         if ( !(obddev->obd_flags & OBD_SET_UP) ) {
337                 EXIT;
338                 return 0;
339         }
340
341         MOD_DEC_USE_COUNT;
342         EXIT;
343         return 0;
344 }
345
346
347 struct obd_ops osc_obd_ops = { 
348         o_setup:   osc_setup,
349         o_cleanup: osc_cleanup, 
350         o_create: osc_create,
351         o_getattr: osc_getattr,
352         o_connect: osc_connect,
353         o_disconnect: osc_disconnect
354 };
355
356 static int __init osc_init(void)
357 {
358         obd_register_type(&osc_obd_ops, LUSTRE_OSC_NAME);
359         return 0;
360 }
361
362 static void __exit osc_exit(void)
363 {
364         obd_unregister_type(LUSTRE_OSC_NAME);
365 }
366
367 MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
368 MODULE_DESCRIPTION("Lustre Object Storage Client (OSC) v1.0");
369 MODULE_LICENSE("GPL"); 
370
371 module_init(osc_init);
372 module_exit(osc_exit);
373