Whamcloud - gitweb
LU-7623 Update obd iocontrol methods with __user attribute
[fs/lustre-release.git] / lustre / mgs / mgs_handler.c
index 0403483..f1a643e 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2010, 2013, Intel Corporation.
+ * Copyright (c) 2010, 2015, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -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);
@@ -92,11 +94,18 @@ static int mgs_exception(struct tgt_session_info *tsi)
        RETURN(0);
 }
 
+static inline bool str_starts_with(const char *str, const char *prefix)
+{
+       return strncmp(str, prefix, strlen(prefix)) == 0;
+}
+
 static int mgs_set_info(struct tgt_session_info *tsi)
 {
        struct mgs_thread_info  *mgi;
        struct mgs_send_param   *msp, *rep_msp;
        struct lustre_cfg       *lcfg;
+       size_t                   param_len;
+       char                    *s;
        int                      rc;
 
        ENTRY;
@@ -109,10 +118,26 @@ static int mgs_set_info(struct tgt_session_info *tsi)
        if (msp == NULL)
                RETURN(err_serious(-EFAULT));
 
+       param_len = strnlen(msp->mgs_param, sizeof(msp->mgs_param));
+       if (param_len == 0 || param_len == sizeof(msp->mgs_param))
+               RETURN(-EINVAL);
+
+       /* We only allow '*.lov.stripe{size,count,offset}=*' from an RPC. */
+       s = strchr(msp->mgs_param, '.');
+       if (s == NULL)
+               RETURN(-EINVAL);
+
+       if (!str_starts_with(s + 1, "lov.stripesize=") &&
+           !str_starts_with(s + 1, "lov.stripecount=") &&
+           !str_starts_with(s + 1, "lov.stripeoffset="))
+               RETURN(-EINVAL);
+
        /* Construct lustre_cfg structure to pass to function mgs_setparam */
        lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
        lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, msp->mgs_param);
        lcfg = lustre_cfg_new(LCFG_PARAM, &mgi->mgi_bufs);
+       if (lcfg == NULL)
+               RETURN(-ENOMEM);
 
        rc = mgs_setparam(tsi->tsi_env, exp2mgs_dev(tsi->tsi_exp), lcfg,
                          mgi->mgi_fsname);
@@ -143,8 +168,7 @@ static int mgs_completion_ast_generic(struct ldlm_lock *lock, __u64 flags,
 {
        ENTRY;
 
-       if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
-                      LDLM_FL_BLOCK_CONV))) {
+       if (!(flags & LDLM_FL_BLOCKED_MASK)) {
                struct fs_db *fsdb;
 
                /* l_ast_data is used as a marker to avoid cancel ldlm lock
@@ -538,11 +562,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);
@@ -573,7 +600,7 @@ static inline int mgs_init_export(struct obd_export *exp)
 
        /* 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;
@@ -625,7 +652,6 @@ static int mgs_iocontrol_nodemap(const struct lu_env *env,
                                 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;
@@ -633,8 +659,9 @@ static int mgs_iocontrol_nodemap(const struct lu_env *env,
        const char              *idtype_str = NULL;
        char                    *param = NULL;
        char                    fs_idstr[16];
+       char                    name_buf[LUSTRE_NODEMAP_NAME_LENGTH + 1];
        int                     rc = 0;
-       __u32                   client_id;
+       unsigned long           client_id;
        __u32                   fs_id;
        __u32                   cmd;
        int                     idtype;
@@ -681,10 +708,10 @@ static int mgs_iocontrol_nodemap(const struct lu_env *env,
                        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)
+               nodemap_test_nid(nid, name_buf, sizeof(name_buf));
+               rc = copy_to_user(data->ioc_pbuf1, name_buf,
+                                 MIN(data->ioc_plen1, sizeof(name_buf)));
+               if (rc != 0)
                        GOTO(out_lcfg, rc = -EFAULT);
                break;
        case LCFG_NODEMAP_TEST_ID:
@@ -695,16 +722,16 @@ static int mgs_iocontrol_nodemap(const struct lu_env *env,
                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);
+               rc = kstrtoul(client_idstr, 10, &client_id);
+               if (rc != 0)
+                       GOTO(out_lcfg, rc = -EINVAL);
+
+               fs_id = nodemap_test_id(nid, idtype, client_id);
 
                if (data->ioc_plen1 < sizeof(fs_idstr))
                        GOTO(out_lcfg, rc = -EINVAL);
@@ -835,8 +862,8 @@ out_pool:
 }
 
 /* from mdt_iocontrol */
-int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
-                  void *karg, void *uarg)
+static int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
+                        void *karg, void __user *uarg)
 {
        struct mgs_device *mgs = exp2mgs_dev(exp);
         struct obd_ioctl_data *data = karg;
@@ -929,17 +956,6 @@ out_free:
                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,
-                                           NULL);
-                llog_ctxt_put(ctxt);
-
-               break;
-        }
-
        case OBD_IOC_CATLOGLIST:
                rc = mgs_list_logs(&env, mgs, data);
                break;
