]> Pileus Git - ~andy/linux/blobdiff - drivers/staging/lustre/lustre/mgc/mgc_request.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
[~andy/linux] / drivers / staging / lustre / lustre / mgc / mgc_request.c
index 12a9ede21a8565a77e4e5f07c43041f35d4025f0..3bdbb94e020fbeeaed169cfae69bc532c7f18594 100644 (file)
 #define DEBUG_SUBSYSTEM S_MGC
 #define D_MGC D_CONFIG /*|D_WARNING*/
 
-# include <linux/module.h>
-# include <linux/pagemap.h>
-# include <linux/miscdevice.h>
-# include <linux/init.h>
-
+#include <linux/module.h>
 #include <obd_class.h>
 #include <lustre_dlm.h>
 #include <lprocfs_status.h>
 #include <lustre_log.h>
-#include <lustre_fsfilt.h>
 #include <lustre_disk.h>
+#include <dt_object.h>
+
 #include "mgc_internal.h"
 
 static int mgc_name2resid(char *name, int len, struct ldlm_res_id *res_id,
@@ -73,7 +70,7 @@ static int mgc_name2resid(char *name, int len, struct ldlm_res_id *res_id,
        memset(res_id, 0, sizeof(*res_id));
        res_id->name[0] = cpu_to_le64(resname);
        /* XXX: unfortunately, sptlprc and config llog share one lock */
-       switch(type) {
+       switch (type) {
        case CONFIG_T_CONFIG:
        case CONFIG_T_SPTLRPC:
                resname = 0;
@@ -400,6 +397,7 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg)
        return rc;
 }
 
+#ifdef LPROCFS
 int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
 {
        struct obd_device       *obd = data;
@@ -423,6 +421,7 @@ int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
 
        return 0;
 }
+#endif
 
 /* reenqueue any lost locks */
 #define RQ_RUNNING 0x1
@@ -578,97 +577,175 @@ static void mgc_requeue_add(struct config_llog_data *cld)
 }
 
 /********************** class fns **********************/
+static int mgc_local_llog_init(const struct lu_env *env,
+                              struct obd_device *obd,
+                              struct obd_device *disk)
+{
+       struct llog_ctxt        *ctxt;
+       int                      rc;
+
+       rc = llog_setup(env, obd, &obd->obd_olg, LLOG_CONFIG_ORIG_CTXT, disk,
+                       &llog_osd_ops);
+       if (rc)
+               return rc;
+
+       ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
+       LASSERT(ctxt);
+       ctxt->loc_dir = obd->u.cli.cl_mgc_configs_dir;
+       llog_ctxt_put(ctxt);
 
-static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb,
-                       struct vfsmount *mnt)
+       return 0;
+}
+
+static int mgc_local_llog_fini(const struct lu_env *env,
+                              struct obd_device *obd)
 {
-       struct lvfs_run_ctxt saved;
-       struct lustre_sb_info *lsi = s2lsi(sb);
-       struct client_obd *cli = &obd->u.cli;
-       struct dentry *dentry;
-       char *label;
-       int err = 0;
+       struct llog_ctxt *ctxt;
+
+       ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
+       llog_cleanup(env, ctxt);
+
+       return 0;
+}
+
+static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb)
+{
+       struct lustre_sb_info   *lsi = s2lsi(sb);
+       struct client_obd       *cli = &obd->u.cli;
+       struct lu_fid            rfid, fid;
+       struct dt_object        *root, *dto;
+       struct lu_env           *env;
+       int                      rc = 0;
 
        LASSERT(lsi);
-       LASSERT(lsi->lsi_srv_mnt == mnt);
+       LASSERT(lsi->lsi_dt_dev);
+
+       OBD_ALLOC_PTR(env);
+       if (env == NULL)
+               return -ENOMEM;
 
        /* The mgc fs exclusion sem. Only one fs can be setup at a time. */
        down(&cli->cl_mgc_sem);
 
        cfs_cleanup_group_info();
 
-       obd->obd_fsops = fsfilt_get_ops(lsi->lsi_fstype);
-       if (IS_ERR(obd->obd_fsops)) {
-               up(&cli->cl_mgc_sem);
-               CERROR("%s: No fstype %s: rc = %ld\n", lsi->lsi_fstype,
-                      obd->obd_name, PTR_ERR(obd->obd_fsops));
-               return PTR_ERR(obd->obd_fsops);
-       }
+       /* Setup the configs dir */
+       rc = lu_env_init(env, LCT_MG_THREAD);
+       if (rc)
+               GOTO(out_err, rc);
 
-       cli->cl_mgc_vfsmnt = mnt;
-       err = fsfilt_setup(obd, mnt->mnt_sb);
-       if (err)
-               GOTO(err_ops, err);
-
-       OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
-       obd->obd_lvfs_ctxt.pwdmnt = mnt;
-       obd->obd_lvfs_ctxt.pwd = mnt->mnt_root;
-       obd->obd_lvfs_ctxt.fs = get_ds();
-
-       push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-       dentry = ll_lookup_one_len(MOUNT_CONFIGS_DIR, cfs_fs_pwd(current->fs),
-                                  strlen(MOUNT_CONFIGS_DIR));
-       pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-       if (IS_ERR(dentry)) {
-               err = PTR_ERR(dentry);
-               CERROR("cannot lookup %s directory: rc = %d\n",
-                      MOUNT_CONFIGS_DIR, err);
-               GOTO(err_ops, err);
-       }
-       cli->cl_mgc_configs_dir = dentry;
+       fid.f_seq = FID_SEQ_LOCAL_NAME;
+       fid.f_oid = 1;
+       fid.f_ver = 0;
+       rc = local_oid_storage_init(env, lsi->lsi_dt_dev, &fid,
+                                   &cli->cl_mgc_los);
+       if (rc)
+               GOTO(out_env, rc);
+
+       rc = dt_root_get(env, lsi->lsi_dt_dev, &rfid);
+       if (rc)
+               GOTO(out_env, rc);
+
+       root = dt_locate_at(env, lsi->lsi_dt_dev, &rfid,
+                           &cli->cl_mgc_los->los_dev->dd_lu_dev);
+       if (unlikely(IS_ERR(root)))
+               GOTO(out_los, rc = PTR_ERR(root));
+
+       dto = local_file_find_or_create(env, cli->cl_mgc_los, root,
+                                       MOUNT_CONFIGS_DIR,
+                                       S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO);
+       lu_object_put_nocache(env, &root->do_lu);
+       if (IS_ERR(dto))
+               GOTO(out_los, rc = PTR_ERR(dto));
+
+       cli->cl_mgc_configs_dir = dto;
+
+       LASSERT(lsi->lsi_osd_exp->exp_obd->obd_lvfs_ctxt.dt);
+       rc = mgc_local_llog_init(env, obd, lsi->lsi_osd_exp->exp_obd);
+       if (rc)
+               GOTO(out_llog, rc);
 
        /* We take an obd ref to insure that we can't get to mgc_cleanup
-          without calling mgc_fs_cleanup first. */
+        * without calling mgc_fs_cleanup first. */
        class_incref(obd, "mgc_fs", obd);
 
-       label = fsfilt_get_label(obd, mnt->mnt_sb);
-       if (label)
-               CDEBUG(D_MGC, "MGC using disk labelled=%s\n", label);
-
        /* We keep the cl_mgc_sem until mgc_fs_cleanup */
-       return 0;
-
-err_ops:
-       fsfilt_put_ops(obd->obd_fsops);
-       obd->obd_fsops = NULL;
-       cli->cl_mgc_vfsmnt = NULL;
-       up(&cli->cl_mgc_sem);
-       return err;
+out_llog:
+       if (rc) {
+               lu_object_put(env, &cli->cl_mgc_configs_dir->do_lu);
+               cli->cl_mgc_configs_dir = NULL;
+       }
+out_los:
+       if (rc < 0) {
+               local_oid_storage_fini(env, cli->cl_mgc_los);
+               cli->cl_mgc_los = NULL;
+               up(&cli->cl_mgc_sem);
+       }
+out_env:
+       lu_env_fini(env);
+out_err:
+       OBD_FREE_PTR(env);
+       return rc;
 }
 
 static int mgc_fs_cleanup(struct obd_device *obd)
 {
-       struct client_obd *cli = &obd->u.cli;
-       int rc = 0;
+       struct lu_env            env;
+       struct client_obd       *cli = &obd->u.cli;
+       int                      rc;
 
-       LASSERT(cli->cl_mgc_vfsmnt != NULL);
+       LASSERT(cli->cl_mgc_los != NULL);
 
-       if (cli->cl_mgc_configs_dir != NULL) {
-               struct lvfs_run_ctxt saved;
-               push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-               l_dput(cli->cl_mgc_configs_dir);
-               cli->cl_mgc_configs_dir = NULL;
-               pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-               class_decref(obd, "mgc_fs", obd);
-       }
+       rc = lu_env_init(&env, LCT_MG_THREAD);
+       if (rc)
+               GOTO(unlock, rc);
+
+       mgc_local_llog_fini(&env, obd);
+
+       lu_object_put_nocache(&env, &cli->cl_mgc_configs_dir->do_lu);
+       cli->cl_mgc_configs_dir = NULL;
 
-       cli->cl_mgc_vfsmnt = NULL;
-       if (obd->obd_fsops)
-               fsfilt_put_ops(obd->obd_fsops);
+       local_oid_storage_fini(&env, cli->cl_mgc_los);
+       cli->cl_mgc_los = NULL;
+       lu_env_fini(&env);
 
+unlock:
+       class_decref(obd, "mgc_fs", obd);
        up(&cli->cl_mgc_sem);
 
-       return rc;
+       return 0;
+}
+
+static int mgc_llog_init(const struct lu_env *env, struct obd_device *obd)
+{
+       struct llog_ctxt        *ctxt;
+       int                      rc;
+
+       /* setup only remote ctxt, the local disk context is switched per each
+        * filesystem during mgc_fs_setup() */
+       rc = llog_setup(env, obd, &obd->obd_olg, LLOG_CONFIG_REPL_CTXT, obd,
+                       &llog_client_ops);
+       if (rc)
+               return rc;
+
+       ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
+       LASSERT(ctxt);
+
+       llog_initiator_connect(ctxt);
+       llog_ctxt_put(ctxt);
+
+       return 0;
+}
+
+static int mgc_llog_fini(const struct lu_env *env, struct obd_device *obd)
+{
+       struct llog_ctxt *ctxt;
+
+       ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
+       if (ctxt)
+               llog_cleanup(env, ctxt);
+
+       return 0;
 }
 
 static atomic_t mgc_count = ATOMIC_INIT(0);
