Whamcloud - gitweb
LU-2309 config: ignore unknown configuration param
[fs/lustre-release.git] / lustre / obdclass / obd_config.c
index 4c2cf37..a9c1ceb 100644 (file)
@@ -1,6 +1,4 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
  * GPL HEADER START
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -29,8 +27,7 @@
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011 Whamcloud, Inc.
- *
+ * Copyright (c) 2011, 2012, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
 #include <linux/string.h>
 #else
 #include <liblustre.h>
+#include <string.h>
 #include <obd_class.h>
 #include <obd.h>
 #endif
 #include <lustre_log.h>
 #include <lprocfs_status.h>
-#include <libcfs/list.h>
 #include <lustre_param.h>
 
+#include "llog_internal.h"
+
 static cfs_hash_ops_t uuid_hash_ops;
 static cfs_hash_ops_t nid_hash_ops;
 static cfs_hash_ops_t nid_stat_hash_ops;
@@ -77,6 +76,48 @@ int class_find_param(char *buf, char *key, char **valp)
 
         return 0;
 }
+EXPORT_SYMBOL(class_find_param);
+
+/**
+ * Check whether the proc parameter \a param is an old parameter or not from
+ * the array \a ptr which contains the mapping from old parameters to new ones.
+ * If it's an old one, then return the pointer to the cfg_interop_param struc-
+ * ture which contains both the old and new parameters.
+ *
+ * \param param                        proc parameter
+ * \param ptr                  an array which contains the mapping from
+ *                             old parameters to new ones
+ *
+ * \retval valid-pointer       pointer to the cfg_interop_param structure
+ *                             which contains the old and new parameters
+ * \retval NULL                        \a param or \a ptr is NULL,
+ *                             or \a param is not an old parameter
+ */
+struct cfg_interop_param *class_find_old_param(const char *param,
+                                              struct cfg_interop_param *ptr)
+{
+       char *value = NULL;
+       int   name_len = 0;
+
+       if (param == NULL || ptr == NULL)
+               RETURN(NULL);
+
+       value = strchr(param, '=');
+       if (value == NULL)
+               name_len = strlen(param);
+       else
+               name_len = value - param;
+
+       while (ptr->old_param != NULL) {
+               if (strncmp(param, ptr->old_param, name_len) == 0 &&
+                   name_len == strlen(ptr->old_param))
+                       RETURN(ptr);
+               ptr++;
+       }
+
+       RETURN(NULL);
+}
+EXPORT_SYMBOL(class_find_old_param);
 
 /**
  * Finds a parameter in \a params and copies it to \a copy.
@@ -143,6 +184,7 @@ int class_get_next_param(char **params, char *copy)
         }
         return 1;
 }
+EXPORT_SYMBOL(class_get_next_param);
 
 /* returns 0 if this is the first key in the buffer, else 1.
    valp points to first char after key. */
@@ -159,8 +201,9 @@ int class_match_param(char *buf, char *key, char **valp)
 
         return 0;
 }
+EXPORT_SYMBOL(class_match_param);
 
-static int parse_nid(char *buf, void *value)
+static int parse_nid(char *buf, void *value, int quiet)
 {
         lnet_nid_t *nid = (lnet_nid_t *)value;
 
@@ -168,7 +211,8 @@ static int parse_nid(char *buf, void *value)
         if (*nid != LNET_NID_ANY)
                 return 0;
 
-        LCONSOLE_ERROR_MSG(0x159, "Can't parse NID '%s'\n", buf);
+       if (!quiet)
+               LCONSOLE_ERROR_MSG(0x159, "Can't parse NID '%s'\n", buf);
         return -EINVAL;
 }
 