@@ -1083,6 +1099,7 @@ static int mgs_init0(const struct lu_env *env, struct mgs_device *mgs,
        struct lustre_mount_info        *lmi;
        struct llog_ctxt                *ctxt;
        struct fs_db                    *fsdb = NULL;
+       struct fs_db                    *fsdb_srpc = NULL;
        int                              rc;
 
        ENTRY;
@@ -1146,6 +1163,7 @@ static int mgs_init0(const struct lu_env *env, struct mgs_device *mgs,
        mutex_init(&mgs->mgs_mutex);
        mgs->mgs_start_time = cfs_time_current_sec();
        spin_lock_init(&mgs->mgs_lock);
+       mutex_init(&mgs->mgs_health_mutex);
 
        rc = lproc_mgs_setup(mgs, lustre_cfg_string(lcfg, 3));
        if (rc != 0) {
@@ -1162,6 +1180,9 @@ static int mgs_init0(const struct lu_env *env, struct mgs_device *mgs,
                CERROR("%s: %s fsdb and log setup failed: rc = %d\n",
                       obd->obd_name, PARAMS_FILENAME, rc);
 
+       /* Setup _mgs fsdb, useful for srpc */
+       mgs__mgs_fsdb_setup(env, mgs, fsdb_srpc);
+
        ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
                           "mgs_ldlm_client", &obd->obd_ldlm_client);
 
@@ -1231,7 +1252,7 @@ err_ops:
        obd_disconnect(mgs->mgs_bottom_exp);
 err_lmi:
        if (lmi)
-               server_put_mount(lustre_cfg_string(lcfg, 0));
+               server_put_mount(lustre_cfg_string(lcfg, 0), true);
        RETURN(rc);
 }
 
@@ -1296,15 +1317,15 @@ static int mgs_object_print(const struct lu_env *env, void *cookie,
        return (*p)(env, cookie, LUSTRE_MGS_NAME"-object@%p", o);
 }
 
-struct lu_object_operations mgs_lu_obj_ops = {
+static struct lu_object_operations mgs_lu_obj_ops = {
        .loo_object_init        = mgs_object_init,
        .loo_object_free        = mgs_object_free,
        .loo_object_print       = mgs_object_print,
 };
 
-struct lu_object *mgs_object_alloc(const struct lu_env *env,
-                                  const struct lu_object_header *hdr,
-                                  struct lu_device *d)
+static struct lu_object *mgs_object_alloc(const struct lu_env *env,
+                                         const struct lu_object_header *hdr,
+                                         struct lu_device *d)
 {
        struct lu_object_header *h;
        struct mgs_object       *o;
@@ -1373,14 +1394,18 @@ static struct lu_device *mgs_device_fini(const struct lu_env *env,
 
        ping_evictor_stop();
 
+       mutex_lock(&mgs->mgs_health_mutex);
        ptlrpc_unregister_service(mgs->mgs_service);
+       mutex_unlock(&mgs->mgs_health_mutex);
+
+       mgs_params_fsdb_cleanup(env, mgs);
+       mgs_cleanup_fsdb_list(mgs);
 
+       ldlm_namespace_free_prior(obd->obd_namespace, NULL, 1);
        obd_exports_barrier(obd);
        obd_zombie_barrier();
 
        tgt_fini(env, &mgs->mgs_lut);
-       mgs_params_fsdb_cleanup(env, mgs);
-       mgs_cleanup_fsdb_list(mgs);
        lproc_mgs_cleanup(mgs);
 
        ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
@@ -1391,7 +1416,7 @@ static struct lu_device *mgs_device_fini(const struct lu_env *env,
 
        mgs_fs_cleanup(env, mgs);
 
-       ldlm_namespace_free(obd->obd_namespace, NULL, 1);
+       ldlm_namespace_free_post(obd->obd_namespace);
        obd->obd_namespace = NULL;
 
        lu_site_purge(env, d->ld_site, ~0);
@@ -1403,7 +1428,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);
+       server_put_mount(obd->obd_name, true);
 
        RETURN(NULL);
 }
@@ -1511,6 +1536,18 @@ static int mgs_obd_disconnect(struct obd_export *exp)
        RETURN(rc);
 }
 
+static int mgs_health_check(const struct lu_env *env, struct obd_device *obd)
+{
+       struct mgs_device *mgs = lu2mgs_dev(obd->obd_lu_dev);
+       int rc = 0;
+
+       mutex_lock(&mgs->mgs_health_mutex);
+       rc |= ptlrpc_service_health_check(mgs->mgs_service);
+       mutex_unlock(&mgs->mgs_health_mutex);
+
+       return rc != 0 ? 1 : 0;
+}
+
 /* use obd ops to offer management infrastructure */
 static struct obd_ops mgs_obd_device_ops = {
        .o_owner                = THIS_MODULE,
@@ -1520,24 +1557,23 @@ static struct obd_ops mgs_obd_device_ops = {
        .o_init_export          = mgs_init_export,
        .o_destroy_export       = mgs_destroy_export,
        .o_iocontrol            = mgs_iocontrol,
+       .o_health_check         = mgs_health_check,
 };
 
 static int __init mgs_init(void)
 {
        return class_register_type(&mgs_obd_device_ops, NULL, true, NULL,
-#ifndef HAVE_ONLY_PROCFS_SEQ
-                                  NULL,
-#endif
                                   LUSTRE_MGS_NAME, &mgs_device_type);
 }
 
-static void /*__exit*/ mgs_exit(void)
+static void __exit mgs_exit(void)
 {
        class_unregister_type(LUSTRE_MGS_NAME);
 }
 
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
-MODULE_DESCRIPTION("Lustre  Management Server (MGS)");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
+MODULE_DESCRIPTION("Lustre Management Server (MGS)");
+MODULE_VERSION(LUSTRE_VERSION_STRING);
 MODULE_LICENSE("GPL");
 
 module_init(mgs_init);