*/
/*
* This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
*
* lustre/obdclass/obd_mount.c
*
#define D_MOUNT (D_SUPER|D_CONFIG/*|D_WARNING */)
#define PRINT_CMD CDEBUG
-#include <obd.h>
-#include <obd_class.h>
+#include <linux/inet.h>
#include <linux/random.h>
-#include <libcfs/linux/linux-uuid.h>
+#include <linux/uuid.h>
#include <linux/version.h>
+
+#include <obd.h>
+#include <obd_class.h>
+#include <lustre_crypto.h>
#include <lustre_log.h>
#include <lustre_disk.h>
#include <uapi/linux/lustre/lustre_param.h>
-#include <libcfs/crypto/llcrypt.h>
-
-static DEFINE_SPINLOCK(client_lock);
-static struct module *client_mod;
-static int (*client_fill_super)(struct super_block *sb);
-
-static void (*kill_super_cb)(struct super_block *sb);
/**************** config llog ********************/
"%s: Confguration from log %s failed from MGS %d. Communication error between node & MGS, a bad configuration, or other errors. See syslog for more info\n",
mgc->obd_name, logname, rc);
- /* class_obd_list(); */
RETURN(rc);
}
EXPORT_SYMBOL(lustre_process_log);
return rc;
}
+static int do_lcfg_nid(char *cfgname, struct lnet_nid *nid, int cmd,
+ char *s1)
+{
+ lnet_nid_t nid4 = 0;
+ char *nidstr = NULL;
+
+ if (nid_is_nid4(nid))
+ nid4 = lnet_nid_to_nid4(nid);
+ else
+ nidstr = libcfs_nidstr(nid);
+ return do_lcfg(cfgname, nid4, cmd, s1, nidstr, NULL, NULL);
+}
+
/**
* Call class_attach and class_setup. These methods in turn call
* OBD type-specific methods.
}
return rc;
}
+EXPORT_SYMBOL(lustre_start_simple);
static DEFINE_MUTEX(mgc_start_lock);
struct obd_export *exp;
struct obd_uuid *uuid = NULL;
uuid_t uuidc;
- lnet_nid_t nid;
+ struct lnet_nid nid;
char nidstr[LNET_NIDSTR_SIZE];
char *mgcname = NULL, *niduuid = NULL, *mgssec = NULL;
char *ptr;
(class_parse_nid(lsi->lsi_lmd->lmd_mgs, &nid, &ptr) == 0)) {
i++;
} else if (IS_MGS(lsi)) {
- struct lnet_process_id id;
+ struct lnet_processid id;
- while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
- if (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND)
+ while ((rc = LNetGetId(i++, &id, true)) != -ENOENT) {
+ if (nid_is_lo0(&id.nid))
continue;
nid = id.nid;
i++;
mutex_lock(&mgc_start_lock);
- libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
+ libcfs_nidstr_r(&nid, nidstr, sizeof(nidstr));
len = strlen(LUSTRE_MGC_OBDNAME) + strlen(nidstr) + 1;
OBD_ALLOC(mgcname, len);
OBD_ALLOC(niduuid, len + 2);
if (lmd_is_client(lsi->lsi_lmd)) {
int has_ir;
int vallen = sizeof(*data);
- __u32 *flags = &lsi->lsi_lmd->lmd_flags;
rc = obd_get_info(NULL, obd->obd_self_export,
strlen(KEY_CONN_DATA), KEY_CONN_DATA,
&vallen, data);
LASSERT(rc == 0);
has_ir = OCD_HAS_FLAG(data, IMP_RECOV);
- if (has_ir ^ !(*flags & LMD_FLG_NOIR)) {
+ if (has_ir ^ !test_bit(LMD_FLG_NOIR,
+ lsi->lsi_lmd->lmd_flags)) {
/* LMD_FLG_NOIR is for test purpose only */
LCONSOLE_WARN(
"Mounting client with IR setting not compatible with current MGC. Using MGC setting that is IR %s",
has_ir ? "enabled" : "disabled");
- if (has_ir)
- *flags &= ~LMD_FLG_NOIR;
- else
- *flags |= LMD_FLG_NOIR;
+ if (has_ir) {
+ clear_bit(LMD_FLG_NOIR,
+ lsi->lsi_lmd->lmd_flags);
+ } else {
+ set_bit(LMD_FLG_NOIR,
+ lsi->lsi_lmd->lmd_flags);
+ }
}
}
CDEBUG(D_MOUNT, "mgs NIDs %s.\n", ptr);
if (IS_MGS(lsi)) {
/* Use local NIDs (including LO) */
- struct lnet_process_id id;
+ struct lnet_processid id;
- while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
- rc = do_lcfg(mgcname, id.nid, LCFG_ADD_UUID,
- niduuid, NULL, NULL, NULL);
+ while ((rc = LNetGetId(i++, &id, true)) != -ENOENT) {
+ rc = do_lcfg_nid(mgcname, &id.nid,
+ LCFG_ADD_UUID,
+ niduuid);
}
} else {
/* Use mgsnode= nids */
* by commas.
*/
while (class_parse_nid(ptr, &nid, &ptr) == 0) {
- rc = do_lcfg(mgcname, nid, LCFG_ADD_UUID,
- niduuid, NULL, NULL, NULL);
+ rc = do_lcfg_nid(mgcname, &nid,
+ LCFG_ADD_UUID,
+ niduuid);
if (rc == 0)
++i;
/* Stop at the first failover NID */
/* 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(mgcname, nid, LCFG_ADD_UUID,
- niduuid, NULL, NULL, NULL);
+ rc = do_lcfg_nid(mgcname, &nid, LCFG_ADD_UUID,
+ niduuid);
if (rc == 0)
++i;
/* Stop at the first failover NID */
GOTO(out_free, rc = -ENOMEM);
generate_random_uuid(uuidc.b);
- snprintf(uuid->uuid, UUID_SIZE, "%pU", uuidc.b);
+ snprintf(uuid->uuid, sizeof(*uuid), "%pU", uuidc.b);
/* Start the MGC */
rc = lustre_start_simple(mgcname, LUSTRE_MGC_NAME,
sprintf(niduuid, "%s_%x", mgcname, i);
j = 0;
while (class_parse_nid_quiet(ptr, &nid, &ptr) == 0) {
- rc = do_lcfg(mgcname, nid, LCFG_ADD_UUID,
- niduuid, NULL, NULL, NULL);
+ rc = do_lcfg_nid(mgcname, &nid, LCFG_ADD_UUID,
+ niduuid);
if (rc == 0)
++j;
if (*ptr == ':')
data->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_AT |
OBD_CONNECT_FULL20 | OBD_CONNECT_IMP_RECOV |
OBD_CONNECT_LVB_TYPE |
- OBD_CONNECT_BULK_MBITS | OBD_CONNECT_BARRIER;
+ OBD_CONNECT_BULK_MBITS | OBD_CONNECT_BARRIER |
+ OBD_CONNECT_FLAGS2;
+ data->ocd_connect_flags2 = OBD_CONNECT2_REP_MBITS |
+ OBD_CONNECT2_LARGE_NID;
if (lmd_is_client(lsi->lsi_lmd) &&
- lsi->lsi_lmd->lmd_flags & LMD_FLG_NOIR)
+ test_bit(LMD_FLG_NOIR, lsi->lsi_lmd->lmd_flags))
data->ocd_connect_flags &= ~OBD_CONNECT_IMP_RECOV;
data->ocd_version = LUSTRE_VERSION_CODE;
rc = obd_connect(NULL, &exp, obd, uuid, data, NULL);
OBD_FREE(niduuid, len + 2);
RETURN(rc);
}
+EXPORT_SYMBOL(lustre_start_mgc);
-static int lustre_stop_mgc(struct super_block *sb)
+int lustre_stop_mgc(struct super_block *sb)
{
struct lustre_sb_info *lsi = s2lsi(sb);
struct obd_device *obd;
- char *niduuid = NULL, *ptr = NULL;
- int i, rc = 0, len = 0;
+ char niduuid[MAX_OBD_NAME + 6], *ptr = NULL;
+ int i, rc = 0;
ENTRY;
}
/*
- * Save the obdname for cleaning the nid uuids, which are
- * obdname_XX
+ * Cache the obdname for cleaning the nid uuids, which are
+ * obdname_XX before calling class_manual_cleanup
*/
- len = strlen(obd->obd_name) + 6;
- OBD_ALLOC(niduuid, len);
- if (niduuid) {
- strcpy(niduuid, obd->obd_name);
- ptr = niduuid + strlen(niduuid);
- }
+ strcpy(niduuid, obd->obd_name);
+ ptr = niduuid + strlen(niduuid);
rc = class_manual_cleanup(obd);
if (rc)
GOTO(out, rc);
- /* Clean the nid uuids */
- if (!niduuid)
- GOTO(out, rc = -ENOMEM);
-
for (i = 0; i < lsi->lsi_lmd->lmd_mgs_failnodes; i++) {
sprintf(ptr, "_%x", i);
rc = do_lcfg(LUSTRE_MGC_OBDNAME, 0, LCFG_DEL_UUID,
niduuid, rc);
}
out:
- if (niduuid)
- OBD_FREE(niduuid, len);
-
/* class_import_put will get rid of the additional connections */
mutex_unlock(&mgc_start_lock);
RETURN(rc);
}
+EXPORT_SYMBOL(lustre_stop_mgc);
/***************** lustre superblock **************/
-static struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
+struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
{
struct lustre_sb_info *lsi;
RETURN(NULL);
}
- lsi->lsi_lmd->lmd_exclude_count = 0;
- lsi->lsi_lmd->lmd_recovery_time_soft = 0;
- lsi->lsi_lmd->lmd_recovery_time_hard = 0;
s2lsi_nocast(sb) = lsi;
/* we take 1 extra ref for our setup */
- atomic_set(&lsi->lsi_mounts, 1);
+ kref_init(&lsi->lsi_mounts);
/* Default umount style */
lsi->lsi_flags = LSI_UMOUNT_FAILOVER;
RETURN(lsi);
}
+EXPORT_SYMBOL(lustre_init_lsi);
-static int lustre_free_lsi(struct super_block *sb)
+static int lustre_free_lsi(struct lustre_sb_info *lsi)
{
- struct lustre_sb_info *lsi = s2lsi(sb);
-
ENTRY;
LASSERT(lsi != NULL);
CDEBUG(D_MOUNT, "Freeing lsi %p\n", lsi);
/* someone didn't call server_put_mount. */
- LASSERT(atomic_read(&lsi->lsi_mounts) == 0);
+ LASSERT(kref_read(&lsi->lsi_mounts) == 0);
- llcrypt_sb_free(sb);
+ llcrypt_sb_free(lsi);
if (lsi->lsi_lmd != NULL) {
if (lsi->lsi_lmd->lmd_dev != NULL)
OBD_FREE(lsi->lsi_lmd->lmd_dev,
LASSERT(lsi->lsi_llsbi == NULL);
OBD_FREE_PTR(lsi);
- s2lsi_nocast(sb) = NULL;
RETURN(0);
}
+static void lustre_put_lsi_free(struct kref *kref)
+{
+ struct lustre_sb_info *lsi = container_of(kref, struct lustre_sb_info,
+ lsi_mounts);
+
+ if (IS_SERVER(lsi) && lsi->lsi_osd_exp) {
+ lu_device_put(&lsi->lsi_dt_dev->dd_lu_dev);
+ lsi->lsi_osd_exp->exp_obd->obd_lvfs_ctxt.dt = NULL;
+ lsi->lsi_dt_dev = NULL;
+ obd_disconnect(lsi->lsi_osd_exp);
+ /* wait till OSD is gone */
+ obd_zombie_barrier();
+ }
+ lustre_free_lsi(lsi);
+}
+
/*
* The lsi has one reference for every server that is using the disk -
* e.g. MDT, MGS, and potentially MGC
LASSERT(lsi != NULL);
- CDEBUG(D_MOUNT, "put %p %d\n", sb, atomic_read(&lsi->lsi_mounts));
- if (atomic_dec_and_test(&lsi->lsi_mounts)) {
- if (IS_SERVER(lsi) && lsi->lsi_osd_exp) {
- lu_device_put(&lsi->lsi_dt_dev->dd_lu_dev);
- lsi->lsi_osd_exp->exp_obd->obd_lvfs_ctxt.dt = NULL;
- lsi->lsi_dt_dev = NULL;
- obd_disconnect(lsi->lsi_osd_exp);
- /* wait till OSD is gone */
- obd_zombie_barrier();
- }
- lustre_free_lsi(sb);
+ CDEBUG(D_MOUNT, "put %p %d\n", sb, kref_read(&lsi->lsi_mounts));
+ if (kref_put(&lsi->lsi_mounts, lustre_put_lsi_free)) {
+ s2lsi_nocast(sb) = NULL;
RETURN(1);
}
RETURN(0);
}
+EXPORT_SYMBOL(lustre_put_lsi);
/*
* The goal of this function is to extract the file system name
}
EXPORT_SYMBOL(server_name2fsname);
+#ifdef HAVE_SERVER_SUPPORT
/**
* Get service name (svname) from string
* rc < 0 on error
return 0;
}
EXPORT_SYMBOL(server_name2svname);
+#endif /* HAVE_SERVER_SUPPORT */
/**
* check server name is OST.
* Get the index from the target name MDTXXXX/OSTXXXX
* rc = server type, or rc < 0 on error
**/
-int target_name2index(const char *tgtname, __u32 *idx, const char **endptr)
+int target_name2index(const char *tgtname, u32 *idx, const char **endptr)
{
const char *dash = tgtname;
- unsigned long index;
- int rc;
+ int type, len, rc;
+ u16 index;
if (strncmp(dash, "MDT", 3) == 0)
- rc = LDD_F_SV_TYPE_MDT;
+ type = LDD_F_SV_TYPE_MDT;
else if (strncmp(dash, "OST", 3) == 0)
- rc = LDD_F_SV_TYPE_OST;
+ type = LDD_F_SV_TYPE_OST;
else
return -EINVAL;
if (strncmp(dash, "all", 3) == 0) {
if (endptr != NULL)
*endptr = dash + 3;
- return rc | LDD_F_SV_ALL;
+ return type | LDD_F_SV_ALL;
}
- index = simple_strtoul(dash, (char **)endptr, 16);
- if (idx != NULL)
+ len = strspn(dash, "0123456789ABCDEFabcdef");
+ if (len > 4)
+ return -ERANGE;
+
+ if (strlen(dash) != len) {
+ char num[5];
+
+ num[4] = '\0';
+ memcpy(num, dash, sizeof(num) - 1);
+ rc = kstrtou16(num, 16, &index);
+ if (rc < 0)
+ return rc;
+ } else {
+ rc = kstrtou16(dash, 16, &index);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (idx)
*idx = index;
- if (index > 0xffff)
- return -ERANGE;
+ if (endptr)
+ *endptr = dash + len;
- return rc;
+ return type;
}
EXPORT_SYMBOL(target_name2index);
if (lmd_is_client(lmd))
PRINT_CMD(D_MOUNT, "profile: %s\n", lmd->lmd_profile);
PRINT_CMD(D_MOUNT, "device: %s\n", lmd->lmd_dev);
- PRINT_CMD(D_MOUNT, "flags: %x\n", lmd->lmd_flags);
if (lmd->lmd_opts)
PRINT_CMD(D_MOUNT, "options: %s\n", lmd->lmd_opts);
devmax = strlen(ptr) / 8 + 1;
/* temp storage until we figure out how many we have */
- OBD_ALLOC(exclude_list, sizeof(index) * devmax);
+ OBD_ALLOC_PTR_ARRAY(exclude_list, devmax);
if (!exclude_list)
RETURN(-ENOMEM);
if (lmd->lmd_exclude_count) {
/* permanent, freed in lustre_free_lsi */
- OBD_ALLOC(lmd->lmd_exclude, sizeof(index) *
- lmd->lmd_exclude_count);
+ OBD_ALLOC_PTR_ARRAY(lmd->lmd_exclude,
+ lmd->lmd_exclude_count);
if (lmd->lmd_exclude) {
memcpy(lmd->lmd_exclude, exclude_list,
sizeof(index) * lmd->lmd_exclude_count);
lmd->lmd_exclude_count = 0;
}
}
- OBD_FREE(exclude_list, sizeof(index) * devmax);
+ OBD_FREE_PTR_ARRAY(exclude_list, devmax);
RETURN(rc);
}
/* Collect multiple values for mgsnid specifiers */
static int lmd_parse_mgs(struct lustre_mount_data *lmd, char **ptr)
{
- lnet_nid_t nid;
+ struct lnet_nid nid;
char *tail = *ptr;
char *mgsnid;
int length;
/**
* Find the first delimiter (comma or colon) from the specified \a buf and
- * make \a *endh point to the string starting with the delimiter. The commas
- * in expression list [...] will be skipped.
+ * make \a *endh point to the string starting with the delimiter. The commas and
+ * colons in expression list [...] will be skipped. Colons that are part of a
+ * NID address are not considered delimiters.
*
* @buf a delimiter-separated string
* @endh a pointer to a pointer that will point to the string
*/
static bool lmd_find_delimiter(char *buf, char **endh)
{
- char *c = buf;
- size_t pos;
- bool found;
-
- if (!buf)
+ char *c;
+ char *at = NULL;
+ char *colon = NULL;
+ char *delim = NULL;
+ int brackets = 0;
+ int ncolons = 0;
+
+ if (!buf || *buf == '\0')
return false;
-try_again:
- if (*c == ',' || *c == ':')
- return true;
- pos = strcspn(c, "[:,]");
- if (!pos)
- return false;
+ c = buf;
+ do {
+ if (*c == '[') {
+ brackets++;
+ continue;
+ }
- /* Not a valid mount string */
- if (*c == ']') {
- CWARN("invalid mount string format\n");
- return false;
- }
+ if (*c == ']') {
+ brackets--;
+ if (brackets < 0) {
+ CWARN("imbalanced brackets detected in \"%s\"",
+ buf);
+ return false;
+ }
+ continue;
+ }
- c += pos;
- if (*c == '[') {
- c = strchr(c, ']');
+ /* Ignore all characters inside brackets */
+ if (brackets > 0)
+ continue;
- /* invalid mount string */
- if (!c) {
- CWARN("invalid mount string format\n");
- return false;
+ if (*c == ':') {
+ if (at) {
+ /* We previously saw an '@', so this ':' is a
+ * delimiter separating NIDs
+ */
+ delim = c;
+ break;
+ }
+
+ /* Record the first ':' that we find, as this may be a
+ * delimiter
+ */
+ if (!colon)
+ colon = c;
+
+ ncolons++;
+ if (ncolons > 2) {
+ /* Something like :::<foo>. The first ':' is a
+ * delimiter
+ */
+ delim = colon;
+ break;
+ }
+ continue;
}
- c++;
- goto try_again;
+
+ ncolons = 0;
+ if (*c == '@') {
+ at = c;
+ } else if (*c == ',') {
+ /* When we find a ',', we can determine whether a ':'
+ * seen earlier was a delimiter or part of a NID
+ */
+ if (colon && !at) {
+ /* We previously saw a ':', but never
+ * encountered an '@'. Thus, the ':' was a
+ * delimiter
+ */
+ delim = colon;
+ } else {
+ /* We either never saw a ':', or we saw both a
+ * ':' and an '@' (so the ':' was part of a
+ * NID). In both cases this ',' is our delimiter
+ */
+ delim = c;
+ }
+ break;
+ }
+ } while (c++ && *c != '\0');
+
+
+ if (brackets != 0) {
+ CWARN("imbalanced brackets detected in \"%s\"", buf);
+ return false;
}
- found = *c != '\0';
- if (found && endh)
- *endh = c;
+ if (!delim && colon && !at)
+ /* We saw a ':' but reached end of string without finding an '@'
+ * or ','. Thus, the ':' is considered a delimiter
+ */
+ delim = colon;
- return found;
+ if (delim && endh)
+ *endh = delim;
+
+ return delim != NULL;
}
/**
char *endp = buf;
char tmp;
int rc = 0;
+ int ncolons = 0;
- if (buf == NULL)
+ if (!buf)
return 1;
- while (*buf == ',' || *buf == ':')
+
+ while (*buf == ',' || *buf == ':') {
+ if (*buf == ':')
+ ncolons++;
+ else
+ ncolons = 0;
buf++;
+ }
+
+ /* IPv6 addresses can start with '::' */
+ if (ncolons >= 2)
+ buf = buf - 2;
+
if (*buf == ' ' || *buf == '/' || *buf == '\0')
return 1;
tmp = *endp;
*endp = '\0';
- if (cfs_parse_nidlist(buf, strlen(buf), &nidlist) <= 0)
+ /* FIXME: cfs_parse_nidlist does not support IPv6 addresses, so if
+ * buf contains a ':' and an '@' then we assume this is supposed to be
+ * an IPv6 address.
+ */
+ if (strchr(buf, ':')) {
+ struct in6_addr addr;
+ char *at;
+
rc = 1;
+ at = strchr(buf, '@');
+ if (at) {
+ *at = '\0';
+ rc = in6_pton(buf, -1, (u8 *)&addr.s6_addr, -1, NULL);
+ if (rc == 1)
+ rc = 0;
+ *at = '@';
+ }
+ } else if (cfs_parse_nidlist(buf, &nidlist) < 0) {
+ rc = 1;
+ }
+
cfs_free_nidlist(&nidlist);
+ /* Restore the delimiter */
*endp = tmp;
- if (rc != 0)
+
+ if (rc)
return rc;
- if (endh != NULL)
+
+ if (endh)
*endh = endp;
+
return 0;
}
* e.g. mount -v -t lustre -o abort_recov uml1:uml2:/lustre-client /mnt/lustre
* dev is passed as device=uml1:/lustre by mount.lustre_tgt
*/
-static int lmd_parse(char *options, struct lustre_mount_data *lmd)
+int lmd_parse(char *options, struct lustre_mount_data *lmd)
{
char *s1, *s2, *devname = NULL;
struct lustre_mount_data *raw = (struct lustre_mount_data *)options;
* Parse non-ldiskfs options here. Rather than modifying
* ldiskfs, we just zero these out here
*/
- if (strncmp(s1, "abort_recov", 11) == 0) {
- lmd->lmd_flags |= LMD_FLG_ABORT_RECOV;
+ if (!strncmp(s1, "abort_recov_mdt", 15) ||
+ !strncmp(s1, "abort_recovery_mdt", 18)) {
+ set_bit(LMD_FLG_ABORT_RECOV_MDT, lmd->lmd_flags);
+ clear++;
+ } else if (strncmp(s1, "abort_recov", 11) == 0) {
+ set_bit(LMD_FLG_ABORT_RECOV, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "recovery_time_soft=", 19) == 0) {
lmd->lmd_recovery_time_soft =
max_t(int, simple_strtoul(s1 + 19, NULL, 10),
time_min);
clear++;
- } else if (strncmp(s1, "no_precreate", 12) == 0) {
- lmd->lmd_flags |= LMD_FLG_NO_PRECREATE;
+ } else if (strncmp(s1, "no_create", 9) == 0 ||
+ /* no_precreate kept for 2.16 compatibility */
+ strncmp(s1, "no_precreate", 12) == 0) {
+ set_bit(LMD_FLG_NO_CREATE, lmd->lmd_flags);
clear++;
- } else if (strncmp(s1, "noir", 4) == 0) {
- lmd->lmd_flags |= LMD_FLG_NOIR; /* test purpose only. */
+ } else if (strncmp(s1, "noir", 4) == 0) { /* test case only */
+ set_bit(LMD_FLG_NOIR, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "nosvc", 5) == 0) {
- lmd->lmd_flags |= LMD_FLG_NOSVC;
+ set_bit(LMD_FLG_NOSVC, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "nomgs", 5) == 0) {
- lmd->lmd_flags |= LMD_FLG_NOMGS;
+ set_bit(LMD_FLG_NOMGS, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "noscrub", 7) == 0) {
- lmd->lmd_flags |= LMD_FLG_NOSCRUB;
+ set_bit(LMD_FLG_NOSCRUB, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "skip_lfsck", 10) == 0) {
- lmd->lmd_flags |= LMD_FLG_SKIP_LFSCK;
+ set_bit(LMD_FLG_SKIP_LFSCK, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "rdonly_dev", 10) == 0) {
- lmd->lmd_flags |= LMD_FLG_DEV_RDONLY;
+ set_bit(LMD_FLG_DEV_RDONLY, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, PARAM_MGSNODE,
sizeof(PARAM_MGSNODE) - 1) == 0) {
s3 = s2;
clear++;
} else if (strncmp(s1, "writeconf", 9) == 0) {
- lmd->lmd_flags |= LMD_FLG_WRITECONF;
+ set_bit(LMD_FLG_WRITECONF, lmd->lmd_flags);
+ clear++;
+ } else if (strncmp(s1, "nolocallogs", 11) == 0) {
+ set_bit(LMD_FLG_NO_LOCAL_LOGS, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "update", 6) == 0) {
- lmd->lmd_flags |= LMD_FLG_UPDATE;
+ set_bit(LMD_FLG_UPDATE, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "virgin", 6) == 0) {
- lmd->lmd_flags |= LMD_FLG_VIRGIN;
+ set_bit(LMD_FLG_VIRGIN, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "noprimnode", 10) == 0) {
- lmd->lmd_flags |= LMD_FLG_NO_PRIMNODE;
+ set_bit(LMD_FLG_NO_PRIMNODE, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "mgssec=", 7) == 0) {
rc = lmd_parse_mgssec(lmd, s1 + 7);
clear++;
} else if (strncmp(s1, "mgs", 3) == 0) {
/* We are an MGS */
- lmd->lmd_flags |= LMD_FLG_MGS;
+ set_bit(LMD_FLG_MGS, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "svname=", 7) == 0) {
rc = lmd_parse_string(&lmd->lmd_profile, s1 + 7);
s3 = s1 + 6 + length;
clear++;
} else if (strncmp(s1, "localrecov", 10) == 0) {
- lmd->lmd_flags |= LMD_FLG_LOCAL_RECOV;
+ set_bit(LMD_FLG_LOCAL_RECOV, lmd->lmd_flags);
clear++;
} else if (strncmp(s1, "osd=", 4) == 0) {
rc = lmd_parse_string(&lmd->lmd_osd_type, s1 + 4);
s1 = strstr(devname, ":/");
if (s1) {
++s1;
- lmd->lmd_flags |= LMD_FLG_CLIENT;
+ set_bit(LMD_FLG_CLIENT, lmd->lmd_flags);
/* Remove leading /s from fsname */
while (*++s1 == '/')
;
}
lmd_print(lmd);
- lmd->lmd_magic = LMD_MAGIC;
RETURN(rc);
CERROR("Bad mount options %s\n", options);
RETURN(-EINVAL);
}
-
-/**
- * This is the entry point for the mount call into Lustre.
- * This is called when a server or client is mounted,
- * and this is where we start setting things up.
- * @param data Mount options (e.g. -o flock,abort_recov)
- */
-static int lustre_fill_super(struct super_block *sb, void *lmd2_data,
- int silent)
-{
- struct lustre_mount_data *lmd;
- struct lustre_sb_info *lsi;
- int rc;
-
- ENTRY;
-
- CDEBUG(D_MOUNT|D_VFSTRACE, "VFS Op: sb %p\n", sb);
-
- lsi = lustre_init_lsi(sb);
- if (!lsi)
- RETURN(-ENOMEM);
- lmd = lsi->lsi_lmd;
-
- /*
- * Disable lockdep during mount, because mount locking patterns are
- * 'special'.
- */
- lockdep_off();
-
- /*
- * LU-639: the OBD cleanup of last mount may not finish yet, wait here.
- */
- obd_zombie_barrier();
-
- /* Figure out the lmd from the mount options */
- if (lmd_parse(lmd2_data, lmd)) {
- lustre_put_lsi(sb);
- GOTO(out, rc = -EINVAL);
- }
-
- if (lmd_is_client(lmd)) {
- bool have_client = false;
-
- CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
- if (!client_fill_super)
- request_module("lustre");
- spin_lock(&client_lock);
- if (client_fill_super && try_module_get(client_mod))
- have_client = true;
- spin_unlock(&client_lock);
- if (!have_client) {
- LCONSOLE_ERROR_MSG(0x165,
- "Nothing registered for client mount! Is the 'lustre' module loaded?\n");
- lustre_put_lsi(sb);
- rc = -ENODEV;
- } else {
- rc = lustre_start_mgc(sb);
- if (rc) {
- lustre_common_put_super(sb);
- GOTO(out, rc);
- }
- /* Connect and start */
- /* (should always be ll_fill_super) */
- rc = (*client_fill_super)(sb);
- /* c_f_s will call lustre_common_put_super on failure,
- * which takes care of the module reference.
- */
- }
- } else {
-#ifdef HAVE_SERVER_SUPPORT
- CDEBUG(D_MOUNT, "Mounting server from %s\n", lmd->lmd_dev);
- rc = server_fill_super(sb);
- /*
- * s_f_s calls lustre_start_mgc after the mount because we need
- * the MGS NIDs which are stored on disk. Plus, we may
- * need to start the MGS first.
- */
- /* s_f_s will call server_put_super on failure */
-#else
- CERROR("client-side-only module, cannot handle server mount\n");
- rc = -EINVAL;
-#endif
- }
-
- /*
- * If error happens in fill_super() call, @lsi will be killed there.
- * This is why we do not put it here.
- */
- GOTO(out, rc);
-out:
- if (rc) {
- CERROR("Unable to mount %s (%d)\n",
- s2lsi(sb) ? lmd->lmd_dev : "", rc);
- } else {
- CDEBUG(D_SUPER, "Mount %s complete\n",
- lmd->lmd_dev);
- }
- lockdep_on();
- return rc;
-}
-
-
-/*
- * We can't call ll_fill_super by name because it lives in a module that
- * must be loaded after this one.
- */
-void lustre_register_super_ops(struct module *mod,
- int (*cfs)(struct super_block *sb),
- void (*ksc)(struct super_block *sb))
-{
- spin_lock(&client_lock);
- client_mod = mod;
- client_fill_super = cfs;
- kill_super_cb = ksc;
- spin_unlock(&client_lock);
-}
-EXPORT_SYMBOL(lustre_register_super_ops);
-
-/***************** FS registration ******************/
-static struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,
- const char *devname, void *data)
-{
- return mount_nodev(fs_type, flags, data, lustre_fill_super);
-}
-
-static void lustre_kill_super(struct super_block *sb)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
-
- if (kill_super_cb && lsi && !IS_SERVER(lsi))
- (*kill_super_cb)(sb);
-
- kill_anon_super(sb);
-}
-
-#ifdef HAVE_SERVER_SUPPORT
-/* Register the "lustre_tgt" fs type.
- *
- * Right now this isn't any different than the normal "lustre" filesystem
- * type, but it is added so that there is some compatibility to allow
- * changing documentation and scripts to start using the "lustre_tgt" type
- * at mount time. That will simplify test interop, and in case of upgrades
- * that change to the new type and then need to roll back for some reason.
- *
- * The long-term goal is to disentangle the client and server mount code.
- */
-static struct file_system_type lustre_fs_type_tgt = {
- .owner = THIS_MODULE,
- .name = "lustre_tgt",
- .mount = lustre_mount,
- .kill_sb = lustre_kill_super,
- .fs_flags = FS_REQUIRES_DEV | FS_RENAME_DOES_D_MOVE,
-};
-MODULE_ALIAS_FS("lustre_tgt");
-
-#define register_filesystem_tgt(fstype) \
-do { \
- int _rc; \
- \
- _rc = register_filesystem(fstype); \
- if (_rc && _rc != -EBUSY) { \
- /* Don't fail if server code also registers "lustre_tgt" */ \
- CERROR("obdclass: register fstype '%s' failed: rc = %d\n", \
- (fstype)->name, _rc); \
- return _rc; \
- } \
-} while (0)
-#define unregister_filesystem_tgt(fstype) unregister_filesystem(fstype)
-#else
-#define register_filesystem_tgt(fstype) do {} while (0)
-#define unregister_filesystem_tgt(fstype) do {} while (0)
-#endif
-
-/* Register the "lustre" fs type */
-static struct file_system_type lustre_fs_type = {
- .owner = THIS_MODULE,
- .name = "lustre",
- .mount = lustre_mount,
- .kill_sb = lustre_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE,
-};
-MODULE_ALIAS_FS("lustre");
-
-int lustre_register_fs(void)
-{
- register_filesystem_tgt(&lustre_fs_type_tgt);
-
- return register_filesystem(&lustre_fs_type);
-}
-
-int lustre_unregister_fs(void)
-{
- unregister_filesystem_tgt(&lustre_fs_type_tgt);
-
- return unregister_filesystem(&lustre_fs_type);
-}
+EXPORT_SYMBOL(lmd_parse);