@@ -190,7 +234,8 @@ enum {
    1 not found
    < 0 error
    endh is set to next separator */
-static int class_parse_value(char *buf, int opc, void *value, char **endh)
+static int class_parse_value(char *buf, int opc, void *value, char **endh,
+                            int quiet)
 {
         char *endp;
         char  tmp;
@@ -214,7 +259,7 @@ static int class_parse_value(char *buf, int opc, void *value, char **endh)
         default:
                 LBUG();
         case CLASS_PARSE_NID:
-                rc = parse_nid(buf, value);
+               rc = parse_nid(buf, value, quiet);
                 break;
         case CLASS_PARSE_NET:
                 rc = parse_net(buf, value);
@@ -230,13 +275,21 @@ static int class_parse_value(char *buf, int opc, void *value, char **endh)
 
 int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh)
 {
-        return class_parse_value(buf, CLASS_PARSE_NID, (void *)nid, endh);
+       return class_parse_value(buf, CLASS_PARSE_NID, (void *)nid, endh, 0);
 }
+EXPORT_SYMBOL(class_parse_nid);
+
+int class_parse_nid_quiet(char *buf, lnet_nid_t *nid, char **endh)
+{
+       return class_parse_value(buf, CLASS_PARSE_NID, (void *)nid, endh, 1);
+}
+EXPORT_SYMBOL(class_parse_nid_quiet);
 
 int class_parse_net(char *buf, __u32 *net, char **endh)
 {
-        return class_parse_value(buf, CLASS_PARSE_NET, (void *)net, endh);
+       return class_parse_value(buf, CLASS_PARSE_NET, (void *)net, endh, 0);
 }
+EXPORT_SYMBOL(class_parse_net);
 
 /* 1 param contains key and match
  * 0 param contains key and not match
@@ -258,6 +311,7 @@ int class_match_nid(char *buf, char *key, lnet_nid_t nid)
         }
         return rc;
 }
+EXPORT_SYMBOL(class_match_nid);
 
 int class_match_net(char *buf, char *key, __u32 net)
 {
@@ -275,13 +329,6 @@ int class_match_net(char *buf, char *key, __u32 net)
         }
         return rc;
 }
-
-EXPORT_SYMBOL(class_find_param);
-EXPORT_SYMBOL(class_get_next_param);
-EXPORT_SYMBOL(class_match_param);
-EXPORT_SYMBOL(class_parse_nid);
-EXPORT_SYMBOL(class_parse_net);
-EXPORT_SYMBOL(class_match_nid);
 EXPORT_SYMBOL(class_match_net);
 
 /********************** class fns **********************/
@@ -335,28 +382,28 @@ int class_attach(struct lustre_cfg *lcfg)
         LASSERTF(strncmp(obd->obd_name, name, strlen(name)) == 0,
                  "%p obd_name %s != %s\n", obd, obd->obd_name, name);
 
-        cfs_rwlock_init(&obd->obd_pool_lock);
-        obd->obd_pool_limit = 0;
-        obd->obd_pool_slv = 0;
-
-        CFS_INIT_LIST_HEAD(&obd->obd_exports);
-        CFS_INIT_LIST_HEAD(&obd->obd_unlinked_exports);
-        CFS_INIT_LIST_HEAD(&obd->obd_delayed_exports);
-        CFS_INIT_LIST_HEAD(&obd->obd_exports_timed);
-        CFS_INIT_LIST_HEAD(&obd->obd_nid_stats);
-        cfs_spin_lock_init(&obd->obd_nid_lock);
-        cfs_spin_lock_init(&obd->obd_dev_lock);
-        cfs_sema_init(&obd->obd_dev_sem, 1);
-        cfs_spin_lock_init(&obd->obd_osfs_lock);
-        /* obd->obd_osfs_age must be set to a value in the distant
-         * past to guarantee a fresh statfs is fetched on mount. */
-        obd->obd_osfs_age = cfs_time_shift_64(-1000);
-
-        /* XXX belongs in setup not attach  */
-        cfs_init_rwsem(&obd->obd_observer_link_sem);
-        /* recovery data */
-        cfs_init_timer(&obd->obd_recovery_timer);
-        cfs_spin_lock_init(&obd->obd_recovery_task_lock);
+       rwlock_init(&obd->obd_pool_lock);
+       obd->obd_pool_limit = 0;
+       obd->obd_pool_slv = 0;
+
+       CFS_INIT_LIST_HEAD(&obd->obd_exports);
+       CFS_INIT_LIST_HEAD(&obd->obd_unlinked_exports);
+       CFS_INIT_LIST_HEAD(&obd->obd_delayed_exports);
+       CFS_INIT_LIST_HEAD(&obd->obd_exports_timed);
+       CFS_INIT_LIST_HEAD(&obd->obd_nid_stats);
+       spin_lock_init(&obd->obd_nid_lock);
+       spin_lock_init(&obd->obd_dev_lock);
+       mutex_init(&obd->obd_dev_mutex);
+       spin_lock_init(&obd->obd_osfs_lock);
+       /* obd->obd_osfs_age must be set to a value in the distant
+        * past to guarantee a fresh statfs is fetched on mount. */
+       obd->obd_osfs_age = cfs_time_shift_64(-1000);
+
+       /* XXX belongs in setup not attach  */
+       init_rwsem(&obd->obd_observer_link_sem);
+       /* recovery data */
+       cfs_init_timer(&obd->obd_recovery_timer);
+       spin_lock_init(&obd->obd_recovery_task_lock);
         cfs_waitq_init(&obd->obd_next_transno_waitq);
         cfs_waitq_init(&obd->obd_evict_inprogress_waitq);
         CFS_INIT_LIST_HEAD(&obd->obd_req_replay_queue);
@@ -366,6 +413,8 @@ int class_attach(struct lustre_cfg *lcfg)
 
         llog_group_init(&obd->obd_olg, FID_SEQ_LLOG);
 
+       obd->obd_conn_inprogress = 0;
+
         len = strlen(uuid);
         if (len >= sizeof(obd->obd_uuid)) {
                 CERROR("uuid must be < %d bytes long\n",
@@ -382,9 +431,9 @@ int class_attach(struct lustre_cfg *lcfg)
         }
 
         /* Detach drops this */
-        cfs_spin_lock(&obd->obd_dev_lock);
-        cfs_atomic_set(&obd->obd_refcount, 1);
-        cfs_spin_unlock(&obd->obd_dev_lock);
+       spin_lock(&obd->obd_dev_lock);
+       cfs_atomic_set(&obd->obd_refcount, 1);
+       spin_unlock(&obd->obd_dev_lock);
         lu_ref_init(&obd->obd_reference);
         lu_ref_add(&obd->obd_reference, "attach", obd);
 
@@ -398,6 +447,7 @@ int class_attach(struct lustre_cfg *lcfg)
         }
         return rc;
 }
