Whamcloud - gitweb
LU-5496 ldlm: reconstruct proper flags on enqueue resend
[fs/lustre-release.git] / lustre / mgs / mgs_handler.c
index 045e94c..7e196fb 100644 (file)
@@ -45,6 +45,7 @@
 
 #include <obd_class.h>
 #include <lprocfs_status.h>
+#include <lustre_ioctl.h>
 #include <lustre_param.h>
 
 #include "mgs_internal.h"
@@ -59,6 +60,7 @@ static int mgs_connect(struct tgt_session_info *tsi)
 
        ENTRY;
 
+       CFS_FAIL_TIMEOUT(OBD_FAIL_MGS_CONNECT_NET, cfs_fail_val);
        rc = tgt_connect(tsi);
        if (rc)
                RETURN(rc);
@@ -132,14 +134,19 @@ out_cfg:
        return rc;
 }
 
-static int mgs_completion_ast_config(struct ldlm_lock *lock, __u64 flags,
-                                    void *cbdata)
+enum ast_type {
+               AST_CONFIG = 1,
+               AST_PARAMS = 2,
+               AST_IR = 3
+};
+
+static int mgs_completion_ast_generic(struct ldlm_lock *lock, __u64 flags,
+                                    void *cbdata, enum ast_type type)
 {
        ENTRY;
 
-       if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
-                      LDLM_FL_BLOCK_CONV))) {
-                struct fs_db *fsdb;
+       if (!(flags & LDLM_FL_BLOCKED_MASK)) {
+               struct fs_db *fsdb;
 
                /* l_ast_data is used as a marker to avoid cancel ldlm lock
                 * twice. See LU-2317. */
@@ -151,8 +158,22 @@ static int mgs_completion_ast_config(struct ldlm_lock *lock, __u64 flags,
                if (fsdb != NULL) {
                        struct lustre_handle lockh;
 
-                       /* clear the bit before lock put */
-                       clear_bit(FSDB_REVOKING_LOCK, &fsdb->fsdb_flags);
+                       switch(type) {
+                               case AST_CONFIG:
+                                       /* clear the bit before lock put */
+                                       clear_bit(FSDB_REVOKING_LOCK,
+                                                 &fsdb->fsdb_flags);
+                                       break;
+                               case AST_PARAMS:
+                                       clear_bit(FSDB_REVOKING_PARAMS,
+                                                 &fsdb->fsdb_flags);
+                                       break;
+                               case AST_IR:
+                                       mgs_ir_notify_complete(fsdb);
+                                       break;
+                               default:
+                                       LBUG();
+                       }
 
                        ldlm_lock2handle(lock, &lockh);
                        ldlm_lock_decref_and_cancel(&lockh, LCK_EX);
@@ -162,80 +183,77 @@ static int mgs_completion_ast_config(struct ldlm_lock *lock, __u64 flags,
        RETURN(ldlm_completion_ast(lock, flags, cbdata));
 }
 
-static int mgs_completion_ast_ir(struct ldlm_lock *lock, __u64 flags,
-                                 void *cbdata)
+static int mgs_completion_ast_config(struct ldlm_lock *lock, __u64 flags,
+                                    void *cbdata)
 {
-        ENTRY;
-
-        if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
-                       LDLM_FL_BLOCK_CONV))) {
-                struct fs_db *fsdb;
-
-                /* l_ast_data is used as a marker to avoid cancel ldlm lock
-                 * twice. See LU-1259. */
-                lock_res_and_lock(lock);
-                fsdb = (struct fs_db *)lock->l_ast_data;
-                lock->l_ast_data = NULL;
-                unlock_res_and_lock(lock);
-
-                if (fsdb != NULL) {
-                        struct lustre_handle lockh;
-
-                        mgs_ir_notify_complete(fsdb);
+       return mgs_completion_ast_generic(lock, flags, cbdata, AST_CONFIG);
+}
 
-                        ldlm_lock2handle(lock, &lockh);
-                        ldlm_lock_decref_and_cancel(&lockh, LCK_EX);
-                }
-        }
+static int mgs_completion_ast_params(struct ldlm_lock *lock, __u64 flags,
+                                    void *cbdata)
+{
+       return mgs_completion_ast_generic(lock, flags, cbdata, AST_PARAMS);
+}
 
-        RETURN(ldlm_completion_ast(lock, flags, cbdata));
+static int mgs_completion_ast_ir(struct ldlm_lock *lock, __u64 flags,
+                                void *cbdata)
+{
+       return mgs_completion_ast_generic(lock, flags, cbdata, AST_IR);
 }
 
 void mgs_revoke_lock(struct mgs_device *mgs, struct fs_db *fsdb, int type)
 {
-        ldlm_completion_callback cp = NULL;
-        struct lustre_handle     lockh = { 0 };
-        struct ldlm_res_id       res_id;
+       ldlm_completion_callback cp = NULL;
+       struct lustre_handle     lockh = { 0 };
+       struct ldlm_res_id       res_id;
        __u64 flags = LDLM_FL_ATOMIC_CB;
-        int rc;
-        ENTRY;
-
-        LASSERT(fsdb->fsdb_name[0] != '\0');
-        rc = mgc_fsname2resid(fsdb->fsdb_name, &res_id, type);
-        LASSERT(rc == 0);
+       int rc;
+       ENTRY;
 
-        switch (type) {
-        case CONFIG_T_CONFIG:
-                cp = mgs_completion_ast_config;
+       LASSERT(fsdb->fsdb_name[0] != '\0');
+       rc = mgc_fsname2resid(fsdb->fsdb_name, &res_id, type);
+       LASSERT(rc == 0);
+       switch (type) {
+       case CONFIG_T_CONFIG:
+               cp = mgs_completion_ast_config;
                if (test_and_set_bit(FSDB_REVOKING_LOCK, &fsdb->fsdb_flags))
-                        rc = -EALREADY;
-                break;
-        case CONFIG_T_RECOVER:
-                cp = mgs_completion_ast_ir;
-        default:
-                break;
-        }
+                       rc = -EALREADY;
+               break;
+       case CONFIG_T_PARAMS:
+               cp = mgs_completion_ast_params;
+               if (test_and_set_bit(FSDB_REVOKING_PARAMS, &fsdb->fsdb_flags))
+                       rc = -EALREADY;
+               break;
+       case CONFIG_T_RECOVER:
+               cp = mgs_completion_ast_ir;
+       default:
+               break;
+       }
 
-        if (!rc) {
-                LASSERT(cp != NULL);
+       if (!rc) {
+               LASSERT(cp != NULL);
                rc = ldlm_cli_enqueue_local(mgs->mgs_obd->obd_namespace,
                                            &res_id, LDLM_PLAIN, NULL, LCK_EX,
                                            &flags, ldlm_blocking_ast, cp,
                                            NULL, fsdb, 0, LVB_T_NONE, NULL,
                                            &lockh);
-                if (rc != ELDLM_OK) {
-                        CERROR("can't take cfg lock for "LPX64"/"LPX64"(%d)\n",
-                               le64_to_cpu(res_id.name[0]),
-                               le64_to_cpu(res_id.name[1]), rc);
+               if (rc != ELDLM_OK) {
+                       CERROR("can't take cfg lock for "LPX64"/"LPX64"(%d)\n",
+                              le64_to_cpu(res_id.name[0]),
+                              le64_to_cpu(res_id.name[1]), rc);
 
-                        if (type == CONFIG_T_CONFIG)
+                       if (type == CONFIG_T_CONFIG)
                                clear_bit(FSDB_REVOKING_LOCK,
-                                              &fsdb->fsdb_flags);
-                }
-                /* lock has been cancelled in completion_ast. */
-        }
+                                         &fsdb->fsdb_flags);
+
+                       if (type == CONFIG_T_PARAMS)
+                               clear_bit(FSDB_REVOKING_PARAMS,
+                                         &fsdb->fsdb_flags);
+               }
+               /* lock has been cancelled in completion_ast. */
+       }
 
-        RETURN_EXIT;
+       RETURN_EXIT;
 }
 
 /* rc=0 means ok
@@ -521,11 +539,14 @@ static int mgs_llog_open(struct tgt_session_info *tsi)
        logname = req_capsule_client_get(tsi->tsi_pill, &RMF_NAME);
        if (logname) {
                char *ptr = strchr(logname, '-');
-               int   len = (int)(ptr - logname);
+               int   len = (ptr != NULL) ? (int)(ptr - logname) : 0;
 
                if (ptr == NULL || len >= sizeof(mgi->mgi_fsname)) {
-                       LCONSOLE_WARN("%s: non-config logname received: %s\n",
-                                     tgt_name(tsi->tsi_tgt), logname);
+                       if (strcmp(logname, PARAMS_FILENAME) != 0)
+                               LCONSOLE_WARN("%s: non-config logname "
+                                             "received: %s\n",
+                                             tgt_name(tsi->tsi_tgt),
+                                             logname);
                        /* not error, this can be llog test name */
                } else {
                        strncpy(mgi->mgi_fsname, logname, len);
@@ -550,22 +571,13 @@ static int mgs_llog_open(struct tgt_session_info *tsi)
        RETURN(rc);
 }
 
