__u32 ldd_flags; /* LDD_SV_TYPE */
__u32 ldd_svindex; /* server index (0001), must match
svname */
-/*28*/ char ldd_fsname[64]; /* filesystem this server is part of */
+ __u32 ldd_mount_type; /* target fs type LDD_MT_* */
+ char ldd_fsname[64]; /* filesystem this server is part of */
char ldd_svname[64]; /* this server's name (lustre-mdt0001)*/
- enum ldd_mount_type ldd_mount_type; /* target fs type LDD_MT_* */
- __u16 ldd_mgsnid_count;
- __u16 ldd_failnid_count; /* server failover nid count */
-/*164*/ lnet_nid_t ldd_mgsnid[MTI_NIDS_MAX]; /* mgs nids; lmd can override */
- lnet_nid_t ldd_failnid[MTI_NIDS_MAX]; /* server failover nids */
- __u16 ldd_mgsnode[8]; /* nid count of each node in... */
- __u16 ldd_failnode[8]; /* ...the nid arrays */
-
-/*1220*/__u8 ldd_uuid[40]; /* server UUID (COMPAT_146) */
+ __u8 ldd_uuid[40]; /* server UUID (COMPAT_146) */
-/*1260*/__u8 ldd_padding[4096 - 1260];
-/*4096*/char ldd_mount_opts[4094]; /* target fs mount opts */
+/*200*/ __u8 ldd_padding[4096 - 200];
+/*4096*/char ldd_mount_opts[4096]; /* target fs mount opts */
+/*8192*/char ldd_params[4096]; /* key=value pairs */
};
#define IS_MDT(data) ((data)->ldd_flags & LDD_F_SV_TYPE_MDT)
struct lustre_mount_data {
__u32 lmd_magic;
__u32 lmd_flags; /* lustre mount flags */
- int lmd_mgsnid_count; /* how many failover nids we have for
- the MGS */
+ int lmd_mgs_failnodes; /* mgs failover node count */
int lmd_exclude_count;
- char *lmd_dev; /* device or file system name */
+ char *lmd_dev; /* device name */
+ char *lmd_fs; /* file system name (client only) */
char *lmd_opts; /* lustre mount options (as opposed to
_device_ mount options) */
__u32 *lmd_exclude; /* array of OSTs to ignore */
- lnet_nid_t lmd_mgsnid[MTI_NIDS_MAX];/* who to contact at startup */
};
#define LMD_FLG_CLIENT 0x0002 /* Mounting a client only */
__u64 mo_device_sz; /* in KB */
int mo_stripe_count;
int mo_flags;
+ int mo_mgs_failnodes;
};
/****************** last_rcvd file *********************/
# define s2lsi_nocast(sb) ((sb)->u.generic_sbp)
#endif
-#define get_profile_name(sb) (s2lsi(sb)->lsi_lmd->lmd_dev)
+#define get_profile_name(sb) (s2lsi(sb)->lsi_lmd->lmd_fs)
#endif /* __KERNEL__ */
#endif
-
#endif // _LUSTRE_DISK_H
__u32 mti_failnid_count;
__u32 mti_config_ver;
__u32 mti_flags;
+ char mti_params[2048];
};
extern void lustre_swab_mgs_target_info(struct mgs_target_info *oinfo);
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2006 Cluster File Systems, Inc.
+ * Author: Nathan Rutman <nathan@clusterfs.com>
+ *
+ * This file is part of Lustre, http://www.lustre.org.
+ *
+ * Lustre is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * Lustre is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Lustre; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * User-settable parameter keys
+ */
+
+#ifndef _LUSTRE_PARAM_H
+#define _LUSTRE_PARAM_H
+
+/* obd_mount.c */
+int class_find_param(char *buf, char *key, char **valp);
+int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh);
+
+
+/****************** User-settable parameter keys *********************/
+
+#define PARAM_MGSNODE "mgsnode="
+#define PARAM_FAILNODE "failnode="
+#define PARAM_OBD_TIMEOUT "obd_timeout="
+#define PARAM_DEFAULT_STRIPE "default_stripe_"
+#define PARAM_D_STRIPE_SIZE PARAM_DEFAULT_STRIPE"size"
+#define PARAM_D_STRIPE_COUNT PARAM_DEFAULT_STRIPE"count"
+#define PARAM_D_STRIPE_OFFSET PARAM_DEFAULT_STRIPE"offset"
+#define PARAM_D_STRIPE_PATTERN PARAM_DEFAULT_STRIPE"pattern"
+
+#endif // _LUSTRE_PARAM_H
#include <linux/obd_lov.h>
#include <linux/obd_ost.h>
#include <linux/lprocfs_status.h>
+#include <linux/lustre_param.h>
#include "lov_internal.h"
}
*sval = 0;
val = simple_strtol(sval + 1, NULL, 0);
- if (strcmp(key, "default_stripe_size") == 0)
+ if (strcmp(key, PARAM_D_STRIPE_SIZE) == 0)
desc->ld_default_stripe_size = val;
- else if (strcmp(key, "default_stripe_count") == 0)
+ else if (strcmp(key, PARAM_D_STRIPE_COUNT) == 0)
desc->ld_default_stripe_count = val;
- else if (strcmp(key, "default_stripe_offset") == 0)
+ else if (strcmp(key, PARAM_D_STRIPE_OFFSET) == 0)
desc->ld_default_stripe_offset = val;
- else if (strcmp(key, "default_stripe_pattern") == 0)
+ else if (strcmp(key, PARAM_D_STRIPE_PATTERN) == 0)
desc->ld_pattern = val;
else {
CERROR("Unknown param %s\n", key);
}
rc = fsfilt_set_md(obd, inode, *handle, lmm, lmm_size);
- lmm_buf = lustre_msg_buf(req->rq_repmsg, offset, 0);
- lmm_bufsize = req->rq_repmsg->buflens[offset];
- LASSERT(lmm_buf);
- LASSERT(lmm_bufsize >= lmm_size);
-
- memcpy(lmm_buf, lmm, lmm_size);
+ lmm_buf = lustre_msg_buf(req->rq_repmsg, offset, lmm_size);
+ if (!lmm_buf) {
+ CERROR("Can't allocate reply buffer size=%d\n", lmm_size);
+ rc = -ENOMEM;
+ } else {
+ memcpy(lmm_buf, lmm, lmm_size);
+ }
obd_free_diskmd(mds->mds_osc_exp, &lmm);
out_oa:
oti_free_cookies(&oti);
/* fsname is at most 8 chars long at the beginning of the logname
e.g. "lustre-MDT0001" or "lustre" */
- name_end = strchr(logname, '-');
+ name_end = strrchr(logname, '-');
if (name_end)
len = name_end - logname;
else
len = strlen(logname);
- LASSERT(len <= 8);
+ if (len > 8) {
+ CERROR("fsname too long: %s\n", logname);
+ return -EINVAL;
+ }
memcpy(&resname, logname, len);
memset(res_id, 0, sizeof(*res_id));
strlen(cfg->cfg_instance) + 1);
strcpy(cld->cld_cfg.cfg_instance, cfg->cfg_instance);
}
- mgc_logname2resid(logname, &cld->cld_resid);
+ rc = mgc_logname2resid(logname, &cld->cld_resid);
+ if (rc) {
+ config_log_put(cld);
+ RETURN(rc);
+ }
spin_lock(&config_list_lock);
list_add(&cld->cld_list_chain, &config_llog_list);
spin_unlock(&config_list_lock);
req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MGS_VERSION,
MGS_TARGET_REG, 1, &size, NULL);
if (!req)
- RETURN(rc = -ENOMEM);
+ RETURN(-ENOMEM);
req_mti = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*req_mti));
+ if (!req_mti)
+ RETURN(-ENOMEM);
memcpy(req_mti, mti, sizeof(*req_mti));
req->rq_replen = lustre_msg_size(1, &rep_size);
cfg->cfg_last_idx);
/* We're only called through here on the initial mount */
- config_log_add(logname, cfg, sb);
-
+ rc = config_log_add(logname, cfg, sb);
+ if (rc)
+ break;
cld = config_log_find(logname, cfg);
if (IS_ERR(cld)) {
rc = PTR_ERR(cld);
- } else {
- /* COMPAT_146 */
- /* For old logs, there was no start marker. */
- /* FIXME only set this for old logs! */
- cld->cld_cfg.cfg_flags |= CFG_F_MARKER;
-
- rc = mgc_process_log(obd, cld);
- config_log_put(cld);
+ break;
}
+
+ /* COMPAT_146 */
+ /* For old logs, there was no start marker. */
+ /* FIXME only set this for old logs! */
+ cld->cld_cfg.cfg_flags |= CFG_F_MARKER;
+
+ rc = mgc_process_log(obd, cld);
+ config_log_put(cld);
+
break;
}
case LCFG_LOG_END: {
ENTRY;
rc = mgc_logname2resid(fsname, &res_id);
-
- rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, res_id,
- LDLM_PLAIN, NULL, LCK_EX, &flags,
- ldlm_blocking_ast, ldlm_completion_ast,
- NULL, fsname, NULL, 0, NULL, lockh);
- if (rc) {
- CERROR("can't take cfg lock %d\n", rc);
- }
+ if (!rc)
+ rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, res_id,
+ LDLM_PLAIN, NULL, LCK_EX, &flags,
+ ldlm_blocking_ast, ldlm_completion_ast,
+ NULL, fsname, NULL, 0, NULL, lockh);
+ if (rc)
+ CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
RETURN(rc);
}
#include <linux/lvfs.h>
#include <linux/lustre_fsfilt.h>
#include <linux/lustre_disk.h>
+#include <linux/lustre_param.h>
#include "mgs_internal.h"
return 0;
}
-static inline void name_destroy(char *newname)
+static inline void name_destroy(char *name)
{
- if (newname)
- OBD_FREE(newname, strlen(newname) + 1);
+ if (name)
+ OBD_FREE(name, strlen(name) + 1);
}
struct llog_handle *llh,
char *cliname)
{
- char *failnodeuuid;
+ char *failnodeuuid = NULL;
+ char *ptr = mti->mti_params;
lnet_nid_t nid;
- int i, j = 0, rc = 0;
-
- if (!mti->mti_failnid_count)
- return 0;
+ int rc = 0;
/*
#03 L add_uuid nid=uml1@tcp(0x20000c0a80201) nal=90 0: 1:uml1_UUID
#0x L add_uuid nid=2@elan(0x1000000000002) nal=90 0: 1:uml2_UUID
#07 L add_conn 0:OSC_uml1_ost1_mdsA 1:uml2_UUID
*/
-
- /* We don't know the failover node name, so just use the first nid
- as the uuid */
- name_create(libcfs_nid2str(mti->mti_failnids[0]), "", &failnodeuuid);
- for (i = 0; i < mti->mti_failnid_count; i++) {
- nid = mti->mti_failnids[i];
- if (mti->mti_failnodes[j] && (i >= mti->mti_failnodes[j])) {
- /* This is the first nid of a new failover node.
- add_conn the old uuid, and start a new one. */
+
+ /* Pull failnid info out of params string */
+ while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
+ while (class_parse_nid(ptr, &nid, &ptr) == 0) {
+ if (failnodeuuid == NULL) {
+ /* We don't know the failover node name,
+ so just use the first nid as the uuid */
+ rc = name_create(libcfs_nid2str(nid), "",
+ &failnodeuuid);
+ if (rc)
+ return rc;
+ }
+ CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
+ "client %s\n", libcfs_nid2str(nid),
+ failnodeuuid, cliname);
+ rc = record_add_uuid(obd, llh, nid, failnodeuuid);
+ }
+ if (failnodeuuid) {
rc = record_add_conn(obd, llh, cliname, failnodeuuid);
name_destroy(failnodeuuid);
- name_create(libcfs_nid2str(mti->mti_failnids[i]),
- "", &failnodeuuid);
- j++;
+ failnodeuuid = NULL;
}
- CDEBUG(D_MGS, "add nid %s for failover uuid %s, client %s\n",
- libcfs_nid2str(nid), failnodeuuid, cliname);
- rc = record_add_uuid(obd, llh, nid, failnodeuuid);
}
- rc = record_add_conn(obd, llh, cliname, failnodeuuid);
- name_destroy(failnodeuuid);
return rc;
}
RETURN(-EINVAL);
}
-
/* Add failover nids to client log */
name_create(mti->mti_fsname, "-client", &logname);
rc = record_start_log(obd, &llh, logname);
if just one nid is missing, add uuid for nodeuuid[nid0]).
*/
-
+ /* Hey, we can just check mti->params to see if we're already in
+ the failover list */
+
down(&fsdb->fsdb_sem);
rc = mgs_write_log_add_failnid(obd, fsdb, mti);
up(&fsdb->fsdb_sem);
return(rc);
}
-static int dentry_readdir(struct obd_device *obd, struct dentry *dir,
- struct vfsmount *inmnt,
- struct list_head *dentry_list){
+static int class_dentry_readdir(struct obd_device *obd, struct dentry *dir,
+ struct vfsmount *inmnt,
+ struct list_head *dentry_list){
/* see mds_cleanup_pending */
struct lvfs_run_ctxt saved;
struct file *file;
ENTRY;
/* Find all the logs in the CONFIGS directory */
- rc = dentry_readdir(obd, mgs->mgs_configs_dir,
- mgs->mgs_vfsmnt, &dentry_list);
+ rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
+ mgs->mgs_vfsmnt, &dentry_list);
if (rc) {
CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
RETURN(rc);
name_destroy(logname);
/* Find all the logs in the CONFIGS directory */
- rc = dentry_readdir(obd, mgs->mgs_configs_dir,
- mgs->mgs_vfsmnt, &dentry_list);
+ rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
+ mgs->mgs_vfsmnt, &dentry_list);
if (rc) {
CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
RETURN(rc);
EXIT;
}
-/* returns 1 if key matches, else 0 */
-static int class_match_key(char *key, char *buf, char **valh)
-{
- char *val;
- *valh = NULL;
-
- if (strncmp(key, buf, strlen(key)) != 0)
- return 0;
-
- val = strchr(buf, '=');
- if (!val || (*(++val) == 0)) {
- CERROR("Key has no value %s\n", buf);
- return 0;
- }
- if (val - buf > strlen(key) + 1) {
- /* We didn't match the entire key */
- return 0;
- }
-
- *valh = val;
- return 1;
-}
-
/* Set a permanent (config log) param for a target or fs */
int mgs_setparam(struct obd_device *obd, char *fsname, struct lustre_cfg *lcfg)
{
/* add failover nidlist */
if ((lcfg->lcfg_command == LCFG_PARAM) &&
- class_match_key("failnid", lustre_cfg_string(lcfg, 1), &val)) {
+ class_find_param(lustre_cfg_string(lcfg, 1),
+ PARAM_FAILNODE, &val)) {
struct mgs_target_info *mti;
- CDEBUG(D_MGS, "failnid, mod MDT, client\n");
+ CDEBUG(D_MGS, "failnode, mod MDT, client\n");
OBD_ALLOC_PTR(mti);
+ if (!mti)
+ GOTO(out, rc = -ENOMEM);
strcpy(mti->mti_fsname, fsname);
strcpy(mti->mti_svname, devname);
rc = server_name2index(devname, &mti->mti_stripe_index, NULL);
GOTO(out, rc);
}
mti->mti_flags = rc;
- /* FIXME add to lctl. nids must be in lnet_nid_t
- form, not ascii - we can't resolve hostnames from the
- kernel. */
- mti->mti_failnid_count = simple_strtoul(val, NULL, 10);
- memcpy(mti->mti_failnids, lustre_cfg_string(lcfg, 2),
- mti->mti_failnid_count * sizeof(mti->mti_failnids[0]));
- /* assume these are nids for a single node. */
+ strncpy(mti->mti_params, lustre_cfg_string(lcfg, 1),
+ sizeof(mti->mti_params));
+ /* FIXME add to lctl. nids must be in dotted-quad ascii -
+ we can't resolve hostnames from the kernel. */
rc = mgs_write_log_add_failnid(obd, fsdb, mti);
OBD_FREE_PTR(mti);
GOTO(out, rc);
}
/* lov default stripe params */
- if ((lcfg->lcfg_command == LCFG_PARAM) && strstr(devname, "-mdtlov")) {
+ if ((lcfg->lcfg_command == LCFG_PARAM) &&
+ class_find_param(lustre_cfg_string(lcfg, 1),
+ PARAM_DEFAULT_STRIPE, &val)) {
char *lovname, *logname;
CDEBUG(D_MGS, "lov param, mod MDT, client\n");
name_create(fsname, "-MDT0000", &logname);
return -ENOENT;
}
+/* Add a nid to a niduuid. Multiple nids can be added to a single uuid;
+ LNET will choose the best one. */
int class_add_uuid(char *uuid, __u64 nid)
{
struct uuid_nid_data *data;
return 0;
}
-/* delete only one entry if uuid is specified, otherwise delete all */
+/* Delete the nids for one uuid if specified, otherwise delete all */
int class_del_uuid (char *uuid)
{
struct list_head deathrow;
#include <linux/version.h>
#include <linux/lustre_log.h>
#include <linux/lustre_disk.h>
+#include <linux/lustre_param.h>
#include <linux/lustre_ver.h>
static int (*client_fill_super)(struct super_block *sb) = NULL;
+/*********** string parsing utils *********/
+
+/* returns 0 if key matches as far as keylen, else 1 */
+int class_find_param(char *buf, char *key, char **valp)
+{
+ char *ptr;
+
+ if (!buf)
+ return 1;
+
+ if ((ptr = strstr(buf, key)) == NULL)
+ return 1;
+
+ if (valp)
+ *valp = ptr + strlen(key);
+
+ return 0;
+}
+
+/* 0 is good nid,
+ 1 not found
+ < 0 error
+ endh is set to next separator */
+int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh)
+{
+ char tmp, *endp;
+
+ if (!buf)
+ return 1;
+ while (*buf == ',' || *buf == ':')
+ buf++;
+ if (*buf == ' ' || *buf == '/' || *buf == '\0')
+ return 1;
+
+ /* nid separators or end of nids */
+ endp = strpbrk(buf, ",: /");
+ if (endp == NULL)
+ endp = buf + strlen(buf);
+
+ tmp = *endp;
+ *endp = '\0';
+ *nid = libcfs_str2nid(buf);
+ if (*nid == LNET_NID_ANY) {
+ LCONSOLE_ERROR("Can't parse NID '%s'\n", buf);
+ *endp = tmp;
+ return -EINVAL;
+ }
+ *endp = tmp;
+
+ if (endh)
+ *endh = endp;
+ CDEBUG(D_WARNING, "Nid %s\n", libcfs_nid2str(*nid));
+ return 0;
+}
/*********** mount lookup *********/
static void ldd_print(struct lustre_disk_data *ldd)
{
- int i;
-
PRINT_CMD(PRINT_MASK, " disk data:\n");
PRINT_CMD(PRINT_MASK, "config: %d\n", ldd->ldd_config_ver);
PRINT_CMD(PRINT_MASK, "fs: %s\n", ldd->ldd_fsname);
PRINT_CMD(PRINT_MASK, "flags: %#x\n", ldd->ldd_flags);
PRINT_CMD(PRINT_MASK, "diskfs: %s\n", MT_STR(ldd));
PRINT_CMD(PRINT_MASK, "options: %s\n", ldd->ldd_mount_opts);
- if (!ldd->ldd_mgsnid_count)
- PRINT_CMD(PRINT_MASK, "no MGS nids\n");
- else for (i = 0; i < ldd->ldd_mgsnid_count; i++) {
- PRINT_CMD(PRINT_MASK, "mgs nid %d: %s\n", i,
- libcfs_nid2str(ldd->ldd_mgsnid[i]));
- }
- if (!ldd->ldd_failnid_count)
- PRINT_CMD(PRINT_MASK, "no failover nids\n");
- else for (i = 0; i < ldd->ldd_failnid_count; i++) {
- PRINT_CMD(PRINT_MASK, "failover nid %d: %s\n", i,
- libcfs_nid2str(ldd->ldd_failnid[i]));
- }
+ PRINT_CMD(PRINT_MASK, "params: %s\n", ldd->ldd_params);
}
static int ldd_parse(struct lvfs_run_ctxt *mount_ctxt,
int rc;
ENTRY;
- LASSERT(mgc);
+ if (!mgc)
+ RETURN(-ENOENT);
/* mgc_process_config */
lustre_cfg_bufs_reset(&bufs, mgc->obd_name);
struct lustre_cfg * lcfg = NULL;
int rc;
- CDEBUG(D_TRACE, "lcfg %s %#x %s %s %s %s\n", cfgname,
+
+ CDEBUG((cmd==LCFG_ADD_UUID)?D_WARNING:D_TRACE,
+ "lcfg %s %#x %s %s %s %s\n", cfgname,
cmd, s1, s2, s3, s4);
lustre_cfg_bufs_reset(&bufs, cfgname);
struct obd_uuid *uuid;
class_uuid_t uuidc;
lnet_nid_t nid;
+ char niduuid[10];
+ char *ptr;
int recov_bk;
- int rc = 0, i;
+ int rc = 0, i = 0, j;
ENTRY;
LASSERT(lsi->lsi_lmd);
GOTO(out, rc = 0);
}
- if (lsi->lsi_lmd->lmd_mgsnid_count == 0) {
- LCONSOLE_ERROR("No NIDs for the MGS were given.\n");
- RETURN(-EINVAL);
- }
-
CDEBUG(D_MOUNT, "Start MGC '%s'\n", LUSTRE_MGC_OBDNAME);
- /* Add the first uuid for the MGS */
- nid = lsi->lsi_lmd->lmd_mgsnid[0];
- rc = do_lcfg(LUSTRE_MGC_OBDNAME, nid, LCFG_ADD_UUID,
- libcfs_nid2str(nid), 0,0,0);
- if (rc < 0)
- RETURN(rc);
+ /* Add the primary nids for the MGS */
+ if (lsi->lsi_flags & LSI_SERVER) {
+ ptr = lsi->lsi_ldd->ldd_params;
+ if (IS_MGS(lsi->lsi_ldd)) {
+ /* Use local nids (including LO) */
+ lnet_process_id_t id;
+ while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
+ rc = do_lcfg(LUSTRE_MGC_OBDNAME, id.nid,
+ LCFG_ADD_UUID, "mgsnid0", 0,0,0);
+ }
+ } else {
+ /* Use mgsnode= nids */
+ if (class_find_param(ptr, PARAM_MGSNODE, &ptr) != 0) {
+ CERROR("No MGS nids given.\n");
+ RETURN(-EINVAL);
+ }
+ while (class_parse_nid(ptr, &nid, &ptr) == 0) {
+ rc = do_lcfg(LUSTRE_MGC_OBDNAME, nid,
+ LCFG_ADD_UUID, "mgsnid0", 0,0,0);
+ i++;
+ }
+ }
+ } else { /* client */
+ /* use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
+ ptr = lsi->lsi_lmd->lmd_dev;
+ while (class_parse_nid(ptr, &nid, &ptr) == 0) {
+ rc = do_lcfg(LUSTRE_MGC_OBDNAME, nid,
+ LCFG_ADD_UUID, "mgsnid0", 0,0,0);
+ i++;
+ if (*ptr == ':')
+ break;
+ }
+ }
+ if (i == 0) {
+ CERROR("No valid MGS nids found.\n");
+ RETURN(-EINVAL);
+ }
+ lsi->lsi_lmd->lmd_mgs_failnodes = 1;
- /* Generate a unique uuid for each MGC */
+ /* Random uuid for MGC allows easier reconnects */
OBD_ALLOC_PTR(uuid);
-#if 0
- /* use the 1st non-loopback nid */
- lnet_process_id_t id;
- i = 0;
- while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
- if (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND)
- continue;
- break;
- }
- sprintf(uuid->uuid, "mgc_"LPX64, id.nid);
-#else
- /* random makes reconnect easier */
class_generate_random_uuid(uuidc);
class_uuid_unparse(uuidc, uuid);
-#endif
- CDEBUG(D_MOUNT, "generated uuid: %s\n", uuid->uuid);
/* Start the MGC */
rc = lustre_start_simple(LUSTRE_MGC_OBDNAME, LUSTRE_MGC_NAME,
(char *)uuid->uuid, LUSTRE_MGS_OBDNAME,
- libcfs_nid2str(nid));
+ "mgsnid0");
OBD_FREE_PTR(uuid);
if (rc)
RETURN(rc);
- /* Add the redundant MGS nids */
- for (i = 1; i < lsi->lsi_lmd->lmd_mgsnid_count; i++) {
- nid = lsi->lsi_lmd->lmd_mgsnid[i];
- rc = do_lcfg(LUSTRE_MGC_OBDNAME, nid, LCFG_ADD_UUID,
- libcfs_nid2str(nid), 0, 0, 0);
- if (rc) {
- CERROR("Add uuid for %s failed %d\n",
- libcfs_nid2str(nid), rc);
- continue;
+ /* Add any failover MGS nids */
+ i = 1;
+ while ((*ptr == ':' ||
+ class_find_param(ptr, PARAM_MGSNODE, &ptr) == 0)) {
+ /* New failover node */
+ sprintf(niduuid, "mgsnid%d", i);
+ j = 0;
+ while (class_parse_nid(ptr, &nid, &ptr) == 0) {
+ j++;
+ rc = do_lcfg(LUSTRE_MGC_OBDNAME, nid,
+ LCFG_ADD_UUID, niduuid, 0,0,0);
+ if (*ptr == ':')
+ break;
+ }
+ if (j > 0) {
+ rc = do_lcfg(LUSTRE_MGC_OBDNAME, 0, LCFG_ADD_CONN,
+ niduuid, 0, 0, 0);
+ i++;
+ } else {
+ /* at ":/fsname" */
+ break;
}
- rc = do_lcfg(LUSTRE_MGC_OBDNAME, 0, LCFG_ADD_CONN,
- libcfs_nid2str(nid), 0, 0, 0);
- if (rc)
- CERROR("Add conn for %s failed %d\n",
- libcfs_nid2str(nid), rc);
}
+ lsi->lsi_lmd->lmd_mgs_failnodes = i;
obd = class_name2obd(LUSTRE_MGC_OBDNAME);
if (!obd) {
{
struct lustre_sb_info *lsi = s2lsi(sb);
struct obd_device *obd;
- lnet_nid_t nid;
+ char niduuid[10];
int i, rc;
ENTRY;
if (rc)
RETURN(rc);
- /* class_add_uuid adds a nid even if the same uuid exists; we might
- delete any copy here. So they all better match. */
- for (i = 0; i < lsi->lsi_lmd->lmd_mgsnid_count; i++) {
- nid = lsi->lsi_lmd->lmd_mgsnid[i];
- rc = do_lcfg(obd->obd_name, nid, LCFG_DEL_UUID,
- libcfs_nid2str(nid), 0, 0, 0);
+ for (i = 0; i < lsi->lsi_lmd->lmd_mgs_failnodes; i++) {
+ sprintf(niduuid, "mgsnid%d", i);
+ rc = do_lcfg(obd->obd_name, 0, LCFG_DEL_UUID,
+ niduuid, 0, 0, 0);
if (rc)
CERROR("del MDC UUID %s failed: rc = %d\n",
- libcfs_nid2str(nid), rc);
+ niduuid, rc);
}
/* class_import_put will get rid of the additional connections */
int i = 0;
ENTRY;
- if (!mti)
- RETURN(-ENOMEM);
if (!(lsi->lsi_flags & LSI_SERVER))
RETURN(-EINVAL);
}
}
- mti->mti_failnid_count = ldd->ldd_failnid_count;
- memcpy(mti->mti_failnids, ldd->ldd_failnid, sizeof(mti->mti_failnids));
- memcpy(mti->mti_failnodes, ldd->ldd_failnode,
- sizeof(mti->mti_failnodes));
- memcpy(mti->mti_uuid, ldd->ldd_uuid, sizeof(mti->mti_uuid));
mti->mti_config_ver = 0;
mti->mti_flags = ldd->ldd_flags;
mti->mti_stripe_index = ldd->ldd_svindex;
+ memcpy(mti->mti_uuid, ldd->ldd_uuid, sizeof(mti->mti_uuid));
+ if (strlen(ldd->ldd_params) > sizeof(mti->mti_params)) {
+ CERROR("params too big for mti\n");
+ RETURN(-ENOMEM);
+ /* FIXME we can't send a msg much bigger than 4k - use bulk? */
+ }
+ memcpy(mti->mti_params, ldd->ldd_params, sizeof(mti->mti_params));
RETURN(0);
}
RETURN(-EINVAL);
OBD_ALLOC_PTR(mti);
+ if (!mti)
+ RETURN(-ENOMEM);
rc = server_sb2mti(sb, mti);
if (rc)
GOTO(out, rc);
{
struct lustre_sb_info *lsi = s2lsi(sb);
struct vfsmount *mnt;
- int mgs_service = 0, i = 0, rc;
+ int rc;
ENTRY;
/* the One True Mount */
GOTO(out, rc = -EALREADY);
}
- /* append on-disk MGS nids to mount-line MGS nids */
- for (i = 0; (i < lsi->lsi_ldd->ldd_mgsnid_count) &&
- (lsi->lsi_lmd->lmd_mgsnid_count < MTI_NIDS_MAX); i++) {
- lsi->lsi_lmd->lmd_mgsnid[lsi->lsi_lmd->lmd_mgsnid_count++] =
- lsi->lsi_ldd->ldd_mgsnid[i];
- }
-
/* start MGS before MGC */
if (IS_MGS(lsi->lsi_ldd)) {
rc = server_start_mgs(sb);
if (rc) {
CERROR("ignoring Failed MGS start!!\n");
//GOTO(out_mnt, rc);
- } else {
- /* add local nids (including LO) to MGS nids */
- lnet_process_id_t id;
- int j = lsi->lsi_lmd->lmd_mgsnid_count;
- i = 0;
- while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
- if (j >= MTI_NIDS_MAX)
- break;
- lsi->lsi_lmd->lmd_mgsnid[j++] = id.nid;
- }
- lsi->lsi_lmd->lmd_mgsnid_count = j;
-
- mgs_service++;
}
}
int i;
PRINT_CMD(PRINT_MASK, " mount data:\n");
- if (!lmd->lmd_mgsnid_count)
- PRINT_CMD(PRINT_MASK, "no MGS nids\n");
- else for (i = 0; i < lmd->lmd_mgsnid_count; i++) {
- PRINT_CMD(PRINT_MASK, "nid %d: %s\n", i,
- libcfs_nid2str(lmd->lmd_mgsnid[i]));
- }
if (lmd_is_client(lmd))
- PRINT_CMD(PRINT_MASK, "fsname: %s\n", lmd->lmd_dev);
- else
- PRINT_CMD(PRINT_MASK, "device: %s\n", lmd->lmd_dev);
+ PRINT_CMD(PRINT_MASK, "fsname: %s\n", lmd->lmd_fs);
+ PRINT_CMD(PRINT_MASK, "device: %s\n", lmd->lmd_dev);
PRINT_CMD(PRINT_MASK, "flags: %x\n", lmd->lmd_flags);
if (lmd->lmd_opts)
PRINT_CMD(PRINT_MASK, "options: %s\n", lmd->lmd_opts);
RETURN(0);
CDEBUG(D_MOUNT, "Check exclusion %s (%d) in %d of %s\n", svname,
- index, lmd->lmd_exclude_count, lmd->lmd_dev);
+ index, lmd->lmd_exclude_count, lmd->lmd_fs);
for(i = 0; i < lmd->lmd_exclude_count; i++) {
if (index == lmd->lmd_exclude[i]) {
/* terminate options right before device. device
must be the last one. */
*s1 = 0;
+ break;
}
/* Find next opt */
goto invalid;
}
- if (strchr(devname, ',')) {
- LCONSOLE_ERROR("Device name must be the final option\n");
- goto invalid;
- }
-
- s1 = devname;
- /* Get MGS nids if client mount: uml1@tcp:uml2@tcp:/fsname-client */
- while ((s2 = strchr(s1, ':'))) {
- lnet_nid_t nid;
- *s2 = 0;
+ s1 = strrchr(devname, ':');
+ if (s1) {
lmd->lmd_flags = LMD_FLG_CLIENT;
- nid = libcfs_str2nid(s1);
- if (nid == LNET_NID_ANY) {
- LCONSOLE_ERROR("Can't parse NID '%s'\n", s1);
- goto invalid;
- }
- if (lmd->lmd_mgsnid_count >= MTI_NIDS_MAX) {
- LCONSOLE_ERROR("Too many NIDs: '%s'\n", s1);
- goto invalid;
- }
- lmd->lmd_mgsnid[lmd->lmd_mgsnid_count++] = nid;
- s1 = s2 + 1;
- }
-
- if (lmd_is_client(lmd)) {
/* Remove leading /s from fsname */
- while (*++s1 == '/')
- ;
- }
-
- if (*s1 == 0) {
- LCONSOLE_ERROR("No filesytem specified\n");
- goto invalid;
- }
+ while (*++s1 == '/') ;
+ } else
+ s1 = devname;
/* freed in lustre_free_lsi */
- OBD_ALLOC(lmd->lmd_dev, strlen(s1) + 1);
+ OBD_ALLOC(lmd->lmd_dev, strlen(devname) + 1);
if (!lmd->lmd_dev)
RETURN(-ENOMEM);
- strcpy(lmd->lmd_dev, s1);
+ strcpy(lmd->lmd_dev, devname);
+ /* fsname is last part of devname for clients (mgsnid:/fsname) */
+ lmd->lmd_fs = lmd->lmd_dev + (s1 - devname);
/* save mount options */
s1 = options + strlen(options) - 1;
}
if (lmd_is_client(lmd)) {
- CDEBUG(D_MOUNT, "Mounting client for fs %s\n", lmd->lmd_dev);
+ CDEBUG(D_MOUNT, "Mounting client for fs %s\n", lmd->lmd_fs);
if (!client_fill_super) {
LCONSOLE_ERROR("Nothing registered for client mount!"
" Is llite module loaded?\n");
- rc = -ENOSYS;
+ rc = -ENODEV;
} else {
rc = lustre_start_mgc(sb);
if (rc)
CERROR("Unable to mount %s\n",
s2lsi(sb) ? lmd->lmd_dev : "");
} else {
- CDEBUG(D_MOUNT, "Successfully mounted %s\n", lmd->lmd_dev);
+ CDEBUG(D_MOUNT, "Successfully mounted %s\n", lmd->lmd_fs);
}
RETURN(rc);
}
EXPORT_SYMBOL(server_register_target);
EXPORT_SYMBOL(server_name2index);
EXPORT_SYMBOL(server_mti_print);
-
+EXPORT_SYMBOL(class_find_param);
+EXPORT_SYMBOL(class_parse_nid);
bufcount = m->bufcount;
if (n >= bufcount) {
- CDEBUG(D_INFO, "msg %p buffer[%d] not present (count %d)\n",
+ CERROR("msg %p buffer[%d] not present (count %d)\n",
m, n, bufcount);
return NULL;
}
#define NO_SYS_VFS 1
#include <linux/fs.h> // for BLKGETSIZE64
#include <linux/lustre_disk.h>
+#include <linux/lustre_param.h>
#include <lnet/lnetctl.h>
#include <linux/lustre_ver.h>
#include "obdctl.h"
void print_ldd(char *str, struct lustre_disk_data *ldd)
{
- int i = 0, j= 0;
printf("\n %s:\n", str);
printf("Target: %s\n", ldd->ldd_svname);
if (ldd->ldd_svindex == INDEX_UNASSIGNED)
ldd->ldd_flags & LDD_F_WRITECONF ? "writeconf ":"",
ldd->ldd_flags & LDD_F_UPGRADE14 ? "upgrade1.4 ":"");
printf("Persistent mount opts: %s\n", ldd->ldd_mount_opts);
- printf("MGS");
- j = 0;
- for (i = 0; i < ldd->ldd_mgsnid_count; i++) {
- if (i == 0 || i == ldd->ldd_mgsnode[j]) {
- if (i)
- j++;
- printf("\n node %d:", j + 1);
- }
- printf(" %s", libcfs_nid2str(ldd->ldd_mgsnid[i]));
- }
- printf("\nFailover");
- j = 0;
- for (i = 0; i < ldd->ldd_failnid_count; i++) {
- if (i == 0 || i == ldd->ldd_failnode[j]) {
- if (i)
- j++;
- printf("\n node %d:", j + 1);
- }
- printf(" %s", libcfs_nid2str(ldd->ldd_failnid[i]));
- }
-
+ printf("Parameters:%s\n", ldd->ldd_params);
printf("\n");
}
if (ret) {
fprintf(stderr, "%s: Unable to mount %s: %s\n",
progname, dev, strerror(errno));
+ if (errno == ENODEV) {
+ fprintf(stderr, "Is the %s module available?\n",
+ MT_STR(&mop->mo_ldd));
+ }
goto out_rmdir;
}
mop->mo_ldd.ldd_magic = LDD_MAGIC;
mop->mo_ldd.ldd_config_ver = 1;
mop->mo_ldd.ldd_flags = LDD_F_NEED_INDEX | LDD_F_UPDATE | LDD_F_VIRGIN;
- mop->mo_ldd.ldd_mgsnid_count = 0;
+ mop->mo_mgs_failnodes = 0;
strcpy(mop->mo_ldd.ldd_fsname, "lustre");
if (get_os_version() == 24)
mop->mo_ldd.ldd_mount_type = LDD_MT_EXT3;
usage(stderr);
}
-
-static int parse_nids(int first_spec, char *buf, __u16 *count,
- lnet_nid_t *nids, __u16 *nodes)
-{
- int j, i = *count;
- char *s1 = buf, *s2;
-
- if (first_spec == 1) {
- /* for the first nid spec in a tunefs, we erase all old nid
- info */
- *count = 0; i = 0;
- for (j = 0; j < 8; j++)
- nodes[j] = 0;
+static int add_param(char *buf, char *key, char *val)
+{
+ int end = sizeof(((struct lustre_disk_data *)0)->ldd_params);
+ int start = strlen(buf);
+ int keylen = 0;
+
+ if (key)
+ keylen = strlen(key);
+ if (start + 1 + keylen + strlen(val) >= end) {
+ fprintf(stderr, "%s: params are too long-\n%s %s%s\n",
+ progname, buf, key ? key : "", val);
+ return 1;
}
- while ((s2 = strsep(&s1, ","))) {
- nids[i] = libcfs_str2nid(s2);
- if (nids[i] == LNET_NID_ANY) {
- fprintf(stderr, "%s: malformed nid %s\n",
+ sprintf(buf + start, " %s%s", key ? key : "", val);
+ return 0;
+}
+
+/* from mount_lustre */
+/* Get rid of symbolic hostnames for tcp, since kernel can't do lookups */
+#define MAXNIDSTR 1024
+static char *convert_hostnames(char *s1)
+{
+ char *converted, *s2 = 0, *c;
+ int left = MAXNIDSTR;
+ lnet_nid_t nid;
+
+ converted = malloc(left);
+ c = converted;
+ while ((left > 0) && ((s2 = strsep(&s1, ",: \0")))) {
+ nid = libcfs_str2nid(s2);
+ if (nid == LNET_NID_ANY) {
+ if (*s2 == '/')
+ /* end of nids */
+ break;
+ fprintf(stderr, "%s: Can't parse NID '%s'\n",
progname, s2);
- return 1;
+ free(converted);
+ return NULL;
}
- i++;
- if (i >= MTI_NIDS_MAX) {
- fprintf(stderr, "%s: too many nids (%s...)\n",
- progname, s1);
- return 1;
+ if (LNET_NETTYP(LNET_NIDNET(nid)) == SOCKLND) {
+ __u32 addr = LNET_NIDADDR(nid);
+ c += snprintf(c, left, "%u.%u.%u.%u@%s%u,",
+ (addr >> 24) & 0xff, (addr >> 16) & 0xff,
+ (addr >> 8) & 0xff, addr & 0xff,
+ libcfs_lnd2str(SOCKLND),
+ LNET_NETNUM(LNET_NIDNET(nid)));
+ } else {
+ c += snprintf(c, left, "%s,", s2);
}
+ left = converted + MAXNIDSTR - c;
}
- if (i == *count)
- return 0;
-
- /* mark the last nid index in the node array */
- j = 0;
- while (nodes[j] && (j < 8))
- j++;
- if (j >= 8) {
- fprintf(stderr, "%s: too many nodes (%s...)\n",
- progname, buf);
- return 1;
- }
- *count = i;
- nodes[j] = i;
- return 0;
+ *(c - 1) = '\0';
+ return converted;
}
int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
{"stripe-count-hint", 1, 0, 'c'},
{"configdev", 1, 0, 'C'},
{"device-size", 1, 0, 'd'},
+ {"erase-params", 0, 0, 'e'},
{"failnode", 1, 0, 'f'},
{"failover", 1, 0, 'f'},
{"mgs", 0, 0, 'G'},
{"nomgs", 0, 0, 'N'},
{"mountfsoptions", 1, 0, 'o'},
{"ost", 0, 0, 'O'},
- {"print", 0, 0, 'p'},
+ {"param", 1, 0, 'p'},
+ {"print", 0, 0, 'P'},
{"quiet", 0, 0, 'q'},
{"reformat", 0, 0, 'r'},
{"verbose", 0, 0, 'v'},
{"writeconf", 0, 0, 'w'},
{0, 0, 0, 0}
};
- char *optstring = "b:c:C:d:f:Ghi:k:m:Mn:No:Opqrvw";
+ char *optstring = "b:c:C:d:ef:Ghi:k:m:Mn:No:Op:Pqrvw";
char opt;
- int longidx;
+ int rc, longidx;
while ((opt = getopt_long(argc, argv, optstring, long_opt, &longidx)) !=
EOF) {
case 'd':
mop->mo_device_sz = atol(optarg);
break;
+ case 'e':
+ mop->mo_ldd.ldd_params[0] = '\0';
+ break;
case 'f': {
- int rc;
- static int first_fail_spec = 1;
- rc = parse_nids(first_fail_spec, optarg,
- &mop->mo_ldd.ldd_failnid_count,
- mop->mo_ldd.ldd_failnid,
- mop->mo_ldd.ldd_failnode);
- if (rc) {
- fprintf(stderr, "%s: bad failover nids\n",
- progname);
+ char *nids = convert_hostnames(optarg);
+ if (!nids)
return 1;
- }
- mop->mo_ldd.ldd_flags |= LDD_F_UPDATE;
- first_fail_spec++;
+ rc = add_param(mop->mo_ldd.ldd_params, PARAM_FAILNODE,
+ nids);
+ free(nids);
+ if (rc)
+ return rc;
break;
}
case 'G':
sizeof(mop->mo_mkfsopts) - 1);
break;
case 'm': {
- int rc;
- static int first_mgs_spec = 1;
- if (IS_MGS(&mop->mo_ldd)) {
- badopt(long_opt[longidx].name,
- "non-MGS MDT,OST");
+ char *nids = convert_hostnames(optarg);
+ if (!nids)
return 1;
- }
- rc = parse_nids(first_mgs_spec, optarg,
- &mop->mo_ldd.ldd_mgsnid_count,
- mop->mo_ldd.ldd_mgsnid,
- mop->mo_ldd.ldd_mgsnode);
- if (rc) {
- fprintf(stderr, "%s: bad MGS nids\n",
- progname);
- return 1;
- }
- first_mgs_spec++;
+ rc = add_param(mop->mo_ldd.ldd_params, PARAM_MGSNODE,
+ nids);
+ free(nids);
+ if (rc)
+ return rc;
+ mop->mo_mgs_failnodes++;
break;
}
case 'M':
mop->mo_ldd.ldd_flags |= LDD_F_SV_TYPE_OST;
break;
case 'p':
+ rc = add_param(mop->mo_ldd.ldd_params, NULL, optarg);
+ if (rc)
+ return rc;
+ break;
+ case 'P':
print_only++;
break;
case 'q':
char default_mountopts[512] = "";
int ret = 0;
- assert(offsetof(struct lustre_disk_data, ldd_padding) == 1260);
+ //printf("pad %d\n", offsetof(struct lustre_disk_data, ldd_padding));
+ assert(offsetof(struct lustre_disk_data, ldd_padding) == 200);
if ((progname = strrchr(argv[0], '/')) != NULL)
progname++;
goto out;
}
- if (IS_MDT(ldd) && !IS_MGS(ldd) && ldd->ldd_mgsnid_count == 0) {
+ if (IS_MDT(ldd) && !IS_MGS(ldd) && (mop.mo_mgs_failnodes == 0)) {
vprint("No management node specified, adding MGS to this "
"MDT\n");
ldd->ldd_flags |= LDD_F_SV_TYPE_MGS;
}
- if (!IS_MGS(ldd) && (ldd->ldd_mgsnid_count == 0)) {
+ if (!IS_MGS(ldd) && (mop.mo_mgs_failnodes == 0)) {
fatal();
- fprintf(stderr, "Must specify either --mgs or --mgsnid\n");
+ fprintf(stderr, "Must specify either --mgs or --mgsnode\n");
usage(stderr);
goto out;
}
static char *convert_hostnames(char *s1)
{
char *converted, *s2 = 0, *c;
+ char sep;
int left = MAXNIDSTR;
lnet_nid_t nid;
converted = malloc(left);
c = converted;
- while ((left > 0) && ((s2 = strsep(&s1, ",:")))) {
- nid = libcfs_str2nid(s2);
- if (nid == LNET_NID_ANY) {
- if (*s2 == '/')
- /* end of nids */
- break;
- fprintf(stderr, "%s: Can't parse NID '%s'\n",
- progname, s2);
- free(converted);
- return NULL;
- }
+ while ((left > 0) && (*s1 != '/')) {
+ s2 = strpbrk(s1, ",:");
+ if (!s2)
+ goto out_free;
+ sep = *s2;
+ *s2 = '\0';
+ nid = libcfs_str2nid(s1);
+ if (nid == LNET_NID_ANY)
+ goto out_free;
if (LNET_NETTYP(LNET_NIDNET(nid)) == SOCKLND) {
__u32 addr = LNET_NIDADDR(nid);
- c += snprintf(c, left, "%u.%u.%u.%u@%s%u:",
+ c += snprintf(c, left, "%u.%u.%u.%u@%s%u%c",
(addr >> 24) & 0xff, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff,
libcfs_lnd2str(SOCKLND),
- LNET_NETNUM(LNET_NIDNET(nid)));
+ LNET_NETNUM(LNET_NIDNET(nid)), sep);
} else {
- c += snprintf(converted, left, "%s:", s2);
+ c += snprintf(c, left, "%s%c", s1, sep);
}
left = converted + MAXNIDSTR - c;
+ s1 = s2 + 1;
}
- snprintf(c, left, "%s", s2);
+ snprintf(c, left, "%s", s1);
return converted;
+out_free:
+ fprintf(stderr, "%s: Can't parse NID '%s'\n", progname, s1);
+ free(converted);
+ return NULL;
}
/*****************************************************************************
if (errno == ENODEV)
fprintf(stderr, "Are the lustre modules loaded?\n"
"Check /etc/modules.conf and /proc/filesystems\n");
- rc = 32;
+ if (errno == ENOTBLK)
+ fprintf(stderr,"Does this filesystem have any OSTs?\n");
+ if (errno == ENOENT)
+ fprintf(stderr,"Is the mgs specification correct? "
+ "(%s)\n", source);
+ rc = errno;
} else if (!nomtab) {
rc = update_mtab_entry(source, target, "lustre", options,0,0,0);
}