+EXPORT_SYMBOL(class_attach);
 
 /** Create hashes, self-export, and call type-specific setup.
  * Setup is effectively the "start this obd" call.
@@ -429,9 +479,9 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
         }
 
         /* is someone else setting us up right now? (attach inits spinlock) */
-        cfs_spin_lock(&obd->obd_dev_lock);
-        if (obd->obd_starting) {
-                cfs_spin_unlock(&obd->obd_dev_lock);
+       spin_lock(&obd->obd_dev_lock);
+       if (obd->obd_starting) {
+               spin_unlock(&obd->obd_dev_lock);
                 CERROR("Device %d setup in progress (type %s)\n",
                        obd->obd_minor, obd->obd_type->typ_name);
                 RETURN(-EEXIST);
@@ -442,7 +492,7 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
         obd->obd_uuid_hash = NULL;
         obd->obd_nid_hash = NULL;
         obd->obd_nid_stats_hash = NULL;
-        cfs_spin_unlock(&obd->obd_dev_lock);
+       spin_unlock(&obd->obd_dev_lock);
 
         /* create an uuid-export lustre hash */
         obd->obd_uuid_hash = cfs_hash_create("UUID_HASH",
@@ -491,10 +541,10 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 
         obd->obd_set_up = 1;
 
-        cfs_spin_lock(&obd->obd_dev_lock);
-        /* cleanup drops this */
-        class_incref(obd, "setup", obd);
-        cfs_spin_unlock(&obd->obd_dev_lock);
+       spin_lock(&obd->obd_dev_lock);
+       /* cleanup drops this */
+       class_incref(obd, "setup", obd);
+       spin_unlock(&obd->obd_dev_lock);
 
         CDEBUG(D_IOCTL, "finished setup of obd %s (uuid %s)\n",
                obd->obd_name, obd->obd_uuid.uuid);
@@ -522,6 +572,7 @@ err_hash:
         CERROR("setup %s failed (%d)\n", obd->obd_name, err);
         return err;
 }
+EXPORT_SYMBOL(class_setup);
 
 /** We have finished using this obd and are ready to destroy it.
  * There can be no more references to this obd.
@@ -535,14 +586,14 @@ int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
                 RETURN(-EBUSY);
         }
 
-        cfs_spin_lock(&obd->obd_dev_lock);
-        if (!obd->obd_attached) {
-                cfs_spin_unlock(&obd->obd_dev_lock);
-                CERROR("OBD device %d not attached\n", obd->obd_minor);
-                RETURN(-ENODEV);
-        }
-        obd->obd_attached = 0;
-        cfs_spin_unlock(&obd->obd_dev_lock);
+       spin_lock(&obd->obd_dev_lock);
+       if (!obd->obd_attached) {
+               spin_unlock(&obd->obd_dev_lock);
+               CERROR("OBD device %d not attached\n", obd->obd_minor);
+               RETURN(-ENODEV);
+       }
+       obd->obd_attached = 0;
+       spin_unlock(&obd->obd_dev_lock);
 
         CDEBUG(D_IOCTL, "detach on obd %s (uuid %s)\n",
                obd->obd_name, obd->obd_uuid.uuid);
@@ -550,6 +601,7 @@ int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
         class_decref(obd, "attach", obd);
         RETURN(0);
 }
+EXPORT_SYMBOL(class_detach);
 
 /** Start shutting down the obd.  There may be in-progess ops when
  * this is called.  We tell them to start shutting down with a call
@@ -568,15 +620,24 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
                 RETURN(-ENODEV);
         }
 
-        cfs_spin_lock(&obd->obd_dev_lock);
-        if (obd->obd_stopping) {
-                cfs_spin_unlock(&obd->obd_dev_lock);
-                CERROR("OBD %d already stopping\n", obd->obd_minor);
-                RETURN(-ENODEV);
-        }
-        /* Leave this on forever */
-        obd->obd_stopping = 1;
-        cfs_spin_unlock(&obd->obd_dev_lock);
+       spin_lock(&obd->obd_dev_lock);
+       if (obd->obd_stopping) {
+               spin_unlock(&obd->obd_dev_lock);
+               CERROR("OBD %d already stopping\n", obd->obd_minor);
+               RETURN(-ENODEV);
+       }
+       /* Leave this on forever */
+       obd->obd_stopping = 1;
+
+       /* wait for already-arrived-connections to finish. */
+       while (obd->obd_conn_inprogress > 0) {
+               spin_unlock(&obd->obd_dev_lock);
+
+               cfs_cond_resched();
+
+               spin_lock(&obd->obd_dev_lock);
+       }
+       spin_unlock(&obd->obd_dev_lock);
 
         if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) {
                 for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++)
@@ -644,6 +705,7 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
 
         RETURN(0);
 }