-/*
- * sec context handlers
- */
-/* XXX: Implement based on mdt_sec_ctx_handle()? */
-static int mgs_sec_ctx_handle(struct tgt_session_info *tsi)
-{
-       return 0;
-}
-
 static inline int mgs_init_export(struct obd_export *exp)
 {
        struct mgs_export_data *data = &exp->u.eu_mgs_data;
 
        /* init mgs_export_data for fsc */
        spin_lock_init(&data->med_lock);
-       CFS_INIT_LIST_HEAD(&data->med_clients);
+       INIT_LIST_HEAD(&data->med_clients);
 
        spin_lock(&exp->exp_lock);
        exp->exp_connecting = 1;
@@ -612,6 +624,139 @@ static int mgs_extract_fs_pool(char * arg, char *fsname, char *poolname)
         RETURN(0);
 }
 
+static int mgs_iocontrol_nodemap(const struct lu_env *env,
+                                struct mgs_device *mgs,
+                                struct obd_ioctl_data *data)
+{
+       struct lustre_cfg       *lcfg = NULL;
+       struct lu_nodemap       *nodemap;
+       lnet_nid_t              nid;
+       const char              *nodemap_name = NULL;
+       const char              *nidstr = NULL;
+       const char              *client_idstr = NULL;
+       const char              *idtype_str = NULL;
+       char                    *param = NULL;
+       char                    fs_idstr[16];
+       int                     rc = 0;
+       __u32                   client_id;
+       __u32                   fs_id;
+       __u32                   cmd;
+       int                     idtype;
+
+       ENTRY;
+
+       if (data->ioc_type != LUSTRE_CFG_TYPE) {
+               CERROR("%s: unknown cfg record type: %d\n",
+                      mgs->mgs_obd->obd_name, data->ioc_type);
+               GOTO(out, rc = -EINVAL);
+       }
+
+       if (data->ioc_plen1 > PAGE_CACHE_SIZE)
+               GOTO(out, rc = -E2BIG);
+
+       OBD_ALLOC(lcfg, data->ioc_plen1);
+       if (lcfg == NULL)
+               GOTO(out, rc = -ENOMEM);
+
+       if (copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1))
+               GOTO(out_lcfg, rc = -EFAULT);
+
+       cmd = lcfg->lcfg_command;
+
+       switch (cmd) {
+       case LCFG_NODEMAP_ACTIVATE:
+               if (lcfg->lcfg_bufcount != 2)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               param = lustre_cfg_string(lcfg, 1);
+               if (strcmp(param, "1") == 0)
+                               nodemap_activate(1);
+               else
+                               nodemap_activate(0);
+               break;
+       case LCFG_NODEMAP_ADD:
+       case LCFG_NODEMAP_DEL:
+               if (lcfg->lcfg_bufcount != 2)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nodemap_name = lustre_cfg_string(lcfg, 1);
+               rc = mgs_nodemap_cmd(env, mgs, cmd, nodemap_name, param);
+               break;
+       case LCFG_NODEMAP_TEST_NID:
+               if (lcfg->lcfg_bufcount != 2)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nidstr = lustre_cfg_string(lcfg, 1);
+               nid = libcfs_str2nid(nidstr);
+               nodemap = nodemap_classify_nid(nid);
+               memset(data->ioc_pbuf1, 0, data->ioc_plen1);
+               if (copy_to_user(data->ioc_pbuf1, nodemap->nm_name,
+                                strlen(nodemap->nm_name)) != 0)
+                       GOTO(out_lcfg, rc = -EFAULT);
+               break;
+       case LCFG_NODEMAP_TEST_ID:
+               if (lcfg->lcfg_bufcount != 4)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nidstr = lustre_cfg_string(lcfg, 1);
+               idtype_str = lustre_cfg_string(lcfg, 2);
+               client_idstr = lustre_cfg_string(lcfg, 3);
+
+               nid = libcfs_str2nid(nidstr);
+               nodemap = nodemap_classify_nid(nid);
+               client_id = simple_strtoul(client_idstr, NULL, 10);
+
+               if (strcmp(idtype_str, "uid") == 0)
+                       idtype = NODEMAP_UID;
+               else
+                       idtype = NODEMAP_GID;
+
+               fs_id = nodemap_map_id(nodemap, idtype, NODEMAP_CLIENT_TO_FS,
+                                      client_id);
+
+               if (data->ioc_plen1 < sizeof(fs_idstr))
+                       GOTO(out_lcfg, rc = -EINVAL);
+
+               snprintf(fs_idstr, sizeof(fs_idstr), "%u", fs_id);
+               if (copy_to_user(data->ioc_pbuf1, fs_idstr,
+                                sizeof(fs_idstr)) != 0)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               break;
+       case LCFG_NODEMAP_ADD_RANGE:
+       case LCFG_NODEMAP_DEL_RANGE:
+       case LCFG_NODEMAP_ADD_UIDMAP:
+       case LCFG_NODEMAP_DEL_UIDMAP:
+       case LCFG_NODEMAP_ADD_GIDMAP:
+       case LCFG_NODEMAP_DEL_GIDMAP:
+               if (lcfg->lcfg_bufcount != 3)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nodemap_name = lustre_cfg_string(lcfg, 1);
+               param = lustre_cfg_string(lcfg, 2);
+               rc = mgs_nodemap_cmd(env, mgs, cmd, nodemap_name, param);
+               break;
+       case LCFG_NODEMAP_ADMIN:
+       case LCFG_NODEMAP_TRUSTED:
+       case LCFG_NODEMAP_SQUASH_UID:
+       case LCFG_NODEMAP_SQUASH_GID:
+               if (lcfg->lcfg_bufcount != 4)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nodemap_name = lustre_cfg_string(lcfg, 1);
+               param = lustre_cfg_string(lcfg, 3);
+               rc = mgs_nodemap_cmd(env, mgs, cmd, nodemap_name, param);
+               break;
+       default:
+               rc = -ENOTTY;
+       }
+
+       if (rc != 0) {
+               CERROR("%s: OBD_IOC_NODEMAP command %X for %s: rc = %d\n",
+                      mgs->mgs_obd->obd_name, lcfg->lcfg_command,
+                      nodemap_name, rc);
+               GOTO(out_lcfg, rc);
+       }
+
+out_lcfg:
+       OBD_FREE(lcfg, data->ioc_plen1);
+out:
+       RETURN(rc);
+}
+
 static int mgs_iocontrol_pool(const struct lu_env *env,
                              struct mgs_device *mgs,
                               struct obd_ioctl_data *data)
