Whamcloud - gitweb
b=18751 Move prng.c to libcfs
[fs/lustre-release.git] / lustre / mds / handler.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/mds/handler.c
37  *
38  * Author: Peter Braam <braam@clusterfs.com>
39  * Author: Andreas Dilger <adilger@clusterfs.com>
40  * Author: Phil Schwan <phil@clusterfs.com>
41  * Author: Mike Shaver <shaver@clusterfs.com>
42  */
43
44 #define DEBUG_SUBSYSTEM S_MDS
45
46 #include <lustre_mds.h>
47 #include <linux/module.h>
48 #include <linux/init.h>
49 #include <linux/fs.h>
50 #include <linux/jbd.h>
51 #include <linux/smp_lock.h>
52 #include <linux/buffer_head.h>
53 #include <linux/workqueue.h>
54 #include <linux/mount.h>
55
56 #include <lustre_acl.h>
57 #include <obd_class.h>
58 #include <lustre_dlm.h>
59 #include <obd_lov.h>
60 #include <lustre_fsfilt.h>
61 #include <lprocfs_status.h>
62 #include <lustre_disk.h>
63 #include <lustre_param.h>
64
65 #include "mds_internal.h"
66
67 __u32 mds_max_ost_index=0xFFFF;
68 CFS_MODULE_PARM(mds_max_ost_index, "i", int, 0444,
69                 "maximal OST index");
70
71 /* Look up an entry by inode number. */
72 /* this function ONLY returns valid dget'd dentries with an initialized inode
73    or errors */
74 struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid,
75                               struct vfsmount **mnt)
76 {
77         char fid_name[32];
78         unsigned long ino = fid->id;
79         __u32 generation = fid->generation;
80         struct inode *inode;
81         struct dentry *result;
82
83         if (ino == 0)
84                 RETURN(ERR_PTR(-ESTALE));
85
86         snprintf(fid_name, sizeof(fid_name), "0x%lx", ino);
87
88         /* under ext3 this is neither supposed to return bad inodes
89            nor NULL inodes. */
90         result = ll_lookup_one_len(fid_name, mds->mds_fid_de, strlen(fid_name));
91         if (IS_ERR(result))
92                 RETURN(result);
93
94         inode = result->d_inode;
95         if (!inode)
96                 RETURN(ERR_PTR(-ENOENT));
97
98         if (inode->i_generation == 0 || inode->i_nlink == 0) {
99                 LCONSOLE_WARN("Found inode with zero generation or link -- this"
100                               " may indicate disk corruption (inode: %lu/%u, "
101                               "link %lu, count %d)\n", inode->i_ino,
102                               inode->i_generation,(unsigned long)inode->i_nlink,
103                               atomic_read(&inode->i_count));
104                 dput(result);
105                 RETURN(ERR_PTR(-ENOENT));
106         }
107
108         if (generation && inode->i_generation != generation) {
109                 /* we didn't find the right inode.. */
110                 CDEBUG(D_INODE, "found wrong generation: inode %lu, link: %lu, "
111                        "count: %d, generation %u/%u\n", inode->i_ino,
112                        (unsigned long)inode->i_nlink,
113                        atomic_read(&inode->i_count), inode->i_generation,
114                        generation);
115                 dput(result);
116                 RETURN(ERR_PTR(-ENOENT));
117         }
118
119         if (mnt) {
120                 *mnt = mds->mds_obt.obt_vfsmnt;
121                 mntget(*mnt);
122         }
123
124         RETURN(result);
125 }
126
127 static int mds_lov_presetup (struct mds_obd *mds, struct lustre_cfg *lcfg)
128 {
129         int rc = 0;
130         ENTRY;
131
132         if (lcfg->lcfg_bufcount >= 4 && LUSTRE_CFG_BUFLEN(lcfg, 3) > 0) {
133                 class_uuid_t uuid;
134
135                 ll_generate_random_uuid(uuid);
136                 class_uuid_unparse(uuid, &mds->mds_lov_uuid);
137
138                 OBD_ALLOC(mds->mds_profile, LUSTRE_CFG_BUFLEN(lcfg, 3));
139                 if (mds->mds_profile == NULL)
140                         RETURN(-ENOMEM);
141
142                 strncpy(mds->mds_profile, lustre_cfg_string(lcfg, 3),
143                         LUSTRE_CFG_BUFLEN(lcfg, 3));
144         }
145         RETURN(rc);
146 }
147
148 static int mds_lov_clean(struct obd_device *obd)
149 {
150         struct mds_obd *mds = &obd->u.mds;
151         struct obd_device *osc = mds->mds_lov_obd;
152         ENTRY;
153
154         if (mds->mds_profile) {
155                 class_del_profile(mds->mds_profile);
156                 OBD_FREE(mds->mds_profile, strlen(mds->mds_profile) + 1);
157                 mds->mds_profile = NULL;
158         }
159
160         /* There better be a lov */
161         if (!osc)
162                 RETURN(0);
163         if (IS_ERR(osc))
164                 RETURN(PTR_ERR(osc));
165
166         obd_register_observer(osc, NULL);
167
168         /* Give lov our same shutdown flags */
169         osc->obd_force = obd->obd_force;
170         osc->obd_fail = obd->obd_fail;
171
172         /* Cleanup the lov */
173         obd_disconnect(mds->mds_lov_exp);
174         class_manual_cleanup(osc);
175
176         RETURN(0);
177 }
178
179 static int mds_postsetup(struct obd_device *obd)
180 {
181         struct mds_obd *mds = &obd->u.mds;
182         struct llog_ctxt *ctxt;
183         int rc = 0;
184         ENTRY;
185
186         rc = llog_setup(obd, &obd->obd_olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
187                         &llog_lvfs_ops);
188         if (rc)
189                 RETURN(rc);
190
191         rc = llog_setup(obd, &obd->obd_olg, LLOG_LOVEA_ORIG_CTXT, obd, 0, NULL,
192                         &llog_lvfs_ops);
193         if (rc)
194                 GOTO(err_llog, rc);
195
196         mds_changelog_llog_init(obd, obd);
197
198         if (mds->mds_profile) {
199                 struct lustre_profile *lprof;
200                 /* The profile defines which osc and mdc to connect to, for a
201                    client.  We reuse that here to figure out the name of the
202                    lov to use (and ignore lprof->lp_md).
203                    The profile was set in the config log with
204                    LCFG_MOUNTOPT profilenm oscnm mdcnm */
205                 lprof = class_get_profile(mds->mds_profile);
206                 if (lprof == NULL) {
207                         CERROR("No profile found: %s\n", mds->mds_profile);
208                         GOTO(err_cleanup, rc = -ENOENT);
209                 }
210                 rc = mds_lov_connect(obd, lprof->lp_dt);
211                 if (rc)
212                         GOTO(err_cleanup, rc);
213         }
214
215         RETURN(rc);
216
217 err_cleanup:
218         mds_lov_clean(obd);
219         ctxt = llog_get_context(obd, LLOG_LOVEA_ORIG_CTXT);
220         if (ctxt)
221                 llog_cleanup(ctxt);
222 err_llog:
223         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
224         if (ctxt)
225                 llog_cleanup(ctxt);
226         return rc;
227 }
228
229 int mds_postrecov(struct obd_device *obd)
230 {
231         int rc = 0;
232         ENTRY;
233
234         if (obd->obd_fail)
235                 RETURN(0);
236
237         LASSERT(!obd->obd_recovering);
238         /* clean PENDING dir */
239 #if 0
240         if (strncmp(obd->obd_name, MDD_OBD_NAME, strlen(MDD_OBD_NAME)))
241                 rc = mds_cleanup_pending(obd);
242                 if (rc < 0)
243                         GOTO(out, rc);
244 #endif
245         /* FIXME Does target_finish_recovery really need this to block? */
246         /* Notify the LOV, which will in turn call mds_notify for each tgt */
247         /* This means that we have to hack obd_notify to think we're obd_set_up
248            during mds_lov_connect. */
249         obd_notify(obd->u.mds.mds_lov_obd, NULL,
250                    obd->obd_async_recov ? OBD_NOTIFY_SYNC_NONBLOCK :
251                    OBD_NOTIFY_SYNC, NULL);
252
253         RETURN(rc);
254 }
255
256 /* We need to be able to stop an mds_lov_synchronize */
257 static int mds_lov_early_clean(struct obd_device *obd)
258 {
259         struct mds_obd *mds = &obd->u.mds;
260         struct obd_device *osc = mds->mds_lov_obd;
261
262         if (!osc || (!obd->obd_force && !obd->obd_fail))
263                 return(0);
264
265         CDEBUG(D_HA, "abort inflight\n");
266         return (obd_precleanup(osc, OBD_CLEANUP_EARLY));
267 }
268
269 static int mds_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
270 {
271         struct mds_obd *mds = &obd->u.mds;
272         struct llog_ctxt *ctxt;
273         int rc = 0;
274         ENTRY;
275
276         switch (stage) {
277         case OBD_CLEANUP_EARLY:
278                 break;
279         case OBD_CLEANUP_EXPORTS:
280                 mds_lov_early_clean(obd);
281                 cfs_down_write(&mds->mds_notify_lock);
282                 mds_lov_disconnect(obd);
283                 mds_lov_clean(obd);
284                 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
285                 if (ctxt)
286                         llog_cleanup(ctxt);
287                 ctxt = llog_get_context(obd, LLOG_LOVEA_ORIG_CTXT);
288                 if (ctxt)
289                         llog_cleanup(ctxt);
290                 rc = obd_llog_finish(obd, 0);
291                 mds->mds_lov_exp = NULL;
292                 cfs_up_write(&mds->mds_notify_lock);
293                 break;
294         }
295         RETURN(rc);
296 }
297
298 static struct dentry *mds_lvfs_fid2dentry(__u64 id, __u32 gen, __u64 gr,
299                                           void *data)
300 {
301         struct obd_device *obd = data;
302         struct ll_fid fid;
303         fid.id = id;
304         fid.generation = gen;
305         return mds_fid2dentry(&obd->u.mds, &fid, NULL);
306 }
307
308
309 struct lvfs_callback_ops mds_lvfs_ops = {
310         l_fid2dentry:     mds_lvfs_fid2dentry,
311 };
312
313 static void mds_init_ctxt(struct obd_device *obd, struct vfsmount *mnt)
314 {
315         struct mds_obd *mds = &obd->u.mds;
316
317         mds->mds_obt.obt_vfsmnt = mnt;
318         /* why not mnt->mnt_sb instead of mnt->mnt_root->d_inode->i_sb? */
319         obd->u.obt.obt_sb = mnt->mnt_root->d_inode->i_sb;
320         obd->u.obt.obt_magic = OBT_MAGIC;
321         fsfilt_setup(obd, obd->u.obt.obt_sb);
322
323         OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
324         obd->obd_lvfs_ctxt.pwdmnt = mnt;
325         obd->obd_lvfs_ctxt.pwd = mnt->mnt_root;
326         obd->obd_lvfs_ctxt.fs = get_ds();
327         obd->obd_lvfs_ctxt.cb_ops = mds_lvfs_ops;
328         return;
329 }
330
331 /*mds still need lov setup here*/
332 static int mds_cmd_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
333 {
334         struct mds_obd *mds = &obd->u.mds;
335         struct lvfs_run_ctxt saved;
336         const char     *dev;
337         struct vfsmount *mnt;
338         struct lustre_sb_info *lsi;
339         struct lustre_mount_info *lmi;
340         struct dentry  *dentry;
341         int rc = 0;
342         ENTRY;
343
344         CDEBUG(D_INFO, "obd %s setup \n", obd->obd_name);
345         if (strncmp(obd->obd_name, MDD_OBD_NAME, strlen(MDD_OBD_NAME)))
346                 RETURN(0);
347
348         if (lcfg->lcfg_bufcount < 5) {
349                 CERROR("invalid arg for setup %s\n", MDD_OBD_NAME);
350                 RETURN(-EINVAL);
351         }
352         dev = lustre_cfg_string(lcfg, 4);
353         lmi = server_get_mount(dev);
354         LASSERT(lmi != NULL);
355
356         lsi = s2lsi(lmi->lmi_sb);
357         mnt = lmi->lmi_mnt;
358         /* FIXME: MDD LOV initialize objects.
359          * we need only lmi here but not get mount
360          * OSD did mount already, so put mount back
361          */
362         cfs_atomic_dec(&lsi->lsi_mounts);
363         mntput(mnt);
364         cfs_init_rwsem(&mds->mds_notify_lock);
365
366         obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
367         mds_init_ctxt(obd, mnt);
368
369         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
370         dentry = simple_mkdir(current->fs->pwd, mnt, "OBJECTS", 0777, 1);
371         if (IS_ERR(dentry)) {
372                 rc = PTR_ERR(dentry);
373                 CERROR("cannot create OBJECTS directory: rc = %d\n", rc);
374                 GOTO(err_putfs, rc);
375         }
376         mds->mds_objects_dir = dentry;
377
378         dentry = lookup_one_len("__iopen__", current->fs->pwd,
379                                 strlen("__iopen__"));
380         if (IS_ERR(dentry)) {
381                 rc = PTR_ERR(dentry);
382                 CERROR("cannot lookup __iopen__ directory: rc = %d\n", rc);
383                 GOTO(err_objects, rc);
384         }
385
386         mds->mds_fid_de = dentry;
387         if (!dentry->d_inode || is_bad_inode(dentry->d_inode)) {
388                 rc = -ENOENT;
389                 CERROR("__iopen__ directory has no inode? rc = %d\n", rc);
390                 GOTO(err_fid, rc);
391         }
392         rc = mds_lov_init_objids(obd);
393         if (rc != 0) {
394                CERROR("cannot init lov objid rc = %d\n", rc);
395                GOTO(err_fid, rc );
396         }
397
398         rc = mds_lov_presetup(mds, lcfg);
399         if (rc < 0)
400                 GOTO(err_objects, rc);
401
402         /* Don't wait for mds_postrecov trying to clear orphans */
403         obd->obd_async_recov = 1;
404         rc = mds_postsetup(obd);
405         /* Bug 11557 - allow async abort_recov start
406            FIXME can remove most of this obd_async_recov plumbing
407         obd->obd_async_recov = 0;
408         */
409
410         if (rc)
411                 GOTO(err_objects, rc);
412
413 err_pop:
414         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
415         RETURN(rc);
416 err_fid:
417         dput(mds->mds_fid_de);
418 err_objects:
419         dput(mds->mds_objects_dir);
420 err_putfs:
421         fsfilt_put_ops(obd->obd_fsops);
422         goto err_pop;
423 }
424
425 static int mds_cmd_cleanup(struct obd_device *obd)
426 {
427         struct mds_obd *mds = &obd->u.mds;
428         struct lvfs_run_ctxt saved;
429         int rc = 0;
430         ENTRY;
431
432         mds->mds_lov_exp = NULL;
433
434         if (obd->obd_fail)
435                 LCONSOLE_WARN("%s: shutting down for failover; client state "
436                               "will be preserved.\n", obd->obd_name);
437
438         if (strncmp(obd->obd_name, MDD_OBD_NAME, strlen(MDD_OBD_NAME)))
439                 RETURN(0);
440
441         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
442
443         mds_lov_destroy_objids(obd);
444
445         if (mds->mds_objects_dir != NULL) {
446                 l_dput(mds->mds_objects_dir);
447                 mds->mds_objects_dir = NULL;
448         }
449
450         dput(mds->mds_fid_de);
451         LL_DQUOT_OFF(obd->u.obt.obt_sb);
452         shrink_dcache_sb(mds->mds_obt.obt_sb);
453         fsfilt_put_ops(obd->obd_fsops);
454
455         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
456         RETURN(rc);
457 }
458
459 #if 0
460 static int mds_cmd_health_check(struct obd_device *obd)
461 {
462         return 0;
463 }
464 #endif
465 static struct obd_ops mds_cmd_obd_ops = {
466         .o_owner           = THIS_MODULE,
467         .o_setup           = mds_cmd_setup,
468         .o_cleanup         = mds_cmd_cleanup,
469         .o_precleanup      = mds_precleanup,
470         .o_create          = mds_obd_create,
471         .o_destroy         = mds_obd_destroy,
472         .o_llog_init       = mds_llog_init,
473         .o_llog_finish     = mds_llog_finish,
474         .o_notify          = mds_notify,
475         .o_postrecov       = mds_postrecov,
476         //   .o_health_check    = mds_cmd_health_check,
477 };
478
479 quota_interface_t *mds_quota_interface_ref;
480 extern quota_interface_t mds_quota_interface;
481
482 static int __init mds_cmd_init(void)
483 {
484         struct lprocfs_static_vars lvars;
485         int rc;
486
487         cfs_request_module("%s", "lquota");
488         mds_quota_interface_ref = PORTAL_SYMBOL_GET(mds_quota_interface);
489         rc = lquota_init(mds_quota_interface_ref);
490         if (rc) {
491                 if (mds_quota_interface_ref)
492                         PORTAL_SYMBOL_PUT(mds_quota_interface);
493                 return rc;
494         }
495         init_obd_quota_ops(mds_quota_interface_ref, &mds_cmd_obd_ops);
496
497         lprocfs_mds_init_vars(&lvars);
498         class_register_type(&mds_cmd_obd_ops, NULL, lvars.module_vars,
499                             LUSTRE_MDS_NAME, NULL);
500
501         return 0;
502 }
503
504 static void /*__exit*/ mds_cmd_exit(void)
505 {
506         lquota_exit(mds_quota_interface_ref);
507         if (mds_quota_interface_ref)
508                 PORTAL_SYMBOL_PUT(mds_quota_interface);
509
510         class_unregister_type(LUSTRE_MDS_NAME);
511 }
512
513 EXPORT_SYMBOL(mds_quota_interface_ref);
514 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
515 MODULE_DESCRIPTION("Lustre Metadata Server (MDS)");
516 MODULE_LICENSE("GPL");
517
518 module_init(mds_cmd_init);
519 module_exit(mds_cmd_exit);