+EXPORT_SYMBOL(class_cleanup);
 
 struct obd_device *class_incref(struct obd_device *obd,
                                 const char *scope, const void *source)
@@ -655,27 +717,28 @@ struct obd_device *class_incref(struct obd_device *obd,
 
         return obd;
 }
+EXPORT_SYMBOL(class_incref);
 
 void class_decref(struct obd_device *obd, const char *scope, const void *source)
 {
-        int err;
-        int refs;
+       int err;
+       int refs;
 
-        cfs_spin_lock(&obd->obd_dev_lock);
-        cfs_atomic_dec(&obd->obd_refcount);
-        refs = cfs_atomic_read(&obd->obd_refcount);
-        cfs_spin_unlock(&obd->obd_dev_lock);
-        lu_ref_del(&obd->obd_reference, scope, source);
+       spin_lock(&obd->obd_dev_lock);
+       cfs_atomic_dec(&obd->obd_refcount);
+       refs = cfs_atomic_read(&obd->obd_refcount);
+       spin_unlock(&obd->obd_dev_lock);
+       lu_ref_del(&obd->obd_reference, scope, source);
 
-        CDEBUG(D_INFO, "Decref %s (%p) now %d\n", obd->obd_name, obd, refs);
+       CDEBUG(D_INFO, "Decref %s (%p) now %d\n", obd->obd_name, obd, refs);
 
-        if ((refs == 1) && obd->obd_stopping) {
-                /* All exports have been destroyed; there should
-                   be no more in-progress ops by this point.*/
+       if ((refs == 1) && obd->obd_stopping) {
+               /* All exports have been destroyed; there should
+                  be no more in-progress ops by this point.*/
 
-                cfs_spin_lock(&obd->obd_self_export->exp_lock);
-                obd->obd_self_export->exp_flags |= exp_flags_from_obd(obd);
-                cfs_spin_unlock(&obd->obd_self_export->exp_lock);
+               spin_lock(&obd->obd_self_export->exp_lock);
+               obd->obd_self_export->exp_flags |= exp_flags_from_obd(obd);
+               spin_unlock(&obd->obd_self_export->exp_lock);
 
                 /* note that we'll recurse into class_decref again */
                 class_unlink_export(obd->obd_self_export);
@@ -701,6 +764,7 @@ void class_decref(struct obd_device *obd, const char *scope, const void *source)
                 class_release_dev(obd);
         }
 }
+EXPORT_SYMBOL(class_decref);
 
 /** Add a failover nid location.
  * Client obd types contact server obd types using this nid list.
@@ -719,6 +783,7 @@ int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
         }
         if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
             strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) &&
+           strcmp(obd->obd_type->typ_name, LUSTRE_OSP_NAME) &&
             strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) {
                 CERROR("can't add connection on non-client dev\n");
                 RETURN(-EINVAL);
@@ -735,6 +800,7 @@ int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
 
         RETURN(rc);
 }
+EXPORT_SYMBOL(class_add_conn);
 
 /** Remove a failover nid location.
  */
@@ -782,6 +848,7 @@ struct lustre_profile *class_get_profile(const char * prof)
         }
         RETURN(NULL);
 }
+EXPORT_SYMBOL(class_get_profile);
 
 /** Create a named "profile".
  * This defines the mdc and osc names to use for a client.
@@ -853,6 +920,7 @@ void class_del_profile(const char *prof)
         }
         EXIT;
 }
+EXPORT_SYMBOL(class_del_profile);
 
 /* COMPAT_146 */
 void class_del_profiles(void)
@@ -870,32 +938,36 @@ void class_del_profiles(void)
         }
         EXIT;
 }
+EXPORT_SYMBOL(class_del_profiles);
 
-static int class_set_global(char *ptr, int val) {
-        ENTRY;
-
-        if (class_match_param(ptr, PARAM_AT_MIN, NULL) == 0)
-            at_min = val;
-        else if (class_match_param(ptr, PARAM_AT_MAX, NULL) == 0)
-                at_max = val;
-        else if (class_match_param(ptr, PARAM_AT_EXTRA, NULL) == 0)
-                at_extra = val;
-        else if (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, NULL) == 0)
-                at_early_margin = val;
-        else if (class_match_param(ptr, PARAM_AT_HISTORY, NULL) == 0)
-                at_history = val;
-        else
-                RETURN(-EINVAL);
-
-        CDEBUG(D_IOCTL, "global %s = %d\n", ptr, val);
-
-        RETURN(0);
+static int class_set_global(char *ptr, int val, struct lustre_cfg *lcfg)
+{
+       ENTRY;
+       if (class_match_param(ptr, PARAM_AT_MIN, NULL) == 0)
+               at_min = val;
+       else if (class_match_param(ptr, PARAM_AT_MAX, NULL) == 0)
+               at_max = val;
+       else if (class_match_param(ptr, PARAM_AT_EXTRA, NULL) == 0)
+               at_extra = val;
+       else if (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, NULL) == 0)
+               at_early_margin = val;
+       else if (class_match_param(ptr, PARAM_AT_HISTORY, NULL) == 0)
+               at_history = val;
+       else if (class_match_param(ptr, PARAM_JOBID_VAR, NULL) == 0)
+               strlcpy(obd_jobid_var, lustre_cfg_string(lcfg, 2),
+                       JOBSTATS_JOBID_VAR_MAX_LEN + 1);
+       else
+               RETURN(-EINVAL);
+
+       CDEBUG(D_IOCTL, "global %s = %d\n", ptr, val);
+       RETURN(0);
 }
 
 