@@ -784,8 +929,12 @@ out_free:
                rc = mgs_iocontrol_pool(&env, mgs, data);
                break;
 
-        case OBD_IOC_DUMP_LOG: {
-                struct llog_ctxt *ctxt;
+       case OBD_IOC_NODEMAP:
+               rc = mgs_iocontrol_nodemap(&env, mgs, data);
+               break;
+
+       case OBD_IOC_DUMP_LOG: {
+               struct llog_ctxt *ctxt;
 
                ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
                rc = class_config_dump_llog(&env, ctxt, data->ioc_inlbuf1,
@@ -795,6 +944,9 @@ out_free:
                break;
         }
 
+       case OBD_IOC_CATLOGLIST:
+               rc = mgs_list_logs(&env, mgs, data);
+               break;
        case OBD_IOC_LLOG_CANCEL:
        case OBD_IOC_LLOG_REMOVE:
         case OBD_IOC_LLOG_CHECK:
@@ -872,7 +1024,20 @@ TGT_OBD_HDL(0,    OBD_PING,       tgt_obd_ping),
 };
 
 static struct tgt_handler mgs_dlm_handlers[] = {
-TGT_DLM_HDL(HABEO_CLAVIS,      LDLM_ENQUEUE,   tgt_enqueue),
+[LDLM_ENQUEUE - LDLM_FIRST_OPC] = {
+       .th_name = "LDLM_ENQUEUE",
+       /* don't use th_fail_id for MGS to don't interfere with MDS tests.
+        * * There are no tests for MGS with OBD_FAIL_LDLM_ENQUEUE_NET so it
+        * * is safe. If such tests will be needed we have to distinguish
+        * * MDS and MGS fail ids, e.g use OBD_FAIL_MGS_ENQUEUE_NET for MGS
+        * * instead of common OBD_FAIL_LDLM_ENQUEUE_NET */
+       .th_fail_id = 0,
+       .th_opc = LDLM_ENQUEUE,
+       .th_flags = HABEO_CLAVIS,
+       .th_act = tgt_enqueue,
+       .th_fmt = &RQF_LDLM_ENQUEUE,
+       .th_version = LUSTRE_DLM_VERSION,
+       },
 };
 
 static struct tgt_handler mgs_llog_handlers[] = {
@@ -883,12 +1048,6 @@ TGT_LLOG_HDL_VAR(0,       LLOG_ORIGIN_HANDLE_CLOSE,       tgt_llog_close),
 TGT_LLOG_HDL    (0,    LLOG_ORIGIN_HANDLE_PREV_BLOCK,  tgt_llog_prev_block),
 };
 
-static struct tgt_handler mgs_sec_ctx_handlers[] = {
-TGT_SEC_HDL_VAR(0,     SEC_CTX_INIT,           mgs_sec_ctx_handle),
-TGT_SEC_HDL_VAR(0,     SEC_CTX_INIT_CONT,      mgs_sec_ctx_handle),
-TGT_SEC_HDL_VAR(0,     SEC_CTX_FINI,           mgs_sec_ctx_handle),
-};
-
 static struct tgt_opc_slice mgs_common_slice[] = {
        {
                .tos_opc_start = MGS_FIRST_OPC,
@@ -913,7 +1072,7 @@ static struct tgt_opc_slice mgs_common_slice[] = {
        {
                .tos_opc_start = SEC_FIRST_OPC,
                .tos_opc_end   = SEC_LAST_OPC,
-               .tos_hs        = mgs_sec_ctx_handlers
+               .tos_hs        = tgt_sec_ctx_handlers
        },
        {
                .tos_hs        = NULL
@@ -927,6 +1086,7 @@ static int mgs_init0(const struct lu_env *env, struct mgs_device *mgs,
        struct obd_device               *obd;
        struct lustre_mount_info        *lmi;
        struct llog_ctxt                *ctxt;
+       struct fs_db                    *fsdb = NULL;
        int                              rc;
 
        ENTRY;
@@ -998,6 +1158,14 @@ static int mgs_init0(const struct lu_env *env, struct mgs_device *mgs,
                GOTO(err_llog, rc);
        }
 
+       /* Setup params fsdb and log, so that other servers can make a local
+        * copy successfully when they are mounted. See LU-4783 */
+       rc = mgs_params_fsdb_setup(env, mgs, fsdb);
+       if (rc)
+               /* params fsdb and log can be setup later */
+               CERROR("%s: %s fsdb and log setup failed: rc = %d\n",
+                      obd->obd_name, PARAMS_FILENAME, rc);
+
        ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
                           "mgs_ldlm_client", &obd->obd_ldlm_client);
 
@@ -1041,6 +1209,7 @@ static int mgs_init0(const struct lu_env *env, struct mgs_device *mgs,
        lu_site_purge(env, mgs2lu_dev(mgs)->ld_site, ~0);
        RETURN(0);
 err_lproc:
+       mgs_params_fsdb_cleanup(env, mgs);
        lproc_mgs_cleanup(mgs);
 err_llog:
        ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
@@ -1066,7 +1235,7 @@ err_ops:
        obd_disconnect(mgs->mgs_bottom_exp);
 err_lmi:
        if (lmi)
-               server_put_mount(lustre_cfg_string(lcfg, 0), lmi->lmi_mnt);
+               server_put_mount(lustre_cfg_string(lcfg, 0), true);
        RETURN(rc);
 }
 
@@ -1214,6 +1383,7 @@ static struct lu_device *mgs_device_fini(const struct lu_env *env,
        obd_zombie_barrier();
 
        tgt_fini(env, &mgs->mgs_lut);
+       mgs_params_fsdb_cleanup(env, mgs);
        mgs_cleanup_fsdb_list(mgs);
        lproc_mgs_cleanup(mgs);
 
@@ -1237,7 +1407,7 @@ static struct lu_device *mgs_device_fini(const struct lu_env *env,
        LASSERT(mgs->mgs_bottom_exp);
        obd_disconnect(mgs->mgs_bottom_exp);
 
-       server_put_mount(obd->obd_name, NULL);
+       server_put_mount(obd->obd_name, true);
 
        RETURN(NULL);
 }
@@ -1358,13 +1528,8 @@ static struct obd_ops mgs_obd_device_ops = {
 
 static int __init mgs_init(void)
 {
-       struct lprocfs_static_vars lvars;
-
-       lprocfs_mgs_init_vars(&lvars);
-       class_register_type(&mgs_obd_device_ops, NULL, lvars.module_vars,
-                           LUSTRE_MGS_NAME, &mgs_device_type);
-
-       return 0;
+       return class_register_type(&mgs_obd_device_ops, NULL, true, NULL,
+                                  LUSTRE_MGS_NAME, &mgs_device_type);
 }
 
 static void /*__exit*/ mgs_exit(void)