Whamcloud - gitweb
LU-1415 tests: Handle OFD procfs changes
[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/smp_lock.h>
50 #include <linux/buffer_head.h>
51 #include <linux/workqueue.h>
52 #include <linux/mount.h>
53
54 #include <lustre_acl.h>
55 #include <obd_class.h>
56 #include <lustre_dlm.h>
57 #include <obd_lov.h>
58 #include <lustre_fsfilt.h>
59 #include <lprocfs_status.h>
60 #include <lustre_disk.h>
61 #include <lustre_param.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(obd, &obd->obd_olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
129                         &llog_lvfs_ops);
130         if (rc)
131                 RETURN(rc);
132
133         rc = llog_setup(obd, &obd->obd_olg, LLOG_LOVEA_ORIG_CTXT, obd, 0, NULL,
134                         &llog_lvfs_ops);
135         if (rc)
136                 GOTO(err_llog, rc);
137
138         mds_changelog_llog_init(obd, obd);
139
140         if (mds->mds_profile) {
141                 struct lustre_profile *lprof;
142                 /* The profile defines which osc and mdc to connect to, for a
143                    client.  We reuse that here to figure out the name of the
144                    lov to use (and ignore lprof->lp_md).
145                    The profile was set in the config log with
146                    LCFG_MOUNTOPT profilenm oscnm mdcnm */
147                 lprof = class_get_profile(mds->mds_profile);
148                 if (lprof == NULL) {
149                         CERROR("No profile found: %s\n", mds->mds_profile);
150                         GOTO(err_cleanup, rc = -ENOENT);
151                 }
152                 rc = mds_lov_connect(obd, lprof->lp_dt);
153                 if (rc)
154                         GOTO(err_cleanup, rc);
155         }
156
157         RETURN(rc);
158
159 err_cleanup:
160         mds_lov_clean(obd);
161         ctxt = llog_get_context(obd, LLOG_LOVEA_ORIG_CTXT);
162         if (ctxt)
163                 llog_cleanup(ctxt);
164 err_llog:
165         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
166         if (ctxt)
167                 llog_cleanup(ctxt);
168         return rc;
169 }
170
171 int mds_postrecov(struct obd_device *obd)
172 {
173         int rc = 0;
174         ENTRY;
175
176         if (obd->obd_fail)
177                 RETURN(0);
178
179         LASSERT(!obd->obd_recovering);
180         /* clean PENDING dir */
181 #if 0
182         if (strncmp(obd->obd_name, MDD_OBD_NAME, strlen(MDD_OBD_NAME)))
183                 rc = mds_cleanup_pending(obd);
184                 if (rc < 0)
185                         GOTO(out, rc);
186 #endif
187         /* FIXME Does target_finish_recovery really need this to block? */
188         /* Notify the LOV, which will in turn call mds_notify for each tgt */
189         /* This means that we have to hack obd_notify to think we're obd_set_up
190            during mds_lov_connect. */
191         obd_notify(obd->u.mds.mds_lov_obd, NULL,
192                    obd->obd_async_recov ? OBD_NOTIFY_SYNC_NONBLOCK :
193                    OBD_NOTIFY_SYNC, NULL);
194
195         RETURN(rc);
196 }
197
198 /* We need to be able to stop an mds_lov_synchronize */
199 static int mds_lov_early_clean(struct obd_device *obd)
200 {
201         struct mds_obd *mds = &obd->u.mds;
202         struct obd_device *osc = mds->mds_lov_obd;
203
204         if (!osc || (!obd->obd_force && !obd->obd_fail))
205                 return(0);
206
207         CDEBUG(D_HA, "abort inflight\n");
208         return (obd_precleanup(osc, OBD_CLEANUP_EARLY));
209 }
210
211 static int mds_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
212 {
213         struct mds_obd *mds = &obd->u.mds;
214         struct llog_ctxt *ctxt;
215         int rc = 0;
216         ENTRY;
217
218         switch (stage) {
219         case OBD_CLEANUP_EARLY:
220                 break;
221         case OBD_CLEANUP_EXPORTS:
222                 mds_lov_early_clean(obd);
223                 cfs_down_write(&mds->mds_notify_lock);
224                 mds_lov_disconnect(obd);
225                 mds_lov_clean(obd);
226                 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
227                 if (ctxt)
228                         llog_cleanup(ctxt);
229                 ctxt = llog_get_context(obd, LLOG_LOVEA_ORIG_CTXT);
230                 if (ctxt)
231                         llog_cleanup(ctxt);
232                 rc = obd_llog_finish(obd, 0);
233                 mds->mds_lov_exp = NULL;
234                 cfs_up_write(&mds->mds_notify_lock);
235                 break;
236         }
237         RETURN(rc);
238 }
239
240 /* Look up an entry by inode number. */
241 /* this function ONLY returns valid dget'd dentries with an initialized inode
242    or errors */
243 static struct dentry *mds_lvfs_fid2dentry(__u64 id, __u32 gen, __u64 gr,
244                                           void *data)
245 {
246         struct fsfilt_fid  fid;
247         struct obd_device *obd = (struct obd_device *)data;
248
249         if (id == 0)
250                 RETURN(ERR_PTR(-ESTALE));
251
252         fid.ino = id;
253         fid.gen = gen;
254
255         RETURN(fsfilt_fid2dentry(obd, obd->u.mds.mds_obt.obt_vfsmnt, &fid, 0));
256 }
257
258
259 struct lvfs_callback_ops mds_lvfs_ops = {
260         l_fid2dentry:     mds_lvfs_fid2dentry,
261 };
262
263 static int mds_init_ctxt(struct obd_device *obd, struct vfsmount *mnt)
264 {
265         struct mds_obd *mds = &obd->u.mds;
266         int rc;
267
268         mds->mds_obt.obt_vfsmnt = mnt;
269         /* why not mnt->mnt_sb instead of mnt->mnt_root->d_inode->i_sb? */
270         obd->u.obt.obt_sb = mnt->mnt_root->d_inode->i_sb;
271         obd->u.obt.obt_magic = OBT_MAGIC;
272         rc = fsfilt_setup(obd, obd->u.obt.obt_sb);
273         if (rc)
274                 return rc;
275
276         OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
277         obd->obd_lvfs_ctxt.pwdmnt = mnt;
278         obd->obd_lvfs_ctxt.pwd = mnt->mnt_root;
279         obd->obd_lvfs_ctxt.fs = get_ds();
280         obd->obd_lvfs_ctxt.cb_ops = mds_lvfs_ops;
281         return 0;
282 }
283
284 /*mds still need lov setup here*/
285 static int mds_cmd_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
286 {
287         struct mds_obd *mds = &obd->u.mds;
288         struct lvfs_run_ctxt saved;
289         const char     *dev;
290         struct vfsmount *mnt;
291         struct lustre_sb_info *lsi;
292         struct lustre_mount_info *lmi;
293         struct dentry  *dentry;
294         int rc = 0;
295         ENTRY;
296
297         CDEBUG(D_INFO, "obd %s setup \n", obd->obd_name);
298         if (strncmp(obd->obd_name, MDD_OBD_NAME, strlen(MDD_OBD_NAME)))
299                 RETURN(0);
300
301         if (lcfg->lcfg_bufcount < 5) {
302                 CERROR("invalid arg for setup %s\n", MDD_OBD_NAME);
303                 RETURN(-EINVAL);
304         }
305         dev = lustre_cfg_string(lcfg, 4);
306         lmi = server_get_mount(dev);
307         LASSERT(lmi != NULL);
308
309         lsi = s2lsi(lmi->lmi_sb);
310         mnt = lmi->lmi_mnt;
311         /* FIXME: MDD LOV initialize objects.
312          * we need only lmi here but not get mount
313          * OSD did mount already, so put mount back
314          */
315         cfs_atomic_dec(&lsi->lsi_mounts);
316         mntput(mnt);
317         cfs_init_rwsem(&mds->mds_notify_lock);
318
319         obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
320         rc = mds_init_ctxt(obd, mnt);
321         if (rc)
322                 GOTO(err_putfs, rc);
323
324         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
325         dentry = simple_mkdir(cfs_fs_pwd(current->fs), mnt, "OBJECTS", 0777, 1);
326         if (IS_ERR(dentry)) {
327                 rc = PTR_ERR(dentry);
328                 CERROR("cannot create OBJECTS directory: rc = %d\n", rc);
329                 GOTO(err_pop, rc);
330         }
331         mds->mds_objects_dir = dentry;
332
333         rc = mds_lov_init_objids(obd);
334         if (rc != 0) {
335                CERROR("cannot init lov objid rc = %d\n", rc);
336                GOTO(err_objects, rc );
337         }
338
339         rc = mds_lov_presetup(mds, lcfg);
340         if (rc < 0)
341                 GOTO(err_objects, rc);
342
343         /* Don't wait for mds_postrecov trying to clear orphans */
344         obd->obd_async_recov = 1;
345         rc = mds_postsetup(obd);
346         /* Bug 11557 - allow async abort_recov start
347            FIXME can remove most of this obd_async_recov plumbing
348         obd->obd_async_recov = 0;
349         */
350
351         if (rc)
352                 GOTO(err_objects, rc);
353
354         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
355         RETURN(0);
356
357 err_objects:
358         dput(mds->mds_objects_dir);
359 err_pop:
360         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
361 err_putfs:
362         fsfilt_put_ops(obd->obd_fsops);
363         return rc;
364 }
365
366 static int mds_cmd_cleanup(struct obd_device *obd)
367 {
368         struct mds_obd *mds = &obd->u.mds;
369         struct lvfs_run_ctxt saved;
370         int rc = 0;
371         ENTRY;
372
373         mds->mds_lov_exp = NULL;
374
375         if (obd->obd_fail)
376                 LCONSOLE_WARN("%s: shutting down for failover; client state "
377                               "will be preserved.\n", obd->obd_name);
378
379         if (strncmp(obd->obd_name, MDD_OBD_NAME, strlen(MDD_OBD_NAME)))
380                 RETURN(0);
381
382         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
383
384         mds_lov_destroy_objids(obd);
385
386         if (mds->mds_objects_dir != NULL) {
387                 l_dput(mds->mds_objects_dir);
388                 mds->mds_objects_dir = NULL;
389         }
390
391         ll_vfs_dq_off(obd->u.obt.obt_sb, 0);
392         shrink_dcache_sb(mds->mds_obt.obt_sb);
393         fsfilt_put_ops(obd->obd_fsops);
394
395         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
396         RETURN(rc);
397 }
398
399 #if 0
400 static int mds_cmd_health_check(struct obd_device *obd)
401 {
402         return 0;
403 }
404 #endif
405 static struct obd_ops mds_cmd_obd_ops = {
406         .o_owner           = THIS_MODULE,
407         .o_setup           = mds_cmd_setup,
408         .o_cleanup         = mds_cmd_cleanup,
409         .o_precleanup      = mds_precleanup,
410         .o_create          = mds_obd_create,
411         .o_destroy         = mds_obd_destroy,
412         .o_llog_init       = mds_llog_init,
413         .o_llog_finish     = mds_llog_finish,
414         .o_notify          = mds_notify,
415         .o_postrecov       = mds_postrecov,
416         //   .o_health_check    = mds_cmd_health_check,
417 };
418
419 quota_interface_t *mds_quota_interface_ref;
420 extern quota_interface_t mds_quota_interface;
421
422 static int __init mds_cmd_init(void)
423 {
424         struct lprocfs_static_vars lvars;
425         int rc;
426
427         cfs_request_module("%s", "lquota");
428         mds_quota_interface_ref = PORTAL_SYMBOL_GET(mds_quota_interface);
429         rc = lquota_init(mds_quota_interface_ref);
430         if (rc) {
431                 if (mds_quota_interface_ref)
432                         PORTAL_SYMBOL_PUT(mds_quota_interface);
433                 return rc;
434         }
435         init_obd_quota_ops(mds_quota_interface_ref, &mds_cmd_obd_ops);
436
437         lprocfs_mds_init_vars(&lvars);
438         class_register_type(&mds_cmd_obd_ops, NULL, lvars.module_vars,
439                             LUSTRE_MDS_NAME, NULL);
440
441         return 0;
442 }
443
444 static void /*__exit*/ mds_cmd_exit(void)
445 {
446         lquota_exit(mds_quota_interface_ref);
447         if (mds_quota_interface_ref)
448                 PORTAL_SYMBOL_PUT(mds_quota_interface);
449
450         class_unregister_type(LUSTRE_MDS_NAME);
451 }
452
453 EXPORT_SYMBOL(mds_quota_interface_ref);
454 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
455 MODULE_DESCRIPTION("Lustre Metadata Server (MDS)");
456 MODULE_LICENSE("GPL");
457
458 module_init(mds_cmd_init);
459 module_exit(mds_cmd_exit);