-/* We can't call ll_process_config directly because it lives in a module that
  must be loaded after this one. */
+/* We can't call ll_process_config or lquota_process_config directly because
* it lives in a module that must be loaded after this one. */
 static int (*client_process_config)(struct lustre_cfg *lcfg) = NULL;
+static int (*quota_process_config)(struct lustre_cfg *lcfg) = NULL;
 
 void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg))
 {
@@ -903,6 +975,85 @@ void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg))
 }
 EXPORT_SYMBOL(lustre_register_client_process_config);
 
+/**
+ * Rename the proc parameter in \a cfg with a new name \a new_name.
+ *
+ * \param cfg     config structure which contains the proc parameter
+ * \param new_name new name of the proc parameter
+ *
+ * \retval valid-pointer    pointer to the newly-allocated config structure
+ *                         which contains the renamed proc parameter
+ * \retval ERR_PTR(-EINVAL) if \a cfg or \a new_name is NULL, or \a cfg does
+ *                         not contain a proc parameter
+ * \retval ERR_PTR(-ENOMEM) if memory allocation failure occurs
+ */
+struct lustre_cfg *lustre_cfg_rename(struct lustre_cfg *cfg,
+                                    const char *new_name)
+{
+       struct lustre_cfg_bufs  *bufs = NULL;
+       struct lustre_cfg       *new_cfg = NULL;
+       char                    *param = NULL;
+       char                    *new_param = NULL;
+       char                    *value = NULL;
+       int                      name_len = 0;
+       int                      new_len = 0;
+       ENTRY;
+
+       if (cfg == NULL || new_name == NULL)
+               RETURN(ERR_PTR(-EINVAL));
+
+       param = lustre_cfg_string(cfg, 1);
+       if (param == NULL)
+               RETURN(ERR_PTR(-EINVAL));
+
+       value = strchr(param, '=');
+       if (value == NULL)
+               name_len = strlen(param);
+       else
+               name_len = value - param;
+
+       new_len = LUSTRE_CFG_BUFLEN(cfg, 1) + strlen(new_name) - name_len;
+
+       OBD_ALLOC(new_param, new_len);
+       if (new_param == NULL)
+               RETURN(ERR_PTR(-ENOMEM));
+
+       strcpy(new_param, new_name);
+       if (value != NULL)
+               strcat(new_param, value);
+
+       OBD_ALLOC_PTR(bufs);
+       if (bufs == NULL) {
+               OBD_FREE(new_param, new_len);
+               RETURN(ERR_PTR(-ENOMEM));
+       }
+
+       lustre_cfg_bufs_reset(bufs, NULL);
+       lustre_cfg_bufs_init(bufs, cfg);
+       lustre_cfg_bufs_set_string(bufs, 1, new_param);
+
+       new_cfg = lustre_cfg_new(cfg->lcfg_command, bufs);
+
+       OBD_FREE(new_param, new_len);
+       OBD_FREE_PTR(bufs);
+       if (new_cfg == NULL)
+               RETURN(ERR_PTR(-ENOMEM));
+
+       new_cfg->lcfg_num = cfg->lcfg_num;
+       new_cfg->lcfg_flags = cfg->lcfg_flags;
+       new_cfg->lcfg_nid = cfg->lcfg_nid;
+       new_cfg->lcfg_nal = cfg->lcfg_nal;
+
+       RETURN(new_cfg);
+}
+EXPORT_SYMBOL(lustre_cfg_rename);
+
+void lustre_register_quota_process_config(int (*qpc)(struct lustre_cfg *lcfg))
+{
+       quota_process_config = qpc;
+}
+EXPORT_SYMBOL(lustre_register_quota_process_config);
+
 /** Process configuration commands given in lustre_cfg form.
  * These may come from direct calls (e.g. class_manual_cleanup)
  * or processing the config llog, or ioctl from lctl.
@@ -962,6 +1113,7 @@ int class_process_config(struct lustre_cfg *lcfg)
                 CDEBUG(D_IOCTL, "changing lustre timeout from %d to %d\n",
                        obd_timeout, lcfg->lcfg_num);
                 obd_timeout = max(lcfg->lcfg_num, 1U);
+               obd_timeout_set = 1;
                 GOTO(out, err = 0);
         }
         case LCFG_SET_LDLM_TIMEOUT: {
@@ -970,7 +1122,7 @@ int class_process_config(struct lustre_cfg *lcfg)
                 ldlm_timeout = max(lcfg->lcfg_num, 1U);
                 if (ldlm_timeout >= obd_timeout)
                         ldlm_timeout = max(obd_timeout / 3, 1U);
-
+               ldlm_timeout_set = 1;
                 GOTO(out, err = 0);
         }
         case LCFG_SET_UPCALL: {
@@ -996,14 +1148,21 @@ int class_process_config(struct lustre_cfg *lcfg)
                 } else if ((class_match_param(lustre_cfg_string(lcfg, 1),
                                               PARAM_SYS, &tmp) == 0)) {
                         /* Global param settings */