@@ -694,7 +771,7 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
                        }
                }
                obd_cleanup_client_import(obd);
-               rc = obd_llog_finish(obd, 0);
+               rc = mgc_llog_fini(NULL, obd);
                if (rc != 0)
                        CERROR("failed to cleanup llogging subsystems\n");
                break;
@@ -704,11 +781,8 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 
 static int mgc_cleanup(struct obd_device *obd)
 {
-       struct client_obd *cli = &obd->u.cli;
        int rc;
 
-       LASSERT(cli->cl_mgc_vfsmnt == NULL);
-
        /* COMPAT_146 - old config logs may have added profiles we don't
           know about */
        if (obd->obd_type->typ_refcnt <= 1)
@@ -733,7 +807,7 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
        if (rc)
                GOTO(err_decref, rc);
 
-       rc = obd_llog_init(obd, &obd->obd_olg, obd, NULL);
+       rc = mgc_llog_init(NULL, obd);
        if (rc) {
                CERROR("failed to setup llogging subsystems\n");
                GOTO(err_cleanup, rc);
@@ -788,8 +862,8 @@ static int mgc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                /* We've given up the lock, prepare ourselves to update. */
                LDLM_DEBUG(lock, "MGC cancel CB");
 
-               CDEBUG(D_MGC, "Lock res "LPX64" (%.8s)\n",
-                      lock->l_resource->lr_name.name[0],
+               CDEBUG(D_MGC, "Lock res "DLDLMRES" (%.8s)\n",
+                      PLDLMRES(lock->l_resource),
                       (char *)&lock->l_resource->lr_name.name[0]);
 
                if (!cld) {
@@ -1011,23 +1085,23 @@ int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp,
        }
        if (KEY_IS(KEY_SET_FS)) {
                struct super_block *sb = (struct super_block *)val;
-               struct lustre_sb_info *lsi;
+
                if (vallen != sizeof(struct super_block))
                        return -EINVAL;
-               lsi = s2lsi(sb);
-               rc = mgc_fs_setup(exp->exp_obd, sb, lsi->lsi_srv_mnt);
-               if (rc) {
+
+               rc = mgc_fs_setup(exp->exp_obd, sb);
+               if (rc)
                        CERROR("set_fs got %d\n", rc);
-               }
+
                return rc;
        }
        if (KEY_IS(KEY_CLEAR_FS)) {
                if (vallen != 0)
                        return -EINVAL;
                rc = mgc_fs_cleanup(exp->exp_obd);
-               if (rc) {
+               if (rc)
                        CERROR("clear_fs got %d\n", rc);
-               }
+
                return rc;
        }
        if (KEY_IS(KEY_SET_INFO)) {
@@ -1145,49 +1219,6 @@ static int mgc_import_event(struct obd_device *obd,
        return rc;
 }
 
-static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
-                        struct obd_device *tgt, int *index)
-{
-       struct llog_ctxt *ctxt;
-       int rc;
-
-       LASSERT(olg == &obd->obd_olg);
-
-
-       rc = llog_setup(NULL, obd, olg, LLOG_CONFIG_REPL_CTXT, tgt,
-                       &llog_client_ops);
-       if (rc)
-               GOTO(out, rc);
-
-       ctxt = llog_group_get_ctxt(olg, LLOG_CONFIG_REPL_CTXT);
-       if (!ctxt)
-               GOTO(out, rc = -ENODEV);
-
-       llog_initiator_connect(ctxt);
-       llog_ctxt_put(ctxt);
-
-       return 0;
-out:
-       ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
-       if (ctxt)
-               llog_cleanup(NULL, ctxt);
-       return rc;
-}
-
-static int mgc_llog_finish(struct obd_device *obd, int count)
-{
-       struct llog_ctxt *ctxt;
-
-       ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
-       if (ctxt)
-               llog_cleanup(NULL, ctxt);
-
-       ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
-       if (ctxt)
-               llog_cleanup(NULL, ctxt);
-       return 0;
-}
-
 enum {
        CONFIG_READ_NRPAGES_INIT = 1 << (20 - PAGE_CACHE_SHIFT),
        CONFIG_READ_NRPAGES      = 4
@@ -1540,17 +1571,58 @@ out:
        return rc;
 }
 
+static int mgc_llog_local_copy(const struct lu_env *env,
+                              struct obd_device *obd,
+                              struct llog_ctxt *rctxt,
+                              struct llog_ctxt *lctxt, char *logname)
+{
+       char    *temp_log;
+       int      rc;
+
+
+
+       /*
+        * - copy it to backup using llog_backup()
+        * - copy remote llog to logname using llog_backup()
+        * - if failed then move bakup to logname again
+        */
+
+       OBD_ALLOC(temp_log, strlen(logname) + 1);
+       if (!temp_log)
+               return -ENOMEM;
+       sprintf(temp_log, "%sT", logname);
+
+       /* make a copy of local llog at first */
+       rc = llog_backup(env, obd, lctxt, lctxt, logname, temp_log);
+       if (rc < 0 && rc != -ENOENT)
+               GOTO(out, rc);
+       /* copy remote llog to the local copy */
+       rc = llog_backup(env, obd, rctxt, lctxt, logname, logname);
+       if (rc == -ENOENT) {
+               /* no remote llog, delete local one too */
+               llog_erase(env, lctxt, NULL, logname);
+       } else if (rc < 0) {
+               /* error during backup, get local one back from the copy */
+               llog_backup(env, obd, lctxt, lctxt, temp_log, logname);
+out:
+               CERROR("%s: failed to copy remote log %s: rc = %d\n",
+                      obd->obd_name, logname, rc);
+       }
+       llog_erase(env, lctxt, NULL, temp_log);
+       OBD_FREE(temp_log, strlen(logname) + 1);
+       return rc;
+}
 
 /* local_only means it cannot get remote llogs */
 static int mgc_process_cfg_log(struct obd_device *mgc,
-                              struct config_llog_data *cld,
-                              int local_only)
+                              struct config_llog_data *cld, int local_only)
 {
-       struct llog_ctxt *ctxt, *lctxt = NULL;
-       struct lvfs_run_ctxt *saved_ctxt;
-       struct lustre_sb_info *lsi = NULL;
-       int rc = 0, must_pop = 0;
-       bool sptlrpc_started = false;
+       struct llog_ctxt        *ctxt, *lctxt = NULL;
+       struct dt_object        *cl_mgc_dir = mgc->u.cli.cl_mgc_configs_dir;
+       struct lustre_sb_info   *lsi = NULL;
+       int                      rc = 0;
+       bool                     sptlrpc_started = false;
+       struct lu_env           *env;
 
        LASSERT(cld);
        LASSERT(mutex_is_locked(&cld->cld_lock));
@@ -1565,20 +1637,48 @@ static int mgc_process_cfg_log(struct obd_device *mgc,
        if (cld->cld_cfg.cfg_sb)
                lsi = s2lsi(cld->cld_cfg.cfg_sb);
 
-       ctxt = llog_get_context(mgc, LLOG_CONFIG_REPL_CTXT);
-       if (!ctxt) {
-               CERROR("missing llog context\n");
-               return -EINVAL;
-       }
-
-       OBD_ALLOC_PTR(saved_ctxt);
-       if (saved_ctxt == NULL)
+       OBD_ALLOC_PTR(env);
+       if (env == NULL)
                return -ENOMEM;
 
+       rc = lu_env_init(env, LCT_MG_THREAD);
+       if (rc)
+               GOTO(out_free, rc);
+
+       ctxt = llog_get_context(mgc, LLOG_CONFIG_REPL_CTXT);
+       LASSERT(ctxt);
+
        lctxt = llog_get_context(mgc, LLOG_CONFIG_ORIG_CTXT);
 
-               if (local_only) { /* no local log at client side */
-               GOTO(out_pop, rc = -EIO);
+       /* Copy the setup log locally if we can. Don't mess around if we're
+        * running an MGS though (logs are already local). */
+       if (lctxt && lsi && IS_SERVER(lsi) && !IS_MGS(lsi) &&
+           cl_mgc_dir != NULL &&
+           lu2dt_dev(cl_mgc_dir->do_lu.lo_dev) == lsi->lsi_dt_dev) {
+               if (!local_only)
+                       /* Only try to copy log if we have the lock. */
+                       rc = mgc_llog_local_copy(env, mgc, ctxt, lctxt,
+                                                cld->cld_logname);
+               if (local_only || rc) {
+                       if (llog_is_empty(env, lctxt, cld->cld_logname)) {
+                               LCONSOLE_ERROR_MSG(0x13a,
+                                                  "Failed to get MGS log %s and no local copy.\n",
+                                                  cld->cld_logname);
+                               GOTO(out_pop, rc = -ENOTCONN);
+                       }
+                       CDEBUG(D_MGC,
+                              "Failed to get MGS log %s, using local copy for now, will try to update later.\n",
+                              cld->cld_logname);
+               }
+               /* Now, whether we copied or not, start using the local llog.
+                * If we failed to copy, we'll start using whatever the old
+                * log has. */
+               llog_ctxt_put(ctxt);
+               ctxt = lctxt;
+               lctxt = NULL;
+       } else {
+               if (local_only) /* no local log at client side */
+                       GOTO(out_pop, rc = -EIO);
        }
 
        if (cld_is_sptlrpc(cld)) {
@@ -1587,19 +1687,16 @@ static int mgc_process_cfg_log(struct obd_device *mgc,
        }
 
        /* logname and instance info should be the same, so use our
-          copy of the instance for the update.  The cfg_last_idx will
-          be updated here. */
-       rc = class_config_parse_llog(NULL, ctxt, cld->cld_logname,
+        * copy of the instance for the update.  The cfg_last_idx will
+        * be updated here. */
+       rc = class_config_parse_llog(env, ctxt, cld->cld_logname,
                                     &cld->cld_cfg);
 
 out_pop:
-       llog_ctxt_put(ctxt);
+       __llog_ctxt_put(env, ctxt);
        if (lctxt)
-               llog_ctxt_put(lctxt);
-       if (must_pop)
-               pop_ctxt(saved_ctxt, &mgc->obd_lvfs_ctxt, NULL);
+               __llog_ctxt_put(env, lctxt);
 
-       OBD_FREE_PTR(saved_ctxt);
        /*
         * update settings on existing OBDs. doing it inside
         * of llog_process_lock so no device is attaching/detaching
@@ -1614,6 +1711,9 @@ out_pop:
                                          strlen("-sptlrpc"));
        }
 
+       lu_env_fini(env);
+out_free:
+       OBD_FREE_PTR(env);
        return rc;
 }
 
@@ -1700,7 +1800,7 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf)
        char *logname;
        int rc = 0;
 
-       switch(lcfg->lcfg_command) {
+       switch (lcfg->lcfg_command) {
        case LCFG_LOV_ADD_OBD: {
                /* Overloading this cfg command: register a new target */
                struct mgs_target_info *mti;
@@ -1795,14 +1895,12 @@ struct obd_ops mgc_obd_ops = {
        .o_del_conn     = client_import_del_conn,
        .o_connect      = client_connect_import,
        .o_disconnect   = client_disconnect_export,
-       //.o_enqueue      = mgc_enqueue,
+       /* .o_enqueue      = mgc_enqueue, */
        .o_cancel       = mgc_cancel,
-       //.o_iocontrol    = mgc_iocontrol,
+       /* .o_iocontrol    = mgc_iocontrol, */
        .o_set_info_async = mgc_set_info_async,
        .o_get_info       = mgc_get_info,
        .o_import_event = mgc_import_event,
-       .o_llog_init    = mgc_llog_init,
-       .o_llog_finish  = mgc_llog_finish,
        .o_process_config = mgc_process_config,
 };