Whamcloud - gitweb
class/class_obd.c: small OBD_ATTACHED sanity cleanup; OBD_SET_UP fix.
[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 /* FIXME: this belongs in some sort of service struct */
36 static int osc_xid = 1;
37
38 struct ptlrpc_request *ost_prep_req(int opcode, int buflen1, char *buf1, 
39                                  int buflen2, char *buf2)
40 {
41         struct ptlrpc_request *request;
42         int rc;
43         ENTRY; 
44
45         request = (struct ptlrpc_request *)kmalloc(sizeof(*request), GFP_KERNEL); 
46         if (!request) { 
47                 printk("osc_prep_req: request allocation out of memory\n");
48                 return NULL;
49         }
50
51         memset(request, 0, sizeof(*request));
52         request->rq_xid = osc_xid++;
53
54         rc = ost_pack_req(buf1, buflen1,  buf2, buflen2,
55                           &request->rq_reqhdr, &request->rq_req.ost, 
56                           &request->rq_reqlen, &request->rq_reqbuf);
57         if (rc) { 
58                 printk("llight request: cannot pack request %d\n", rc); 
59                 return NULL;
60         }
61         request->rq_reqhdr->opc = opcode;
62
63         EXIT;
64         return request;
65 }
66
67 /* XXX: unify with mdc_queue_wait */
68 extern int osc_queue_wait(struct obd_conn *conn, struct ptlrpc_request *req)
69 {
70         struct obd_device *client = conn->oc_dev;
71         struct lustre_peer *peer = &conn->oc_dev->u.osc.osc_peer;
72         int rc;
73
74         ENTRY;
75
76         /* set the connection id */
77         req->rq_req.ost->connid = conn->oc_id;
78
79         /* XXX fix the race here (wait_for_event?)*/
80         if (peer == NULL) {
81                 /* Local delivery */
82                 CDEBUG(D_INODE, "\n");
83                 rc = ost_queue_req(client, req); 
84         } else {
85                 /* Remote delivery via portals. */
86                 req->rq_req_portal = OST_REQUEST_PORTAL;
87                 req->rq_reply_portal = OST_REPLY_PORTAL;
88                 rc = ptl_send_rpc(req, peer);
89         }
90         if (rc) { 
91                 printk(__FUNCTION__ ": error %d, opcode %d\n", rc, 
92                        req->rq_reqhdr->opc); 
93                 return -rc;
94         }
95
96         CDEBUG(D_INODE, "tgt at %p, conn id %d, opcode %d request at: %p\n", 
97                &conn->oc_dev->u.osc.osc_tgt->u.ost, 
98                conn->oc_id, req->rq_reqhdr->opc, req);
99
100         /* wait for the reply */
101         init_waitqueue_head(&req->rq_wait_for_rep);
102         CDEBUG(D_INODE, "-- sleeping\n");
103         interruptible_sleep_on(&req->rq_wait_for_rep);
104         CDEBUG(D_INODE, "-- done\n");
105
106         rc = ost_unpack_rep(req->rq_repbuf, req->rq_replen, &req->rq_rephdr, 
107                             &req->rq_rep.ost); 
108         if (rc) {
109                 printk(__FUNCTION__ ": mds_unpack_rep failed: %d\n", rc);
110                 return rc;
111         }
112
113         if ( req->rq_rephdr->status == 0 )
114                 CDEBUG(D_INODE, "buf %p len %d status %d\n", 
115                        req->rq_repbuf, req->rq_replen, 
116                        req->rq_rephdr->status); 
117
118         EXIT;
119         return 0;
120 }
121
122 void osc_free_req(struct ptlrpc_request *request)
123 {
124         kfree(request);
125 }
126
127 int osc_connect(struct obd_conn *conn)
128 {
129         struct ptlrpc_request *request;
130         int rc; 
131         ENTRY;
132         
133         request = ost_prep_req(OST_CONNECT, 0, NULL, 0, NULL);
134         if (!request) { 
135                 printk(__FUNCTION__ ": cannot pack req!\n"); 
136                 return -ENOMEM;
137         }
138
139         request->rq_replen = 
140                 sizeof(struct ptlrep_hdr) + sizeof(struct ost_rep);
141
142         rc = osc_queue_wait(conn, request);
143         if (rc) { 
144                 EXIT;
145                 goto out;
146         }
147       
148         CDEBUG(D_INODE, "received connid %d\n", request->rq_rep.ost->connid); 
149
150         conn->oc_id = request->rq_rep.ost->connid;
151  out:
152         osc_free_req(request);
153         EXIT;
154         return rc;
155 }
156
157 int osc_disconnect(struct obd_conn *conn)
158 {
159         struct ptlrpc_request *request;
160         int rc; 
161         ENTRY;
162         
163         request = ost_prep_req(OST_DISCONNECT, 0, NULL, 0, NULL);
164         if (!request) { 
165                 printk(__FUNCTION__ ": cannot pack req!\n"); 
166                 return -ENOMEM;
167         }
168
169         request->rq_replen = 
170                 sizeof(struct ptlrep_hdr) + sizeof(struct ost_rep);
171
172         rc = osc_queue_wait(conn, request);
173         if (rc) { 
174                 EXIT;
175                 goto out;
176         }
177  out:
178         osc_free_req(request);
179         EXIT;
180         return rc;
181 }
182
183
184 int osc_getattr(struct obd_conn *conn, struct obdo *oa)
185 {
186         struct ptlrpc_request *request;
187         int rc; 
188
189         request = ost_prep_req(OST_GETATTR, 0, NULL, 0, NULL);
190         if (!request) { 
191                 printk(__FUNCTION__ ": cannot pack req!\n"); 
192                 return -ENOMEM;
193         }
194         
195         memcpy(&request->rq_req.ost->oa, oa, sizeof(*oa));
196         request->rq_req.ost->oa.o_valid = ~0;
197         request->rq_replen = 
198                 sizeof(struct ptlrep_hdr) + sizeof(struct ost_rep);
199         
200         rc = osc_queue_wait(conn, request);
201         if (rc) { 
202                 EXIT;
203                 goto out;
204         }
205
206         CDEBUG(D_INODE, "mode: %o\n", request->rq_rep.ost->oa.o_mode); 
207         if (oa) { 
208                 memcpy(oa, &request->rq_rep.ost->oa, sizeof(*oa));
209         }
210
211  out:
212         osc_free_req(request);
213         return 0;
214 }
215
216 int osc_setattr(struct obd_conn *conn, struct obdo *oa)
217 {
218         struct ptlrpc_request *request;
219         int rc; 
220
221         request = ost_prep_req(OST_SETATTR, 0, NULL, 0, NULL);
222         if (!request) { 
223                 printk(__FUNCTION__ ": cannot pack req!\n"); 
224                 return -ENOMEM;
225         }
226         
227         memcpy(&request->rq_req.ost->oa, oa, sizeof(*oa));
228         request->rq_replen = 
229                 sizeof(struct ptlrep_hdr) + sizeof(struct ost_rep);
230         
231         rc = osc_queue_wait(conn, request);
232         if (rc) { 
233                 EXIT;
234                 goto out;
235         }
236
237  out:
238         osc_free_req(request);
239         return 0;
240 }
241
242 int osc_create(struct obd_conn *conn, struct obdo *oa)
243 {
244         struct ptlrpc_request *request;
245         int rc; 
246
247         if (!oa) { 
248                 printk(__FUNCTION__ ": oa NULL\n"); 
249         }
250         request = ost_prep_req(OST_CREATE, 0, NULL, 0, NULL);
251         if (!request) { 
252                 printk("osc_connect: cannot pack req!\n"); 
253                 return -ENOMEM;
254         }
255         
256         memcpy(&request->rq_req.ost->oa, oa, sizeof(*oa));
257         request->rq_req.ost->oa.o_valid = ~0;
258         request->rq_replen = 
259                 sizeof(struct ptlrep_hdr) + sizeof(struct ost_rep);
260         
261         rc = osc_queue_wait(conn, request);
262         if (rc) { 
263                 EXIT;
264                 goto out;
265         }
266         memcpy(oa, &request->rq_rep.ost->oa, sizeof(*oa));
267
268  out:
269         osc_free_req(request);
270         return 0;
271 }
272
273
274 /* mount the file system (secretly) */
275 static int osc_setup(struct obd_device *obddev, obd_count len,
276                         void *buf)
277                         
278 {
279         struct obd_ioctl_data* data = buf;
280         struct osc_obd *osc = &obddev->u.osc;
281         ENTRY;
282
283         if (data->ioc_dev >= 0 && data->ioc_dev < MAX_OBD_DEVICES) {
284                 /* This is a local connection */
285                 osc->osc_tgt = &obd_dev[data->ioc_dev];
286
287                 printk("OSC: tgt %d ost at %p\n", data->ioc_dev,
288                        &osc->osc_tgt->u.ost);
289                 if ( ! (osc->osc_tgt->obd_flags & OBD_ATTACHED) || 
290                      ! (osc->osc_tgt->obd_flags & OBD_SET_UP) ){
291                         printk("device not attached or not set up (%d)\n", 
292                                data->ioc_dev);
293                         EXIT;
294                         return -EINVAL;
295                 }
296         } else {
297                 int err;
298                 /* This is a remote connection using Portals */
299
300                 /* XXX: this should become something like ioc_inlbuf1 */
301                 err = kportal_uuid_to_peer("ost", &osc->osc_peer);
302                 if (err != 0) {
303                         printk("Cannot find 'ost' peer.\n");
304                         EXIT;
305                         return -EINVAL;
306                 }
307         }
308
309         MOD_INC_USE_COUNT;
310         EXIT;
311         return 0;
312
313
314 void osc_sendpage(struct niobuf *dst, struct niobuf *src)
315 {
316         memcpy((char *)(unsigned long)dst->addr,  
317                (char *)(unsigned long)src->addr, 
318                src->len);
319         return;
320 }
321
322
323 int osc_brw(int rw, struct obd_conn *conn, obd_count num_oa,
324               struct obdo **oa, obd_count *oa_bufs, struct page **buf,
325               obd_size *count, obd_off *offset, obd_flag *flags)
326 {
327         struct ptlrpc_request *request;
328         int rc; 
329         struct obd_ioobj ioo;
330         struct niobuf src;
331         int size1, size2 = 0; 
332         void *ptr1, *ptr2;
333         int i, j, n;
334
335         size1 = num_oa * sizeof(ioo); 
336         for (i = 0; i < num_oa; i++) { 
337                 size2 += oa_bufs[i] * sizeof(src);
338         }
339
340         request = ost_prep_req(OST_PREPW, size1, NULL, size2, NULL);
341         if (!request) { 
342                 printk("osc_connect: cannot pack req!\n"); 
343                 return -ENOMEM;
344         }
345
346         n = 0;
347         ptr1 = ost_req_buf1(request->rq_req.ost);
348         ptr2 = ost_req_buf2(request->rq_req.ost);
349         for (i=0; i < num_oa; i++) { 
350                 ost_pack_ioo(&ptr1, oa[i], oa_bufs[i]); 
351                 for (j = 0 ; j < oa_bufs[i] ; j++) { 
352                         ost_pack_niobuf(&ptr2, kmap(buf[n]), offset[n],
353                                         count[n], flags[n]); 
354                         n++;
355                 }
356         }
357
358         rc = osc_queue_wait(conn, request);
359         if (rc) { 
360                 EXIT;
361                 goto out;
362         }
363
364         ptr2 = ost_rep_buf2(request->rq_rep.ost); 
365         if (request->rq_rep.ost->buflen2 != n * sizeof(struct niobuf)) { 
366                 printk(__FUNCTION__ ": buffer length wrong\n"); 
367                 goto out;
368         }
369
370         for (i=0; i < num_oa; i++) { 
371                 for (j = 0 ; j < oa_bufs[i] ; j++) { 
372                         struct niobuf *dst;
373                         src.addr = (__u64)(unsigned long)buf[n];
374                         src.len = count[n];
375                         ost_unpack_niobuf(&ptr2, &dst);
376                         osc_sendpage(dst, &src);
377                         n++;
378                 }
379         }
380         //ost_complete_brw(rep); 
381
382  out:
383         if (request->rq_rephdr)
384                 kfree(request->rq_rephdr);
385         n = 0;
386         for (i=0; i < num_oa; i++) { 
387                 for (j = 0 ; j < oa_bufs[i] ; j++) { 
388                         kunmap(buf[n]);
389                         n++;
390                 }
391         }
392
393         osc_free_req(request);
394         return 0;
395 }
396
397 static int osc_cleanup(struct obd_device * obddev)
398 {
399         MOD_DEC_USE_COUNT;
400         return 0;
401 }
402
403 struct obd_ops osc_obd_ops = { 
404         o_setup:   osc_setup,
405         o_cleanup: osc_cleanup, 
406         o_create: osc_create,
407         o_getattr: osc_getattr,
408         o_setattr: osc_setattr,
409         o_connect: osc_connect,
410         o_disconnect: osc_disconnect
411 };
412
413 static int __init osc_init(void)
414 {
415         obd_register_type(&osc_obd_ops, LUSTRE_OSC_NAME);
416         return 0;
417 }
418
419 static void __exit osc_exit(void)
420 {
421         obd_unregister_type(LUSTRE_OSC_NAME);
422 }
423
424 MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
425 MODULE_DESCRIPTION("Lustre Object Storage Client (OSC) v1.0");
426 MODULE_LICENSE("GPL"); 
427
428 module_init(osc_init);
429 module_exit(osc_exit);
430