-                        err = class_set_global(tmp, lcfg->lcfg_num);
-                        /* Note that since LCFG_PARAM is LCFG_REQUIRED, new
-                           unknown globals would cause config to fail */
-                        if (err)
-                                CWARN("Ignoring unknown param %s\n", tmp);
-                        GOTO(out, 0);
-                }
-
+                       err = class_set_global(tmp, lcfg->lcfg_num, lcfg);
+                       /*
+                        * Client or server should not fail to mount if
+                        * it hits an unknown configuration parameter.
+                        */
+                       if (err != 0)
+                               CWARN("Ignoring unknown param %s\n", tmp);
+
+                       GOTO(out, err = 0);
+               } else if ((class_match_param(lustre_cfg_string(lcfg, 1),
+                                             PARAM_QUOTA, &tmp) == 0) &&
+                          quota_process_config) {
+                       err = (*quota_process_config)(lcfg);
+                       GOTO(out, err);
+               }
                 /* Fall through */
                 break;
         }
@@ -1078,6 +1237,7 @@ out:
         }
         return err;
 }
+EXPORT_SYMBOL(class_process_config);
 
 int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
                              struct lustre_cfg *lcfg, void *data)
@@ -1146,12 +1306,12 @@ int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
                         CERROR("writing proc entry %s err %d\n",
                                var->name, rc);
                         rc = 0;
-                } else {
-                        CDEBUG(D_CONFIG, "%s.%.*s: set parameter %.*s=%s\n",
-                                      lustre_cfg_string(lcfg, 0),
-                                      (int)strlen(prefix) - 1, prefix,
-                                      (int)(sval - key - 1), key, sval);
-                }
+               } else {
+                       CDEBUG(D_CONFIG, "%s.%.*s: Set parameter %.*s=%s\n",
+                                        lustre_cfg_string(lcfg, 0),
+                                        (int)strlen(prefix) - 1, prefix,
+                                        (int)(sval - key - 1), key, sval);
+               }
         }
 
         if (rc > 0)
@@ -1165,9 +1325,7 @@ int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
         RETURN(0);
 #endif
 }
-
-int class_config_dump_handler(struct llog_handle * handle,
-                              struct llog_rec_hdr *rec, void *data);
+EXPORT_SYMBOL(class_process_proc_param);
 
 #ifdef __KERNEL__
 extern int lustre_check_exclusion(struct super_block *sb, char *svname);
@@ -1180,8 +1338,9 @@ extern int lustre_check_exclusion(struct super_block *sb, char *svname);
  * records, change uuids, etc), then class_process_config() resulting
  * net records.
  */
-static int class_config_llog_handler(struct llog_handle * handle,
-                                     struct llog_rec_hdr *rec, void *data)
+int class_config_llog_handler(const struct lu_env *env,
+                             struct llog_handle *handle,
+                             struct llog_rec_hdr *rec, void *data)
 {
         struct config_llog_instance *clli = data;
         int cfg_len = rec->lrh_len;
@@ -1277,6 +1436,32 @@ static int class_config_llog_handler(struct llog_handle * handle,
                         }
                 }
 
+#if defined(HAVE_SERVER_SUPPORT) && defined(__KERNEL__)
+               /* newer MDS replaces LOV/OSC with LOD/OSP */
+               {
+                       char *typename = lustre_cfg_string(lcfg, 1);
+
+                       if ((lcfg->lcfg_command == LCFG_ATTACH && typename &&
+                           strcmp(typename, LUSTRE_LOV_NAME) == 0) &&
+                           IS_MDT(s2lsi(clli->cfg_sb))) {
+                               CDEBUG(D_CONFIG,
+                                      "For 2.x interoperability, rename obd "
+                                      "type from lov to lod (%s)\n",
+                                      s2lsi(clli->cfg_sb)->lsi_svname);
+                               strcpy(typename, LUSTRE_LOD_NAME);
+                       }
+                       if ((lcfg->lcfg_command == LCFG_ATTACH && typename &&
+                           strcmp(typename, LUSTRE_OSC_NAME) == 0) &&
+                           IS_MDT(s2lsi(clli->cfg_sb))) {
+                               CDEBUG(D_CONFIG,
+                                      "For 2.x interoperability, rename obd "
+                                      "type from osc to osp (%s)\n",
+                                      s2lsi(clli->cfg_sb)->lsi_svname);
+                               strcpy(typename, LUSTRE_OSP_NAME);
+                       }
+               }
+#endif
+
                 if ((clli->cfg_flags & CFG_F_EXCLUDE) &&
                     (lcfg->lcfg_command == LCFG_LOV_ADD_OBD))
                         /* Add inactive instead */
