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