*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
*
* GPL HEADER END
*/
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, 2013, Intel Corporation.
+ * Copyright (c) 2011, 2016, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
*/
#define DEBUG_SUBSYSTEM S_CLASS
-#ifdef __KERNEL__
-#include <obd_class.h>
+
#include <linux/string.h>
+
+#include <llog_swab.h>
+#include <lprocfs_status.h>
#include <lustre_disk.h>
-#else
-#include <liblustre.h>
-#include <string.h>
-#include <obd_class.h>
-#include <obd.h>
-#endif
#include <lustre_ioctl.h>
#include <lustre_log.h>
-#include <lprocfs_status.h>
#include <lustre_param.h>
+#include <obd_class.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;
+static struct cfs_hash_ops uuid_hash_ops;
+static struct cfs_hash_ops nid_hash_ops;
+static struct cfs_hash_ops nid_stat_hash_ops;
+static struct cfs_hash_ops gen_hash_ops;
/*********** string parsing utils *********/
/* returns 0 if this is the first key in the buffer, else 1.
valp points to first char after key. */
-int class_match_param(char *buf, char *key, char **valp)
+int class_match_param(char *buf, const char *key, char **valp)
{
if (!buf)
return 1;
{
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
}
return rc;
}
-EXPORT_SYMBOL(class_match_nid);
int class_match_net(char *buf, char *key, __u32 net)
{
}
return rc;
}
-EXPORT_SYMBOL(class_match_net);
/********************** class fns **********************/
/* XXX belongs in setup not attach */
init_rwsem(&obd->obd_observer_link_sem);
/* recovery data */
- cfs_init_timer(&obd->obd_recovery_timer);
+ init_timer(&obd->obd_recovery_timer);
spin_lock_init(&obd->obd_recovery_task_lock);
init_waitqueue_head(&obd->obd_next_transno_waitq);
init_waitqueue_head(&obd->obd_evict_inprogress_waitq);
obd->obd_uuid_hash = NULL;
obd->obd_nid_hash = NULL;
obd->obd_nid_stats_hash = NULL;
+ obd->obd_gen_hash = NULL;
spin_unlock(&obd->obd_dev_lock);
/* create an uuid-export lustre hash */
if (!obd->obd_nid_stats_hash)
GOTO(err_hash, err = -ENOMEM);
+ /* create a client_generation-export lustre hash */
+ obd->obd_gen_hash = cfs_hash_create("UUID_HASH",
+ HASH_GEN_CUR_BITS,
+ HASH_GEN_MAX_BITS,
+ HASH_GEN_BKT_BITS, 0,
+ CFS_HASH_MIN_THETA,
+ CFS_HASH_MAX_THETA,
+ &gen_hash_ops, CFS_HASH_DEFAULT);
+ if (!obd->obd_gen_hash)
+ GOTO(err_hash, err = -ENOMEM);
+
exp = class_new_export(obd, &obd->obd_uuid);
if (IS_ERR(exp))
GOTO(err_hash, err = PTR_ERR(exp));
cfs_hash_putref(obd->obd_nid_stats_hash);
obd->obd_nid_stats_hash = NULL;
}
+ if (obd->obd_gen_hash) {
+ cfs_hash_putref(obd->obd_gen_hash);
+ obd->obd_gen_hash = NULL;
+ }
obd->obd_starting = 0;
CERROR("setup %s failed (%d)\n", obd->obd_name, err);
return err;
*/
int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
{
- int err = 0;
- char *flag;
- ENTRY;
+ int err = 0;
+ char *flag;
+ ENTRY;
- OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS);
+ OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS);
- if (!obd->obd_set_up) {
- CERROR("Device %d not setup\n", obd->obd_minor);
- RETURN(-ENODEV);
- }
+ if (!obd->obd_set_up) {
+ CERROR("Device %d not setup\n", obd->obd_minor);
+ RETURN(-ENODEV);
+ }
spin_lock(&obd->obd_dev_lock);
if (obd->obd_stopping) {
yield();
smp_rmb();
- if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) {
- for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++)
- switch (*flag) {
- case 'F':
- obd->obd_force = 1;
- break;
- case 'A':
- LCONSOLE_WARN("Failing over %s\n",
- obd->obd_name);
- obd->obd_fail = 1;
- obd->obd_no_transno = 1;
- obd->obd_no_recov = 1;
- if (OBP(obd, iocontrol)) {
- obd_iocontrol(OBD_IOC_SYNC,
- obd->obd_self_export,
- 0, NULL, NULL);
- }
- break;
- default:
- CERROR("Unrecognised flag '%c'\n", *flag);
- }
- }
+ if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) {
+ for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++)
+ switch (*flag) {
+ case 'F':
+ obd->obd_force = 1;
+ break;
+ case 'A':
+ LCONSOLE_WARN("Failing over %s\n",
+ obd->obd_name);
+ obd->obd_fail = 1;
+ obd->obd_no_transno = 1;
+ obd->obd_no_recov = 1;
+ if (OBP(obd, iocontrol)) {
+ obd_iocontrol(OBD_IOC_SYNC,
+ obd->obd_self_export,
+ 0, NULL, NULL);
+ }
+ break;
+ default:
+ CERROR("Unrecognised flag '%c'\n", *flag);
+ }
+ }
- LASSERT(obd->obd_self_export);
+ LASSERT(obd->obd_self_export);
- /* The three references that should be remaining are the
- * obd_self_export and the attach and setup references. */
+ /* The three references that should be remaining are the
+ * obd_self_export and the attach and setup references. */
if (atomic_read(&obd->obd_refcount) > 3) {
- /* refcounf - 3 might be the number of real exports
- (excluding self export). But class_incref is called
- by other things as well, so don't count on it. */
- CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
+ /* refcounf - 3 might be the number of real exports
+ (excluding self export). But class_incref is called
+ by other things as well, so don't count on it. */
+ CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
obd->obd_name, atomic_read(&obd->obd_refcount) - 3);
- dump_exports(obd, 0);
- class_disconnect_exports(obd);
- }
+ dump_exports(obd, 0, D_HA);
+ class_disconnect_exports(obd);
+ }
- /* Precleanup, we must make sure all exports get destroyed. */
- err = obd_precleanup(obd, OBD_CLEANUP_EXPORTS);
- if (err)
- CERROR("Precleanup %s returned %d\n",
- obd->obd_name, err);
+ /* Precleanup, we must make sure all exports get destroyed. */
+ err = obd_precleanup(obd);
+ if (err)
+ CERROR("Precleanup %s returned %d\n",
+ obd->obd_name, err);
- /* destroy an uuid-export hash body */
- if (obd->obd_uuid_hash) {
- cfs_hash_putref(obd->obd_uuid_hash);
- obd->obd_uuid_hash = NULL;
- }
+ /* destroy an uuid-export hash body */
+ if (obd->obd_uuid_hash) {
+ cfs_hash_putref(obd->obd_uuid_hash);
+ obd->obd_uuid_hash = NULL;
+ }
- /* destroy a nid-export hash body */
- if (obd->obd_nid_hash) {
- cfs_hash_putref(obd->obd_nid_hash);
- obd->obd_nid_hash = NULL;
- }
+ /* destroy a nid-export hash body */
+ if (obd->obd_nid_hash) {
+ cfs_hash_putref(obd->obd_nid_hash);
+ obd->obd_nid_hash = NULL;
+ }
- /* destroy a nid-stats hash body */
- if (obd->obd_nid_stats_hash) {
- cfs_hash_putref(obd->obd_nid_stats_hash);
- obd->obd_nid_stats_hash = NULL;
- }
+ /* destroy a nid-stats hash body */
+ if (obd->obd_nid_stats_hash) {
+ cfs_hash_putref(obd->obd_nid_stats_hash);
+ obd->obd_nid_stats_hash = NULL;
+ }
- class_decref(obd, "setup", obd);
- obd->obd_set_up = 0;
+ /* destroy a client_generation-export hash body */
+ if (obd->obd_gen_hash) {
+ cfs_hash_putref(obd->obd_gen_hash);
+ obd->obd_gen_hash = NULL;
+ }
- RETURN(0);
+ class_decref(obd, "setup", obd);
+ obd->obd_set_up = 0;
+
+ RETURN(0);
}
-EXPORT_SYMBOL(class_cleanup);
struct obd_device *class_incref(struct obd_device *obd,
const char *scope, const void *source)
RETURN(rc);
}
-EXPORT_SYMBOL(class_add_conn);
/** Remove a failover nid location.
*/
-int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
+static int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
{
struct obd_import *imp;
struct obd_uuid uuid;
RETURN(rc);
}
-struct list_head lustre_profile_list =
+static struct list_head lustre_profile_list =
LIST_HEAD_INIT(lustre_profile_list);
+static DEFINE_SPINLOCK(lustre_profile_list_lock);
struct lustre_profile *class_get_profile(const char * prof)
{
- struct lustre_profile *lprof;
+ struct lustre_profile *lprof;
- ENTRY;
+ ENTRY;
+ spin_lock(&lustre_profile_list_lock);
list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
- if (!strcmp(lprof->lp_profile, prof)) {
- RETURN(lprof);
- }
- }
- RETURN(NULL);
+ if (!strcmp(lprof->lp_profile, prof)) {
+ lprof->lp_refs++;
+ spin_unlock(&lustre_profile_list_lock);
+ RETURN(lprof);
+ }
+ }
+ spin_unlock(&lustre_profile_list_lock);
+ RETURN(NULL);
}
EXPORT_SYMBOL(class_get_profile);
* This defines the mdc and osc names to use for a client.
* This also is used to define the lov to be used by a mdt.
*/
-int class_add_profile(int proflen, char *prof, int osclen, char *osc,
- int mdclen, char *mdc)
+static int class_add_profile(int proflen, char *prof, int osclen, char *osc,
+ int mdclen, char *mdc)
{
struct lustre_profile *lprof;
int err = 0;
memcpy(lprof->lp_md, mdc, mdclen);
}
+ spin_lock(&lustre_profile_list_lock);
+ lprof->lp_refs = 1;
+ lprof->lp_list_deleted = false;
+
list_add(&lprof->lp_list, &lustre_profile_list);
+ spin_unlock(&lustre_profile_list_lock);
RETURN(err);
out:
void class_del_profile(const char *prof)
{
- struct lustre_profile *lprof;
- ENTRY;
+ struct lustre_profile *lprof;
+ ENTRY;
- CDEBUG(D_CONFIG, "Del profile %s\n", prof);
+ CDEBUG(D_CONFIG, "Del profile %s\n", prof);
- lprof = class_get_profile(prof);
- if (lprof) {
+ lprof = class_get_profile(prof);
+ if (lprof) {
+ spin_lock(&lustre_profile_list_lock);
+ /* because get profile increments the ref counter */
+ lprof->lp_refs--;
list_del(&lprof->lp_list);
- OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
- OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
- if (lprof->lp_md)
- OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
- OBD_FREE(lprof, sizeof *lprof);
- }
- EXIT;
+ lprof->lp_list_deleted = true;
+ spin_unlock(&lustre_profile_list_lock);
+
+ class_put_profile(lprof);
+ }
+ EXIT;
}
EXPORT_SYMBOL(class_del_profile);
+void class_put_profile(struct lustre_profile *lprof)
+{
+ spin_lock(&lustre_profile_list_lock);
+ if ((--lprof->lp_refs) > 0) {
+ LASSERT(lprof->lp_refs > 0);
+ spin_unlock(&lustre_profile_list_lock);
+ return;
+ }
+ spin_unlock(&lustre_profile_list_lock);
+
+ /* confirm not a negative number */
+ LASSERT(lprof->lp_refs == 0);
+
+ /* At least one class_del_profile/profiles must be called
+ * on the target profile or lustre_profile_list will corrupt */
+ LASSERT(lprof->lp_list_deleted);
+ OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
+ OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
+ if (lprof->lp_md != NULL)
+ OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
+ OBD_FREE(lprof, sizeof(*lprof));
+}
+EXPORT_SYMBOL(class_put_profile);
+
/* COMPAT_146 */
void class_del_profiles(void)
{
- struct lustre_profile *lprof, *n;
- ENTRY;
+ struct lustre_profile *lprof, *n;
+ ENTRY;
+ spin_lock(&lustre_profile_list_lock);
list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) {
list_del(&lprof->lp_list);
- OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
- OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
- if (lprof->lp_md)
- OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
- OBD_FREE(lprof, sizeof *lprof);
- }
- EXIT;
+ lprof->lp_list_deleted = true;
+ spin_unlock(&lustre_profile_list_lock);
+
+ class_put_profile(lprof);
+
+ spin_lock(&lustre_profile_list_lock);
+ }
+ spin_unlock(&lustre_profile_list_lock);
+ EXIT;
}
EXPORT_SYMBOL(class_del_profiles);
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)
[2] = param,
[3] = NULL
};
- struct timeval start;
- struct timeval end;
+ ktime_t start;
+ ktime_t end;
int rc;
ENTRY;
RETURN(-EINVAL);
}
- do_gettimeofday(&start);
- rc = call_usermodehelper(argv[0], argv, NULL, 0);
- do_gettimeofday(&end);
+ start = ktime_get();
+ rc = call_usermodehelper(argv[0], argv, NULL, UMH_WAIT_PROC);
+ end = ktime_get();
if (rc < 0) {
CERROR("lctl: error invoking upcall %s %s %s: rc = %d; "
"time %ldus\n", argv[0], argv[1], argv[2], rc,
- cfs_timeval_sub(&end, &start, NULL));
+ (long)ktime_us_delta(end, start));
} else {
CDEBUG(D_HA, "lctl: invoked upcall %s %s %s, time %ldus\n",
argv[0], argv[1], argv[2],
- cfs_timeval_sub(&end, &start, NULL));
+ (long)ktime_us_delta(end, start));
rc = 0;
}
GOTO(out, err);
}
case LCFG_ADD_UUID: {
- CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid "LPX64
+ CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid %#llx"
" (%s)\n", lustre_cfg_string(lcfg, 1),
lcfg->lcfg_nid, libcfs_nid2str(lcfg->lcfg_nid));
char *tmp;
/* llite has no obd */
if ((class_match_param(lustre_cfg_string(lcfg, 1),
- PARAM_LLITE, 0) == 0) &&
+ PARAM_LLITE, NULL) == 0) &&
client_process_config) {
err = (*client_process_config)(lcfg);
GOTO(out, err);
}
EXPORT_SYMBOL(class_process_config);
-#ifndef HAVE_ONLY_PROCFS_SEQ
int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
- struct lustre_cfg *lcfg, void *data)
-{
-#ifdef __KERNEL__
- struct lprocfs_vars *var;
- char *key, *sval;
- int i, keylen, vallen;
- int matched = 0, j = 0;
- int rc = 0;
- int skip = 0;
- ENTRY;
-
- if (lcfg->lcfg_command != LCFG_PARAM) {
- CERROR("Unknown command: %d\n", lcfg->lcfg_command);
- RETURN(-EINVAL);
- }
-
- /* e.g. tunefs.lustre --param mdt.group_upcall=foo /r/tmp/lustre-mdt
- or lctl conf_param lustre-MDT0000.mdt.group_upcall=bar
- or lctl conf_param lustre-OST0000.osc.max_dirty_mb=36 */
- for (i = 1; i < lcfg->lcfg_bufcount; i++) {
- key = lustre_cfg_buf(lcfg, i);
- /* Strip off prefix */
- if (class_match_param(key, prefix, &key))
- /* If the prefix doesn't match, return error so we
- * can pass it down the stack */
- RETURN(-ENOSYS);
- sval = strchr(key, '=');
- if (!sval || (*(sval + 1) == 0)) {
- CERROR("Can't parse param %s (missing '=')\n", key);
- /* rc = -EINVAL; continue parsing other params */
- continue;
- }
- keylen = sval - key;
- sval++;
- vallen = strlen(sval);
- matched = 0;
- j = 0;
- /* Search proc entries */
- while (lvars[j].name) {
- var = &lvars[j];
- if (class_match_param(key, (char *)var->name, 0) == 0 &&
- keylen == strlen(var->name)) {
- matched++;
- rc = -EROFS;
-
- if (var->write_fptr) {
- mm_segment_t oldfs;
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- rc = (var->write_fptr)(NULL, sval,
- vallen, data);
- set_fs(oldfs);
- }
- break;
- }
- j++;
- }
- if (!matched) {
- CERROR("%.*s: %s unknown param %s\n",
- (int)strlen(prefix) - 1, prefix,
- (char *)lustre_cfg_string(lcfg, 0), key);
- /* rc = -EINVAL; continue parsing other params */
- skip++;
- } else if (rc < 0) {
- CERROR("%s: error writing proc entry '%s': rc = %d\n",
- prefix, 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);
- }
- }
-
- if (rc > 0)
- rc = 0;
- if (!rc && skip)
- rc = skip;
- RETURN(rc);
-#else
- CDEBUG(D_CONFIG, "liblustre can't process params.\n");
- /* Don't throw config error */
- RETURN(0);
-#endif
-}
-EXPORT_SYMBOL(class_process_proc_param);
-#endif
-
-int class_process_proc_seq_param(char *prefix, struct lprocfs_seq_vars *lvars,
- struct lustre_cfg *lcfg, void *data)
+ struct lustre_cfg *lcfg, void *data)
{
-#ifdef __KERNEL__
- struct lprocfs_seq_vars *var;
+ struct lprocfs_vars *var;
struct file fakefile;
struct seq_file fake_seqfile;
char *key, *sval;
/* Search proc entries */
while (lvars[j].name) {
var = &lvars[j];
- if (class_match_param(key, (char *)var->name, 0) == 0 &&
+ if (class_match_param(key, var->name, NULL) == 0 &&
keylen == strlen(var->name)) {
matched++;
rc = -EROFS;
j++;
}
if (!matched) {
+ /* It was upgraded from old MDT/OST device,
+ * ignore the obsolete "sec_level" parameter. */
+ if (strncmp("sec_level", key, keylen) == 0)
+ continue;
+
CERROR("%.*s: %s unknown param %s\n",
(int)strlen(prefix) - 1, prefix,
(char *)lustre_cfg_string(lcfg, 0), key);
if (!rc && skip)
rc = skip;
RETURN(rc);
-#else
- CDEBUG(D_CONFIG, "liblustre can't process params.\n");
- /* Don't throw config error */
- RETURN(0);
-#endif
}
-EXPORT_SYMBOL(class_process_proc_seq_param);
-
-#ifdef __KERNEL__
-extern int lustre_check_exclusion(struct super_block *sb, char *svname);
-#else
-#define lustre_check_exclusion(a,b) 0
-#endif
+EXPORT_SYMBOL(class_process_proc_param);
/*
* Supplemental functions for config logs, it allocates lustre_cfg
struct llog_handle *handle,
struct llog_rec_hdr *rec, void *data)
{
- struct config_llog_instance *clli = data;
- int cfg_len = rec->lrh_len;
- char *cfg_buf = (char*) (rec + 1);
- int rc = 0;
- ENTRY;
+ struct config_llog_instance *cfg = data;
+ int cfg_len = rec->lrh_len;
+ char *cfg_buf = (char *) (rec + 1);
+ int rc = 0;
+ ENTRY;
- //class_config_dump_handler(handle, rec, data);
+ /* class_config_dump_handler(handle, rec, data); */
- switch (rec->lrh_type) {
- case OBD_CFG_REC: {
- struct lustre_cfg *lcfg, *lcfg_new;
- struct lustre_cfg_bufs bufs;
- char *inst_name = NULL;
- int inst_len = 0;
- int inst = 0, swab = 0;
+ switch (rec->lrh_type) {
+ case OBD_CFG_REC: {
+ struct lustre_cfg *lcfg, *lcfg_new;
+ struct lustre_cfg_bufs bufs;
+ char *inst_name = NULL;
+ int inst_len = 0;
+ int inst = 0, swab = 0;
- lcfg = (struct lustre_cfg *)cfg_buf;
- if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION)) {
- lustre_swab_lustre_cfg(lcfg);
- swab = 1;
- }
+ lcfg = (struct lustre_cfg *)cfg_buf;
+ if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION)) {
+ lustre_swab_lustre_cfg(lcfg);
+ swab = 1;
+ }
- rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
- if (rc)
- GOTO(out, rc);
+ rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
+ if (rc)
+ GOTO(out, rc);
/* Figure out config state info */
- if (lcfg->lcfg_command == LCFG_MARKER) {
- struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
- lustre_swab_cfg_marker(marker, swab,
- LUSTRE_CFG_BUFLEN(lcfg, 1));
- CDEBUG(D_CONFIG, "Marker, inst_flg=%#x mark_flg=%#x\n",
- clli->cfg_flags, marker->cm_flags);
- if (marker->cm_flags & CM_START) {
+ if (lcfg->lcfg_command == LCFG_MARKER) {
+ struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
+ lustre_swab_cfg_marker(marker, swab,
+ LUSTRE_CFG_BUFLEN(lcfg, 1));
+ CDEBUG(D_CONFIG, "Marker, inst_flg=%#x mark_flg=%#x\n",
+ cfg->cfg_flags, marker->cm_flags);
+ if (marker->cm_flags & CM_START) {
/* all previous flags off */
- clli->cfg_flags = CFG_F_MARKER;
+ cfg->cfg_flags = CFG_F_MARKER;
server_name2index(marker->cm_tgtname,
- &clli->cfg_lwp_idx, NULL);
- if (marker->cm_flags & CM_SKIP) {
- clli->cfg_flags |= CFG_F_SKIP;
- CDEBUG(D_CONFIG, "SKIP #%d\n",
- marker->cm_step);
- } else if ((marker->cm_flags & CM_EXCLUDE) ||
- (clli->cfg_sb &&
- lustre_check_exclusion(clli->cfg_sb,
- marker->cm_tgtname))) {
- clli->cfg_flags |= CFG_F_EXCLUDE;
- CDEBUG(D_CONFIG, "EXCLUDE %d\n",
- marker->cm_step);
- }
- } else if (marker->cm_flags & CM_END) {
- clli->cfg_flags = 0;
- }
- }
- /* A config command without a start marker before it is
- illegal (post 146) */
- if (!(clli->cfg_flags & CFG_F_COMPAT146) &&
- !(clli->cfg_flags & CFG_F_MARKER) &&
- (lcfg->lcfg_command != LCFG_MARKER)) {
- CWARN("Config not inside markers, ignoring! "
- "(inst: %p, uuid: %s, flags: %#x)\n",
- clli->cfg_instance,
- clli->cfg_uuid.uuid, clli->cfg_flags);
- clli->cfg_flags |= CFG_F_SKIP;
- }
- if (clli->cfg_flags & CFG_F_SKIP) {
- CDEBUG(D_CONFIG, "skipping %#x\n",
- clli->cfg_flags);
- rc = 0;
- /* No processing! */
- break;
- }
+ &cfg->cfg_lwp_idx, NULL);
+ if (marker->cm_flags & CM_SKIP) {
+ cfg->cfg_flags |= CFG_F_SKIP;
+ CDEBUG(D_CONFIG, "SKIP #%d\n",
+ marker->cm_step);
+ } else if ((marker->cm_flags & CM_EXCLUDE) ||
+ (cfg->cfg_sb &&
+ lustre_check_exclusion(cfg->cfg_sb,
+ marker->cm_tgtname))) {
+ cfg->cfg_flags |= CFG_F_EXCLUDE;
+ CDEBUG(D_CONFIG, "EXCLUDE %d\n",
+ marker->cm_step);
+ }
+ } else if (marker->cm_flags & CM_END) {
+ cfg->cfg_flags = 0;
+ }
+ }
+ /* A config command without a start marker before it is
+ illegal (post 146) */
+ if (!(cfg->cfg_flags & CFG_F_COMPAT146) &&
+ !(cfg->cfg_flags & CFG_F_MARKER) &&
+ (lcfg->lcfg_command != LCFG_MARKER)) {
+ CWARN("Config not inside markers, ignoring! "
+ "(inst: %p, uuid: %s, flags: %#x)\n",
+ cfg->cfg_instance,
+ cfg->cfg_uuid.uuid, cfg->cfg_flags);
+ cfg->cfg_flags |= CFG_F_SKIP;
+ }
+ if (cfg->cfg_flags & CFG_F_SKIP) {
+ CDEBUG(D_CONFIG, "skipping %#x\n",
+ cfg->cfg_flags);
+ rc = 0;
+ /* No processing! */
+ break;
+ }
/*
* For interoperability between 1.8 and 2.0,
* rename "mds" obd device type to "mdt".
*/
- {
- char *typename = lustre_cfg_string(lcfg, 1);
- char *index = lustre_cfg_string(lcfg, 2);
-
- if ((lcfg->lcfg_command == LCFG_ATTACH && typename &&
- strcmp(typename, "mds") == 0)) {
- CWARN("For 1.8 interoperability, rename obd "
- "type from mds to mdt\n");
- typename[2] = 't';
- }
- if ((lcfg->lcfg_command == LCFG_SETUP && index &&
- strcmp(index, "type") == 0)) {
- CDEBUG(D_INFO, "For 1.8 interoperability, "
- "set this index to '0'\n");
- index[0] = '0';
- index[1] = 0;
- }
- }
+ {
+ char *typename = lustre_cfg_string(lcfg, 1);
+ char *index = lustre_cfg_string(lcfg, 2);
-#if defined(HAVE_SERVER_SUPPORT) && defined(__KERNEL__)
+ if ((lcfg->lcfg_command == LCFG_ATTACH && typename &&
+ strcmp(typename, "mds") == 0)) {
+ CWARN("For 1.8 interoperability, rename obd "
+ "type from mds to mdt\n");
+ typename[2] = 't';
+ }
+ if ((lcfg->lcfg_command == LCFG_SETUP && index &&
+ strcmp(index, "type") == 0)) {
+ CDEBUG(D_INFO, "For 1.8 interoperability, "
+ "set this index to '0'\n");
+ index[0] = '0';
+ index[1] = 0;
+ }
+ }
+
+#ifdef HAVE_SERVER_SUPPORT
/* 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))) {
+ cfg->cfg_sb && IS_MDT(s2lsi(cfg->cfg_sb))) {
CDEBUG(D_CONFIG,
"For 2.x interoperability, rename obd "
"type from lov to lod (%s)\n",
- s2lsi(clli->cfg_sb)->lsi_svname);
+ s2lsi(cfg->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))) {
+ cfg->cfg_sb && IS_MDT(s2lsi(cfg->cfg_sb))) {
CDEBUG(D_CONFIG,
"For 2.x interoperability, rename obd "
"type from osc to osp (%s)\n",
- s2lsi(clli->cfg_sb)->lsi_svname);
+ s2lsi(cfg->cfg_sb)->lsi_svname);
strcpy(typename, LUSTRE_OSP_NAME);
}
}
-#endif
+#endif /* HAVE_SERVER_SUPPORT */
- if (clli->cfg_flags & CFG_F_EXCLUDE) {
+ if (cfg->cfg_flags & CFG_F_EXCLUDE) {
CDEBUG(D_CONFIG, "cmd: %x marked EXCLUDED\n",
lcfg->lcfg_command);
if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD)
lcfg->lcfg_command = LCFG_LOV_ADD_INA;
}
- lustre_cfg_bufs_init(&bufs, lcfg);
-
- if (clli && clli->cfg_instance &&
- LUSTRE_CFG_BUFLEN(lcfg, 0) > 0){
- inst = 1;
- inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
- sizeof(clli->cfg_instance) * 2 + 4;
- OBD_ALLOC(inst_name, inst_len);
- if (inst_name == NULL)
- GOTO(out, rc = -ENOMEM);
- sprintf(inst_name, "%s-%p",
- lustre_cfg_string(lcfg, 0),
- clli->cfg_instance);
- lustre_cfg_bufs_set_string(&bufs, 0, inst_name);
- CDEBUG(D_CONFIG, "cmd %x, instance name: %s\n",
- lcfg->lcfg_command, inst_name);
- }
+ lustre_cfg_bufs_reset(&bufs, NULL);
+ lustre_cfg_bufs_init(&bufs, lcfg);
+
+ if (cfg->cfg_instance &&
+ LUSTRE_CFG_BUFLEN(lcfg, 0) > 0) {
+ inst = 1;
+ inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
+ sizeof(cfg->cfg_instance) * 2 + 4;
+ OBD_ALLOC(inst_name, inst_len);
+ if (inst_name == NULL)
+ GOTO(out, rc = -ENOMEM);
+ snprintf(inst_name, inst_len, "%s-%p",
+ lustre_cfg_string(lcfg, 0),
+ cfg->cfg_instance);
+ lustre_cfg_bufs_set_string(&bufs, 0, inst_name);
+ CDEBUG(D_CONFIG, "cmd %x, instance name: %s\n",
+ lcfg->lcfg_command, inst_name);
+ }
/* we override the llog's uuid for clients, to insure they
are unique */
- if (clli && clli->cfg_instance != NULL &&
- lcfg->lcfg_command == LCFG_ATTACH) {
- lustre_cfg_bufs_set_string(&bufs, 2,
- clli->cfg_uuid.uuid);
- }
+ if (cfg->cfg_instance != NULL &&
+ lcfg->lcfg_command == LCFG_ATTACH) {
+ lustre_cfg_bufs_set_string(&bufs, 2,
+ cfg->cfg_uuid.uuid);
+ }
/*
* sptlrpc config record, we expect 2 data segments:
* [0]: fs_name/target_name,
* moving them to index [1] and [2], and insert MGC's
* obdname at index [0].
*/
- if (clli && clli->cfg_instance == NULL &&
- lcfg->lcfg_command == LCFG_SPTLRPC_CONF) {
- lustre_cfg_bufs_set(&bufs, 2, bufs.lcfg_buf[1],
- bufs.lcfg_buflen[1]);
- lustre_cfg_bufs_set(&bufs, 1, bufs.lcfg_buf[0],
- bufs.lcfg_buflen[0]);
- lustre_cfg_bufs_set_string(&bufs, 0,
- clli->cfg_obdname);
- }
+ if (cfg->cfg_instance == NULL &&
+ lcfg->lcfg_command == LCFG_SPTLRPC_CONF) {
+ lustre_cfg_bufs_set(&bufs, 2, bufs.lcfg_buf[1],
+ bufs.lcfg_buflen[1]);
+ lustre_cfg_bufs_set(&bufs, 1, bufs.lcfg_buf[0],
+ bufs.lcfg_buflen[0]);
+ lustre_cfg_bufs_set_string(&bufs, 0,
+ cfg->cfg_obdname);
+ }
+
+ /* Add net info to setup command
+ * if given on command line.
+ * So config log will be:
+ * [0]: client name
+ * [1]: client UUID
+ * [2]: server UUID
+ * [3]: inactive-on-startup
+ * [4]: restrictive net
+ */
+ if (cfg && cfg->cfg_sb && s2lsi(cfg->cfg_sb) &&
+ !IS_SERVER(s2lsi(cfg->cfg_sb))) {
+ struct lustre_sb_info *lsi = s2lsi(cfg->cfg_sb);
+ char *nidnet = lsi->lsi_lmd->lmd_nidnet;
+
+ if (lcfg->lcfg_command == LCFG_SETUP &&
+ lcfg->lcfg_bufcount != 2 && nidnet) {
+ CDEBUG(D_CONFIG, "Adding net %s info to setup "
+ "command for client %s\n", nidnet,
+ lustre_cfg_string(lcfg, 0));
+ lustre_cfg_bufs_set_string(&bufs, 4, nidnet);
+ }
+ }
- lcfg_new = lustre_cfg_new(lcfg->lcfg_command, &bufs);
+ /* Skip add_conn command if uuid is
+ * not on restricted net */
+ if (cfg && cfg->cfg_sb && s2lsi(cfg->cfg_sb) &&
+ !IS_SERVER(s2lsi(cfg->cfg_sb))) {
+ struct lustre_sb_info *lsi = s2lsi(cfg->cfg_sb);
+ char *uuid_str = lustre_cfg_string(lcfg, 1);
+
+ if (lcfg->lcfg_command == LCFG_ADD_CONN &&
+ lsi->lsi_lmd->lmd_nidnet &&
+ LNET_NIDNET(libcfs_str2nid(uuid_str)) !=
+ libcfs_str2net(lsi->lsi_lmd->lmd_nidnet)) {
+ CDEBUG(D_CONFIG, "skipping add_conn for %s\n",
+ uuid_str);
+ rc = 0;
+ /* No processing! */
+ break;
+ }
+ }
+
+ lcfg_new = lustre_cfg_new(lcfg->lcfg_command, &bufs);
if (lcfg_new == NULL)
GOTO(out, rc = -ENOMEM);
- lcfg_new->lcfg_num = lcfg->lcfg_num;
- lcfg_new->lcfg_flags = lcfg->lcfg_flags;
-
- /* XXX Hack to try to remain binary compatible with
- * pre-newconfig logs */
- if (lcfg->lcfg_nal != 0 && /* pre-newconfig log? */
- (lcfg->lcfg_nid >> 32) == 0) {
- __u32 addr = (__u32)(lcfg->lcfg_nid & 0xffffffff);
-
- lcfg_new->lcfg_nid =
- LNET_MKNID(LNET_MKNET(lcfg->lcfg_nal, 0), addr);
- CWARN("Converted pre-newconfig NAL %d NID %x to %s\n",
- lcfg->lcfg_nal, addr,
- libcfs_nid2str(lcfg_new->lcfg_nid));
- } else {
- lcfg_new->lcfg_nid = lcfg->lcfg_nid;
- }
+ lcfg_new->lcfg_num = lcfg->lcfg_num;
+ lcfg_new->lcfg_flags = lcfg->lcfg_flags;
+
+ /* XXX Hack to try to remain binary compatible with
+ * pre-newconfig logs */
+ if (lcfg->lcfg_nal != 0 && /* pre-newconfig log? */
+ (lcfg->lcfg_nid >> 32) == 0) {
+ __u32 addr = (__u32)(lcfg->lcfg_nid & 0xffffffff);
+
+ lcfg_new->lcfg_nid =
+ LNET_MKNID(LNET_MKNET(lcfg->lcfg_nal, 0), addr);
+ CWARN("Converted pre-newconfig NAL %d NID %x to %s\n",
+ lcfg->lcfg_nal, addr,
+ libcfs_nid2str(lcfg_new->lcfg_nid));
+ } else {
+ lcfg_new->lcfg_nid = lcfg->lcfg_nid;
+ }
- lcfg_new->lcfg_nal = 0; /* illegal value for obsolete field */
+ lcfg_new->lcfg_nal = 0; /* illegal value for obsolete field */
rc = class_process_config(lcfg_new);
- lustre_cfg_free(lcfg_new);
+ lustre_cfg_free(lcfg_new);
- if (inst)
- OBD_FREE(inst_name, inst_len);
- break;
- }
- default:
- CERROR("Unknown llog record type %#x encountered\n",
- rec->lrh_type);
- break;
- }
+ if (inst)
+ OBD_FREE(inst_name, inst_len);
+ break;
+ }
+ default:
+ CERROR("Unknown llog record type %#x encountered\n",
+ rec->lrh_type);
+ break;
+ }
out:
- if (rc) {
+ if (rc) {
CERROR("%s: cfg command failed: rc = %d\n",
- handle->lgh_ctxt->loc_obd->obd_name, rc);
+ handle->lgh_ctxt->loc_obd->obd_name, rc);
class_config_dump_handler(NULL, handle, rec, data);
- }
- RETURN(rc);
+ }
+ RETURN(rc);
}
EXPORT_SYMBOL(class_config_llog_handler);
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;
- llog_cb_t callback;
- int rc;
+ struct llog_process_cat_data cd = {
+ .lpcd_first_idx = 0,
+ };
+ struct llog_handle *llh;
+ llog_cb_t callback;
+ int rc;
ENTRY;
CDEBUG(D_INFO, "looking up llog %s\n", name);
}
EXPORT_SYMBOL(class_config_parse_llog);
-struct lcfg_type_data {
+static struct lcfg_type_data {
__u32 ltd_type;
char *ltd_name;
char *ltd_bufs[4];
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")",
- libcfs_nid2str(lcfg->lcfg_nid),
- lcfg->lcfg_nid);
+ if (lcfg->lcfg_nid) {
+ char nidstr[LNET_NIDSTR_SIZE];
+
+ libcfs_nid2str_r(lcfg->lcfg_nid, nidstr, sizeof(nidstr));
+ ptr += snprintf(ptr, end - ptr, ", nid: %s(%#llx)",
+ nidstr, lcfg->lcfg_nid);
+ }
if (LUSTRE_CFG_BUFLEN(lcfg, 0) > 0)
ptr += snprintf(ptr, end - ptr, ", device: %s",
* 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)
+static int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf, int size)
{
struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1);
char *ptr = buf;
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_nid) {
+ char nidstr[LNET_NIDSTR_SIZE];
+
+ libcfs_nid2str_r(lcfg->lcfg_nid, nidstr, sizeof(nidstr));
+ ptr += snprintf(ptr, end-ptr, "nid=%s(%#llx)\n ",
+ nidstr, lcfg->lcfg_nid);
+ }
if (lcfg->lcfg_command == LCFG_MARKER) {
struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
RETURN(rc);
}
-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;
-
- ENTRY;
-
- LCONSOLE_INFO("Dumping config log %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);
-
- 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.
*/
CDEBUG(D_CONFIG, "Manual cleanup of %s (flags='%s')\n",
obd->obd_name, flags);
- lustre_cfg_bufs_reset(&bufs, obd->obd_name);
- lustre_cfg_bufs_set_string(&bufs, 1, flags);
- lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
- if (!lcfg)
- RETURN(-ENOMEM);
+ lustre_cfg_bufs_reset(&bufs, obd->obd_name);
+ lustre_cfg_bufs_set_string(&bufs, 1, flags);
+ lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
+ if (lcfg == NULL)
+ RETURN(-ENOMEM);
rc = class_process_config(lcfg);
if (rc) {
*/
static unsigned
-uuid_hash(cfs_hash_t *hs, const void *key, unsigned mask)
+uuid_hash(struct cfs_hash *hs, const void *key, unsigned mask)
{
return cfs_hash_djb2_hash(((struct obd_uuid *)key)->uuid,
sizeof(((struct obd_uuid *)key)->uuid), mask);
}
static void
-uuid_export_get(cfs_hash_t *hs, struct hlist_node *hnode)
+uuid_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
{
struct obd_export *exp;
}
static void
-uuid_export_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+uuid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
{
struct obd_export *exp;
class_export_put(exp);
}
-static cfs_hash_ops_t uuid_hash_ops = {
+static struct cfs_hash_ops uuid_hash_ops = {
.hs_hash = uuid_hash,
.hs_key = uuid_key,
.hs_keycmp = uuid_keycmp,
*/
static unsigned
-nid_hash(cfs_hash_t *hs, const void *key, unsigned mask)
+nid_hash(struct cfs_hash *hs, const void *key, unsigned mask)
{
return cfs_hash_djb2_hash(key, sizeof(lnet_nid_t), mask);
}
}
static void
-nid_export_get(cfs_hash_t *hs, struct hlist_node *hnode)
+nid_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
{
struct obd_export *exp;
}
static void
-nid_export_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+nid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
{
struct obd_export *exp;
class_export_put(exp);
}
-static cfs_hash_ops_t nid_hash_ops = {
+static struct cfs_hash_ops nid_hash_ops = {
.hs_hash = nid_hash,
.hs_key = nid_key,
.hs_keycmp = nid_kepcmp,
}
static void
-nidstats_get(cfs_hash_t *hs, struct hlist_node *hnode)
+nidstats_get(struct cfs_hash *hs, struct hlist_node *hnode)
{
struct nid_stat *ns;
}
static void
-nidstats_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+nidstats_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
{
struct nid_stat *ns;
nidstat_putref(ns);
}
-static cfs_hash_ops_t nid_stat_hash_ops = {
+static struct cfs_hash_ops nid_stat_hash_ops = {
.hs_hash = nid_hash,
.hs_key = nidstats_key,
.hs_keycmp = nidstats_keycmp,
.hs_get = nidstats_get,
.hs_put_locked = nidstats_put_locked,
};
+
+
+/*
+ * client_generation<->export hash operations
+ */
+
+static unsigned
+gen_hash(struct cfs_hash *hs, const void *key, unsigned mask)
+{
+ return cfs_hash_djb2_hash(key, sizeof(__u32), mask);
+}
+
+static void *
+gen_key(struct hlist_node *hnode)
+{
+ struct obd_export *exp;
+
+ exp = hlist_entry(hnode, struct obd_export, exp_gen_hash);
+
+ RETURN(&exp->exp_target_data.ted_lcd->lcd_generation);
+}
+
+/*
+ * NOTE: It is impossible to find an export that is in failed
+ * state with this function
+ */
+static int
+gen_kepcmp(const void *key, struct hlist_node *hnode)
+{
+ struct obd_export *exp;
+
+ LASSERT(key);
+ exp = hlist_entry(hnode, struct obd_export, exp_gen_hash);
+
+ RETURN(exp->exp_target_data.ted_lcd->lcd_generation == *(__u32 *)key &&
+ !exp->exp_failed);
+}
+
+static void *
+gen_export_object(struct hlist_node *hnode)
+{
+ return hlist_entry(hnode, struct obd_export, exp_gen_hash);
+}
+
+static void
+gen_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
+{
+ struct obd_export *exp;
+
+ exp = hlist_entry(hnode, struct obd_export, exp_gen_hash);
+ class_export_get(exp);
+}
+
+static void
+gen_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
+{
+ struct obd_export *exp;
+
+ exp = hlist_entry(hnode, struct obd_export, exp_gen_hash);
+ class_export_put(exp);
+}
+
+static struct cfs_hash_ops gen_hash_ops = {
+ .hs_hash = gen_hash,
+ .hs_key = gen_key,
+ .hs_keycmp = gen_kepcmp,
+ .hs_object = gen_export_object,
+ .hs_get = gen_export_get,
+ .hs_put_locked = gen_export_put_locked,
+};