@@ -1360,137 +1545,158 @@ static int class_config_llog_handler(struct llog_handle * handle,
         }
 out:
         if (rc) {
-                CERROR("Err %d on cfg command:\n", rc);
-                class_config_dump_handler(handle, rec, data);
+               CERROR("%s: cfg command failed: rc = %d\n",
+                      handle->lgh_ctxt->loc_obd->obd_name, rc);
+               class_config_dump_handler(NULL, handle, rec, data);
         }
         RETURN(rc);
 }
+EXPORT_SYMBOL(class_config_llog_handler);
 
-int class_config_parse_llog(struct llog_ctxt *ctxt, char *name,
-                            struct config_llog_instance *cfg)
+int class_config_parse_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
+                           char *name, struct config_llog_instance *cfg)
 {
-        struct llog_process_cat_data cd = {0, 0};
-        struct llog_handle *llh;
-        int rc, rc2;
-        ENTRY;
-
-        CDEBUG(D_INFO, "looking up llog %s\n", name);
-        rc = llog_create(ctxt, &llh, NULL, name);
-        if (rc)
-                RETURN(rc);
-
-        rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
-        if (rc)
-                GOTO(parse_out, rc);
-
-        /* continue processing from where we last stopped to end-of-log */
-        if (cfg)
-                cd.lpcd_first_idx = cfg->cfg_last_idx;
-        cd.lpcd_last_idx = 0;
-
-        rc = llog_process(llh, class_config_llog_handler, cfg, &cd);
-
-        CDEBUG(D_CONFIG, "Processed log %s gen %d-%d (rc=%d)\n", name,
-               cd.lpcd_first_idx + 1, cd.lpcd_last_idx, rc);
-
-        if (cfg)
-                cfg->cfg_last_idx = cd.lpcd_last_idx;
+       struct llog_process_cat_data     cd = {0, 0};
+       struct llog_handle              *llh;
+       llog_cb_t                        callback;
+       int                              rc;
+       ENTRY;
+
+       CDEBUG(D_INFO, "looking up llog %s\n", name);
+       rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
+       if (rc)
+               RETURN(rc);
+
+       rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
+       if (rc)
+               GOTO(parse_out, rc);
+
+       /* continue processing from where we last stopped to end-of-log */
+       if (cfg) {
+               cd.lpcd_first_idx = cfg->cfg_last_idx;
+               callback = cfg->cfg_callback;
+               LASSERT(callback != NULL);
+       } else {
+               callback = class_config_llog_handler;
+       }
+
+       cd.lpcd_last_idx = 0;
+
+       rc = llog_process(env, llh, callback, cfg, &cd);
+
+       CDEBUG(D_CONFIG, "Processed log %s gen %d-%d (rc=%d)\n", name,
+              cd.lpcd_first_idx + 1, cd.lpcd_last_idx, rc);
+       if (cfg)
+               cfg->cfg_last_idx = cd.lpcd_last_idx;
 
 parse_out:
-        rc2 = llog_close(llh);
-        if (rc == 0)
-                rc = rc2;
-
+       llog_close(env, llh);
         RETURN(rc);
 }
+EXPORT_SYMBOL(class_config_parse_llog);
 
-int class_config_dump_handler(struct llog_handle * handle,
-                              struct llog_rec_hdr *rec, void *data)
+/**
+ * parse config record and output dump in supplied buffer.
+ * This is separated from class_config_dump_handler() to use
+ * for ioctl needs as well
+ */
+int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf, int size)
 {
-        int cfg_len = rec->lrh_len;
-        char *cfg_buf = (char*) (rec + 1);
-        char *outstr, *ptr, *end;
-        int rc = 0;
-        ENTRY;
+       struct lustre_cfg       *lcfg = (struct lustre_cfg *)(rec + 1);
+       char                    *ptr = buf;
+       char                    *end = buf + size;
+       int                      rc = 0;
+
+       ENTRY;
+
+       LASSERT(rec->lrh_type == OBD_CFG_REC);
+       rc = lustre_cfg_sanity_check(lcfg, rec->lrh_len);
+       if (rc < 0)
+               RETURN(rc);
+
+       ptr += snprintf(ptr, end-ptr, "cmd=%05x ", lcfg->lcfg_command);
+       if (lcfg->lcfg_flags)
+               ptr += snprintf(ptr, end-ptr, "flags=%#08x ",
+                               lcfg->lcfg_flags);
+
+       if (lcfg->lcfg_num)
+               ptr += snprintf(ptr, end-ptr, "num=%#08x ", lcfg->lcfg_num);
+
+       if (lcfg->lcfg_nid)
+               ptr += snprintf(ptr, end-ptr, "nid=%s("LPX64")\n     ",
+                               libcfs_nid2str(lcfg->lcfg_nid),
+                               lcfg->lcfg_nid);
+
+       if (lcfg->lcfg_command == LCFG_MARKER) {
+               struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
+
+               ptr += snprintf(ptr, end-ptr, "marker=%d(%#x)%s '%s'",
+                               marker->cm_step, marker->cm_flags,
+                               marker->cm_tgtname, marker->cm_comment);
+       } else {
+               int i;
+
+               for (i = 0; i <  lcfg->lcfg_bufcount; i++) {
+                       ptr += snprintf(ptr, end-ptr, "%d:%s  ", i,
+                                       lustre_cfg_string(lcfg, i));
+               }
+       }
+       /* return consumed bytes */
+       rc = ptr - buf;
+       RETURN(rc);
+}
 
