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