scoutfs: add server_addr mount option

Add a server_addr mount option that takes an ipv4 address.  This will be
used by the upcoming changes to quorum voting to indicate that a mount
should participate in voting and to specify the address that its server
should listen on.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2019-08-20 15:52:13 -07:00
committed by Zach Brown
parent 532256271c
commit 5929a36747
3 changed files with 66 additions and 0 deletions
+50
View File
@@ -27,6 +27,7 @@
#include "super.h"
static const match_table_t tokens = {
{Opt_server_addr, "server_addr=%s"},
{Opt_uniq_name, "uniq_name=%s"},
{Opt_err, NULL}
};
@@ -50,12 +51,54 @@ u32 scoutfs_option_u32(struct super_block *sb, int token)
return 0;
}
/* The caller's string is null terminted and can be clobbered */
static int parse_ipv4(struct super_block *sb, char *str,
struct sockaddr_in *sin)
{
unsigned long port = 0;
__be32 addr;
char *c;
int ret;
/* null term port, if specified */
c = strchr(str, ':');
if (c)
*c = '\0';
/* parse addr */
addr = in_aton(str);
if (ipv4_is_multicast(addr) || ipv4_is_lbcast(addr) ||
ipv4_is_zeronet(addr) ||
ipv4_is_local_multicast(addr)) {
scoutfs_err(sb, "invalid unicast ipv4 address: %s", str);
return -EINVAL;
}
/* parse port, if specified */
if (c) {
c++;
ret = kstrtoul(c, 0, &port);
if (ret != 0 || port == 0 || port >= U16_MAX) {
scoutfs_err(sb, "invalid port in ipv4 address: %s", c);
return -EINVAL;
}
}
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = addr;
sin->sin_port = cpu_to_be16(port);
return 0;
}
int scoutfs_parse_options(struct super_block *sb, char *options,
struct mount_options *parsed)
{
char ipstr[INET_ADDRSTRLEN + 1];
substring_t args[MAX_OPT_ARGS];
int token, len;
char *p;
int ret;
/* Set defaults */
memset(parsed, 0, sizeof(*parsed));
@@ -66,6 +109,13 @@ int scoutfs_parse_options(struct super_block *sb, char *options,
token = match_token(p, tokens, args);
switch (token) {
case Opt_server_addr:
match_strlcpy(ipstr, args, ARRAY_SIZE(ipstr));
ret = parse_ipv4(sb, ipstr, &parsed->server_addr);
if (ret < 0)
return ret;
break;
case Opt_uniq_name:
len = match_strlcpy(parsed->uniq_name, args,
SCOUTFS_UNIQUE_NAME_MAX_BYTES);
+3
View File
@@ -2,6 +2,7 @@
#define _SCOUTFS_OPTIONS_H_
#include <linux/fs.h>
#include <linux/in.h>
#include "format.h"
enum {
@@ -10,11 +11,13 @@ enum {
* the number of items in each block as though the blocks were tiny.
*/
Opt_btree_force_tiny_blocks,
Opt_server_addr,
Opt_uniq_name,
Opt_err,
};
struct mount_options {
struct sockaddr_in server_addr;
char uniq_name[SCOUTFS_UNIQUE_NAME_MAX_BYTES];
};
+13
View File
@@ -138,11 +138,23 @@ static int scoutfs_show_options(struct seq_file *seq, struct dentry *root)
struct super_block *sb = root->d_sb;
struct mount_options *opts = &SCOUTFS_SB(sb)->opts;
seq_printf(seq, ",server_addr="SIN_FMT, SIN_ARG(&opts->server_addr));
seq_printf(seq, ",uniq_name=%s", opts->uniq_name);
return 0;
}
static ssize_t server_addr_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct super_block *sb = SCOUTFS_SYSFS_ATTRS_SB(kobj);
struct mount_options *opts = &SCOUTFS_SB(sb)->opts;
return snprintf(buf, PAGE_SIZE, SIN_FMT"\n",
SIN_ARG(&opts->server_addr));
}
SCOUTFS_ATTR_RO(server_addr);
static ssize_t uniq_name_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
@@ -154,6 +166,7 @@ static ssize_t uniq_name_show(struct kobject *kobj,
SCOUTFS_ATTR_RO(uniq_name);
static struct attribute *mount_options_attrs[] = {
SCOUTFS_ATTR_PTR(server_addr),
SCOUTFS_ATTR_PTR(uniq_name),
NULL,
};