-        OBD_ALLOC(outstr, 256);
-        end = outstr + 256;
-        ptr = outstr;
-        if (!outstr) {
-                RETURN(-ENOMEM);
-        }
-        if (rec->lrh_type == OBD_CFG_REC) {
-                struct lustre_cfg *lcfg;
-                int i;
+int class_config_dump_handler(const struct lu_env *env,
+                             struct llog_handle *handle,
+                             struct llog_rec_hdr *rec, void *data)
+{
+       char    *outstr;
+       int      rc = 0;
 
-                rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
-                if (rc)
-                        GOTO(out, rc);
-                lcfg = (struct lustre_cfg *)cfg_buf;
+       ENTRY;
 
-                ptr += snprintf(ptr, end-ptr, "cmd=%05x ",
-                                lcfg->lcfg_command);
-                if (lcfg->lcfg_flags) {
-                        ptr += snprintf(ptr, end-ptr, "flags=%#08x ",
-                                        lcfg->lcfg_flags);
-                }
-                if (lcfg->lcfg_num) {
-                        ptr += snprintf(ptr, end-ptr, "num=%#08x ",
-                                        lcfg->lcfg_num);
-                }
-                if (lcfg->lcfg_nid) {
-                        ptr += snprintf(ptr, end-ptr, "nid=%s("LPX64")\n     ",
-                                        libcfs_nid2str(lcfg->lcfg_nid),
-                                        lcfg->lcfg_nid);
-                }
-                if (lcfg->lcfg_command == LCFG_MARKER) {
-                        struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
-                        ptr += snprintf(ptr, end-ptr, "marker=%d(%#x)%s '%s'",
-                                        marker->cm_step, marker->cm_flags,
-                                        marker->cm_tgtname, marker->cm_comment);
-                } else {
-                        for (i = 0; i <  lcfg->lcfg_bufcount; i++) {
-                                ptr += snprintf(ptr, end-ptr, "%d:%s  ", i,
-                                                lustre_cfg_string(lcfg, i));
-                        }
-                }
-                LCONSOLE(D_WARNING, "   %s\n", outstr);
-        } else {
-                LCONSOLE(D_WARNING, "unhandled lrh_type: %#x\n", rec->lrh_type);
-                rc = -EINVAL;
-        }
-out:
-        OBD_FREE(outstr, 256);
-        RETURN(rc);
+       OBD_ALLOC(outstr, 256);
+       if (outstr == NULL)
+               RETURN(-ENOMEM);
+
+       if (rec->lrh_type == OBD_CFG_REC) {
+               class_config_parse_rec(rec, outstr, 256);
+               LCONSOLE(D_WARNING, "   %s\n", outstr);
+       } else {
+               LCONSOLE(D_WARNING, "unhandled lrh_type: %#x\n", rec->lrh_type);
+               rc = -EINVAL;
+       }
+
+       OBD_FREE(outstr, 256);
+       RETURN(rc);
 }
 
-int class_config_dump_llog(struct llog_ctxt *ctxt, char *name,
-                           struct config_llog_instance *cfg)
+int class_config_dump_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
+                          char *name, struct config_llog_instance *cfg)
 {
-        struct llog_handle *llh;
-        int rc, rc2;
-        ENTRY;
+       struct llog_handle      *llh;
+       int                      rc;
 
-        LCONSOLE_INFO("Dumping config log %s\n", name);
+       ENTRY;
 
-        rc = llog_create(ctxt, &llh, NULL, name);
-        if (rc)
-                RETURN(rc);
+       LCONSOLE_INFO("Dumping config log %s\n", name);
 
-        rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
-        if (rc)
-                GOTO(parse_out, rc);
+       rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
+       if (rc)
+               RETURN(rc);
 
-        rc = llog_process(llh, class_config_dump_handler, cfg, NULL);
-parse_out:
-        rc2 = llog_close(llh);
-        if (rc == 0)
-                rc = rc2;
+       rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
+       if (rc)
+               GOTO(parse_out, rc);
 
-        LCONSOLE_INFO("End config log %s\n", name);
-        RETURN(rc);
+       rc = llog_process(env, llh, class_config_dump_handler, cfg, NULL);
+parse_out:
+       llog_close(env, llh);
 
+       LCONSOLE_INFO("End config log %s\n", name);
+       RETURN(rc);
 }
+EXPORT_SYMBOL(class_config_dump_llog);
 
 /** Call class_cleanup and class_detach.
  * "Manual" only in the sense that we're faking lcfg commands.
@@ -1537,6 +1743,7 @@ out:
         lustre_cfg_free(lcfg);
         RETURN(rc);
 }
+EXPORT_SYMBOL(class_manual_cleanup);
 
 /*
  * uuid<->export lustre hash operations