Whamcloud - gitweb
Small bug fixes. OSC/OST almost working.
[fs/lustre-release.git] / lustre / mds / handler.c
1 /*
2  *  linux/mds/handler.c
3  *  
4  *  Lustre Metadata Server (mds) request handler
5  * 
6  *  Copyright (C) 2001  Cluster File Systems, Inc.
7  *
8  *  This code is issued under the GNU General Public License.
9  *  See the file COPYING in this distribution
10  *
11  *  by Peter Braam <braam@clusterfs.com>
12  * 
13  *  This server is single threaded at present (but can easily be multi threaded). 
14  * 
15  */
16
17
18 #define EXPORT_SYMTAB
19
20 #include <linux/version.h>
21 #include <linux/module.h>
22 #include <linux/fs.h>
23 #include <linux/stat.h>
24 #include <linux/locks.h>
25 #include <linux/ext2_fs.h>
26 #include <linux/quotaops.h>
27 #include <asm/unistd.h>
28 #include <linux/obd_support.h>
29 #include <linux/obd.h>
30 #include <linux/lustre_lib.h>
31 #include <linux/lustre_idl.h>
32 #include <linux/lustre_mds.h>
33 #include <linux/obd_class.h>
34
35 // for testing
36 static struct mds_obd *MDS;
37
38 // XXX make this networked!  
39 static int mds_queue_req(struct mds_request *req)
40 {
41         struct mds_request *srv_request;
42         
43         if (!MDS) { 
44                 EXIT;
45                 return -1;
46         }
47
48         srv_request = kmalloc(sizeof(*srv_request), GFP_KERNEL);
49         if (!srv_request) { 
50                 EXIT;
51                 return -ENOMEM;
52         }
53
54         /* move the request buffer */
55         srv_request->rq_reqlen = req->rq_reqlen;
56         srv_request->rq_reqbuf = req->rq_reqbuf;
57         srv_request->rq_obd = MDS;
58
59         req->rq_reqbuf = NULL;
60         req->rq_reqlen = 0; 
61
62         /* remember where it came from */
63         srv_request->rq_reply_handle = req;
64
65         /* get the server working on this request */
66         spin_lock(&MDS->mds_lock); 
67         list_add(&srv_request->rq_list, &MDS->mds_reqs); 
68         spin_unlock(&MDS->mds_lock); 
69         wake_up(&MDS->mds_waitq);
70
71         /* put client asleep */
72         printk("-- sleeping\n");
73         interruptible_sleep_on(&req->rq_wait_for_rep);
74         printk("-- done\n");
75         return 0;
76 }
77
78 static struct dentry *mds_fid2dentry(struct mds_obd *mds, struct lustre_fid *fid)
79 {
80         struct dentry *de;
81         struct inode *inode;
82
83         inode = iget(mds->mds_sb, fid->id);
84         if (!inode) { 
85                 EXIT;
86         }
87
88         de = d_alloc_root(inode);
89         if (!de) { 
90                 iput(inode);
91                 EXIT;
92                 return NULL;
93         }
94
95         de->d_inode = inode;
96         return de;
97 }
98
99 int mds_getattr(struct mds_request *req)
100 {
101         struct dentry *de = mds_fid2dentry(req->rq_obd, &req->rq_req->fid1);
102         struct inode *inode;
103         struct mds_rep *rep;
104         int rc;
105         
106         rc = mds_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep, 
107                           &req->rq_replen, &req->rq_repbuf);
108         if (rc) { 
109                 EXIT;
110                 printk("mds: out of memory\n");
111                 req->rq_status = -ENOMEM;
112                 return -ENOMEM;
113         }
114
115         req->rq_rephdr->seqno = req->rq_reqhdr->seqno;
116         rep = req->rq_rep;
117
118         if (!de) { 
119                 EXIT;
120                 req->rq_rephdr->status = -ENOENT;
121                 return 0;
122         }
123
124         inode = de->d_inode;
125         rep->atime = inode->i_atime;
126         rep->ctime = inode->i_ctime;
127         rep->mtime = inode->i_mtime;
128         rep->uid = inode->i_uid;
129         rep->gid = inode->i_gid;
130         rep->size = inode->i_size;
131         rep->mode = inode->i_mode;
132
133         dput(de); 
134         return 0;
135 }
136
137 /* XXX replace with networking code */
138 int mds_reply(struct mds_request *req)
139 {
140         struct mds_request *clnt_req = req->rq_reply_handle;
141
142         ENTRY;
143
144         /* free the request buffer */
145         kfree(req->rq_reqbuf);
146         req->rq_reqbuf = NULL; 
147         
148         /* move the reply to the client */ 
149         clnt_req->rq_replen = req->rq_replen;
150         clnt_req->rq_repbuf = req->rq_repbuf;
151         req->rq_repbuf = NULL;
152         req->rq_replen = 0;
153
154         /* wake up the client */ 
155         wake_up_interruptible(&clnt_req->rq_wait_for_rep); 
156         EXIT;
157         return 0;
158 }
159
160 int mds_error(struct mds_request *req)
161 {
162         struct mds_rep_hdr *hdr;
163
164         ENTRY;
165         hdr = kmalloc(sizeof(*hdr), GFP_KERNEL);
166         if (!hdr) { 
167                 EXIT;
168                 return -ENOMEM;
169         }
170
171         memset(hdr, 0, sizeof(*hdr));
172         
173         hdr->seqno = req->rq_reqhdr->seqno;
174         hdr->status = req->rq_status; 
175         hdr->type = MDS_TYPE_ERR;
176
177         req->rq_repbuf = (char *)hdr;
178         req->rq_replen = sizeof(*hdr); 
179
180         EXIT;
181         return mds_reply(req);
182 }
183
184 //int mds_handle(struct mds_conn *conn, int len, char *buf)
185 int mds_handle(struct mds_request *req)
186 {
187         int rc;
188         struct mds_req_hdr *hdr;
189
190         ENTRY;
191
192         hdr = (struct mds_req_hdr *)req->rq_reqbuf;
193
194         if (NTOH__u32(hdr->type) != MDS_TYPE_REQ) {
195                 printk("lustre_mds: wrong packet type sent %d\n",
196                        NTOH__u32(hdr->type));
197                 rc = -EINVAL;
198                 goto out;
199         }
200
201         rc = mds_unpack_req(req->rq_reqbuf, req->rq_reqlen, 
202                             &req->rq_reqhdr, &req->rq_req);
203         if (rc) { 
204                 printk("lustre_mds: Invalid request\n");
205                 EXIT; 
206                 goto out;
207         }
208
209         switch (req->rq_reqhdr->opc) { 
210
211         case MDS_GETATTR:
212                 CDEBUG(D_INODE, "getattr\n");
213                 rc = mds_getattr(req);
214                 break;
215
216         case MDS_OPEN:
217                 return mds_getattr(req);
218
219         case MDS_SETATTR:
220                 return mds_getattr(req);
221
222         case MDS_CREATE:
223                 return mds_getattr(req);
224
225         case MDS_MKDIR:
226                 return mds_getattr(req);
227
228         case MDS_RMDIR:
229                 return mds_getattr(req);
230
231         case MDS_SYMLINK:
232                 return mds_getattr(req);
233  
234         case MDS_LINK:
235                 return mds_getattr(req);
236   
237         case MDS_MKNOD:
238                 return mds_getattr(req);
239
240         case MDS_UNLINK:
241                 return mds_getattr(req);
242
243         case MDS_RENAME:
244                 return mds_getattr(req);
245
246         default:
247                 return mds_error(req);
248         }
249
250 out:
251         if (rc) { 
252                 printk("mds: processing error %d\n", rc);
253                 mds_error(req);
254         } else { 
255                 CDEBUG(D_INODE, "sending reply\n"); 
256                 mds_reply(req); 
257         }
258
259         return 0;
260 }
261
262
263 static void mds_timer_run(unsigned long __data)
264 {
265         struct task_struct * p = (struct task_struct *) __data;
266
267         wake_up_process(p);
268 }
269
270 int mds_main(void *arg)
271 {
272         struct mds_obd *mds = (struct mds_obd *) arg;
273         struct timer_list timer;
274
275         lock_kernel();
276         daemonize();
277         spin_lock_irq(&current->sigmask_lock);
278         sigfillset(&current->blocked);
279         recalc_sigpending(current);
280         spin_unlock_irq(&current->sigmask_lock);
281
282         sprintf(current->comm, "lustre_mds");
283
284         /* Set up an interval timer which can be used to trigger a
285            wakeup after the interval expires */
286         init_timer(&timer);
287         timer.data = (unsigned long) current;
288         timer.function = mds_timer_run;
289         mds->mds_timer = &timer;
290
291         /* Record that the  thread is running */
292         mds->mds_thread = current;
293         wake_up(&mds->mds_done_waitq); 
294
295         printk(KERN_INFO "lustre_mds starting.  Commit interval %d seconds\n",
296                         mds->mds_interval / HZ);
297
298         /* XXX maintain a list of all managed devices: insert here */
299
300         /* And now, wait forever for commit wakeup events. */
301         while (1) {
302                 struct mds_request *request;
303                 int rc; 
304
305                 if (mds->mds_flags & MDS_UNMOUNT)
306                         break;
307
308
309                 wake_up(&mds->mds_done_waitq);
310                 interruptible_sleep_on(&mds->mds_waitq);
311
312                 CDEBUG(D_INODE, "lustre_mds wakes\n");
313                 CDEBUG(D_INODE, "pick up req here and continue\n"); 
314
315                 if (list_empty(&mds->mds_reqs)) { 
316                         CDEBUG(D_INODE, "woke because of timer\n"); 
317                 } else { 
318                         request = list_entry(mds->mds_reqs.next, 
319                                              struct mds_request, rq_list);
320                         list_del(&request->rq_list);
321                         rc = mds_handle(request); 
322                 }
323         }
324
325         del_timer_sync(mds->mds_timer);
326
327         /* XXX maintain a list of all managed devices: cleanup here */
328
329         mds->mds_thread = NULL;
330         wake_up(&mds->mds_done_waitq);
331         printk("lustre_mds: exiting\n");
332         return 0;
333 }
334
335 static void mds_stop_srv_thread(struct mds_obd *mds)
336 {
337         mds->mds_flags |= MDS_UNMOUNT;
338
339         while (mds->mds_thread) {
340                 wake_up(&mds->mds_waitq);
341                 sleep_on(&mds->mds_done_waitq);
342         }
343 }
344
345 static void mds_start_srv_thread(struct mds_obd *mds)
346 {
347         init_waitqueue_head(&mds->mds_waitq);
348         init_waitqueue_head(&mds->mds_done_waitq);
349         kernel_thread(mds_main, (void *)mds, 
350                       CLONE_VM | CLONE_FS | CLONE_FILES);
351         while (!mds->mds_thread) 
352                 sleep_on(&mds->mds_done_waitq);
353 }
354
355 /* mount the file system (secretly) */
356 static int mds_setup(struct obd_device *obddev, obd_count len,
357                         void *buf)
358                         
359 {
360         struct obd_ioctl_data* data = buf;
361         struct mds_obd *mds = &obddev->u.mds;
362         struct vfsmount *mnt;
363         int err; 
364         ENTRY;
365         
366         mnt = do_kern_mount(data->ioc_inlbuf2, 0, 
367                             data->ioc_inlbuf1, NULL); 
368         err = PTR_ERR(mnt);
369         if (IS_ERR(mnt)) { 
370                 EXIT;
371                 return err;
372         }
373
374         mds->mds_sb = mnt->mnt_root->d_inode->i_sb;
375         if (!obddev->u.mds.mds_sb) {
376                 EXIT;
377                 return -ENODEV;
378         }
379
380         INIT_LIST_HEAD(&mds->mds_reqs);
381         mds->mds_thread = NULL;
382         mds->mds_flags = 0;
383         mds->mds_interval = 3 * HZ;
384         mds->mds_vfsmnt = mnt;
385         obddev->u.mds.mds_fstype = strdup(data->ioc_inlbuf2);
386
387         mds->mds_ctxt.pwdmnt = mnt;
388         mds->mds_ctxt.pwd = mnt->mnt_root;
389         mds->mds_ctxt.fs = KERNEL_DS;
390         MDS = mds;
391
392         spin_lock_init(&obddev->u.mds.fo_lock);
393
394         mds_start_srv_thread(mds);
395
396         MOD_INC_USE_COUNT;
397         EXIT; 
398         return 0;
399
400
401 static int mds_cleanup(struct obd_device * obddev)
402 {
403         struct super_block *sb;
404         struct mds_obd *mds = &obddev->u.mds;
405
406         ENTRY;
407
408         if ( !(obddev->obd_flags & OBD_SET_UP) ) {
409                 EXIT;
410                 return 0;
411         }
412
413         if ( !list_empty(&obddev->obd_gen_clients) ) {
414                 printk(KERN_WARNING __FUNCTION__ ": still has clients!\n");
415                 EXIT;
416                 return -EBUSY;
417         }
418
419         MDS = NULL;
420         mds_stop_srv_thread(mds);
421         sb = mds->mds_sb;
422         if (!mds->mds_sb){
423                 EXIT;
424                 return 0;
425         }
426
427         if (!list_empty(&mds->mds_reqs)) {
428                 // XXX reply with errors and clean up
429                 CDEBUG(D_INODE, "Request list not empty!\n");
430         }
431
432         unlock_kernel();
433         mntput(mds->mds_vfsmnt); 
434         mds->mds_sb = 0;
435         kfree(mds->mds_fstype);
436         lock_kernel();
437         
438
439         MOD_DEC_USE_COUNT;
440         EXIT;
441         return 0;
442 }
443
444 /* use obd ops to offer management infrastructure */
445 static struct obd_ops mds_obd_ops = {
446         o_setup:       mds_setup,
447         o_cleanup:     mds_cleanup,
448 };
449
450 static int __init mds_init(void)
451 {
452         obd_register_type(&mds_obd_ops, LUSTRE_MDS_NAME);
453         return 0;
454 }
455
456 static void __exit mds_exit(void)
457 {
458         obd_unregister_type(LUSTRE_MDS_NAME);
459 }
460
461 MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
462 MODULE_DESCRIPTION("Lustre Metadata Server (MDS) v0.01");
463 MODULE_LICENSE("GPL");
464
465
466 // for testing (maybe this stays)
467 EXPORT_SYMBOL(mds_queue_req);
468
469 module_init(mds_init);
470 module_exit(mds_exit);