All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ceph: use kernel DNS resolver
@ 2011-09-22 18:54 Noah Watkins
  2011-09-22 21:29 ` Sage Weil
  0 siblings, 1 reply; 5+ messages in thread
From: Noah Watkins @ 2011-09-22 18:54 UTC (permalink / raw)
  To: Sage Weil; +Cc: ceph-devel, LKML

Change ceph_parse_ips to take either names given as
IP addresses or standard hostnames (e.g. localhost).
The DNS lookup is done using the dns_resolver facility
similar to its use in AFS, NFS, and CIFS.

Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
---
 net/ceph/Kconfig     |    1 +
 net/ceph/messenger.c |  106 ++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 95 insertions(+), 12 deletions(-)

diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig
index be683f2..aac5fc8 100644
--- a/net/ceph/Kconfig
+++ b/net/ceph/Kconfig
@@ -5,6 +5,7 @@ config CEPH_LIB
 	select CRYPTO_AES
 	select CRYPTO
 	select KEYS
+	select DNS_RESOLVER
 	default n
 	help
 	  Choose Y or M here to include cephlib, which provides the
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index c340e2e..c22aa58 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -11,6 +11,7 @@
 #include <linux/string.h>
 #include <linux/bio.h>
 #include <linux/blkdev.h>
+#include <linux/dns_resolver.h>
 #include <net/tcp.h>

 #include <linux/ceph/libceph.h>
@@ -1078,6 +1079,93 @@ static void addr_set_port(struct
sockaddr_storage *ss, int p)
 }

 /*
+ * Unlike other *_pton function semantics, zero indicates success.
+ */
+static int ceph_pton(const char *str, size_t len, struct sockaddr_storage *ss,
+		char delim, const char **ipend)
+{
+	struct sockaddr_in *in4 = (void *)ss;
+	struct sockaddr_in6 *in6 = (void *)ss;
+
+	memset(ss, 0, sizeof(*ss));
+
+	if (in4_pton(str, len, (u8 *)&in4->sin_addr.s_addr, delim, ipend)) {
+		ss->ss_family = AF_INET;
+		return 0;
+	}
+
+	if (in6_pton(str, len, (u8 *)&in6->sin6_addr.s6_addr, delim, ipend)) {
+		ss->ss_family = AF_INET6;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * Extract hostname string and resolve using kernel DNS facility.
+ */
+static int ceph_dns_resolve_name(const char *name, size_t namelen,
+			struct sockaddr_storage *ss, char delim, const char **ipend)
+{
+	const char *end, *delim_p;
+	char *colon_p, *ip_addr = NULL;
+	int ip_len, ret;
+
+	/*
+	 * The end of the hostname occurs immediately preceding the delimiter or
+	 * the port marker (':') where the delimiter takes precedence.
+	 */
+	delim_p = memchr(name, delim, namelen);
+	colon_p = memchr(name, ':', namelen);
+
+	if (delim_p && colon_p)
+		end = delim_p < colon_p ? delim_p : colon_p;
+	else if (!delim_p && colon_p)
+		end = colon_p;
+	else {
+		end = delim_p;
+		if (!end) /* case: hostname:/ */
+			end = name + namelen;
+	}
+
+	if (end <= name)
+		return -EINVAL;
+
+	/* do dns_resolve upcall */
+	ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL);
+	if (ip_len > 0)
+		ret = ceph_pton(ip_addr, ip_len, ss, -1, NULL);
+	else
+		ret = -ESRCH;
+
+	kfree(ip_addr);
+
+	*ipend = end;
+
+	pr_info("resolve '%.*s' (ret=%d): %s\n", (int)(end - name), name,
+			ret, ret ? "failed" : ceph_pr_addr(ss));
+
+	return ret;
+}
+
+/*
+ * Parse a server name (IP or hostname). If a valid IP address is not found
+ * then try to extract a hostname to resolve using userspace DNS upcall.
+ */
+static int ceph_parse_server_name(const char *name, size_t namelen,
+			struct sockaddr_storage *ss, char delim, const char **ipend)
+{
+	int ret;
+
+	ret = ceph_pton(name, namelen, ss, delim, ipend);
+	if (ret)
+		ret = ceph_dns_resolve_name(name, namelen, ss, delim, ipend);
+
+	return ret;
+}
+
+/*
  * Parse an ip[:port] list into an addr array.  Use the default
  * monitor port if a port isn't specified.
  */
@@ -1085,15 +1173,13 @@ int ceph_parse_ips(const char *c, const char *end,
 		   struct ceph_entity_addr *addr,
 		   int max_count, int *count)
 {
-	int i;
+	int i, ret = -EINVAL;
 	const char *p = c;

 	dout("parse_ips on '%.*s'\n", (int)(end-c), c);
 	for (i = 0; i < max_count; i++) {
 		const char *ipend;
 		struct sockaddr_storage *ss = &addr[i].in_addr;
-		struct sockaddr_in *in4 = (void *)ss;
-		struct sockaddr_in6 *in6 = (void *)ss;
 		int port;
 		char delim = ',';

@@ -1102,15 +1188,11 @@ int ceph_parse_ips(const char *c, const char *end,
 			p++;
 		}

-		memset(ss, 0, sizeof(*ss));
-		if (in4_pton(p, end - p, (u8 *)&in4->sin_addr.s_addr,
-			     delim, &ipend))
-			ss->ss_family = AF_INET;
-		else if (in6_pton(p, end - p, (u8 *)&in6->sin6_addr.s6_addr,
-				  delim, &ipend))
-			ss->ss_family = AF_INET6;
-		else
+		ret = ceph_parse_server_name(p, end - p, ss, delim, &ipend);
+		if (ret)
 			goto bad;
+		ret = -EINVAL;
+
 		p = ipend;

 		if (delim == ']') {
@@ -1155,7 +1237,7 @@ int ceph_parse_ips(const char *c, const char *end,

 bad:
 	pr_err("parse_ips bad ip '%.*s'\n", (int)(end - c), c);
-	return -EINVAL;
+	return ret;
 }
 EXPORT_SYMBOL(ceph_parse_ips);

-- 
1.7.6.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] ceph: use kernel DNS resolver
  2011-09-22 18:54 [PATCH] ceph: use kernel DNS resolver Noah Watkins
@ 2011-09-22 21:29 ` Sage Weil
  2011-09-23 18:51   ` Noah Watkins
  0 siblings, 1 reply; 5+ messages in thread
From: Sage Weil @ 2011-09-22 21:29 UTC (permalink / raw)
  To: Noah Watkins; +Cc: ceph-devel, LKML

Hey Noah,

On Thu, 22 Sep 2011, Noah Watkins wrote:
> Change ceph_parse_ips to take either names given as
> IP addresses or standard hostnames (e.g. localhost).
> The DNS lookup is done using the dns_resolver facility
> similar to its use in AFS, NFS, and CIFS.

Currently the dns resolution is handled by mount.ceph and 'rbd map/unmap'.  
I don't think that will go away (at the very least need to support old 
kernels).  

Allowing this in the raw kernel interface would be nice, but I don't think 
we want make DNS_RESOLVER a strict dependency, since it's new, kind of 
kludgey, and a ripe target for compiling out of small or secure kernels.  
Can you make it build either with or without it?

Thanks!
sage


> 
> Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
> ---
>  net/ceph/Kconfig     |    1 +
>  net/ceph/messenger.c |  106 ++++++++++++++++++++++++++++++++++++++++++++------
>  2 files changed, 95 insertions(+), 12 deletions(-)
> 
> diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig
> index be683f2..aac5fc8 100644
> --- a/net/ceph/Kconfig
> +++ b/net/ceph/Kconfig
> @@ -5,6 +5,7 @@ config CEPH_LIB
>  	select CRYPTO_AES
>  	select CRYPTO
>  	select KEYS
> +	select DNS_RESOLVER
>  	default n
>  	help
>  	  Choose Y or M here to include cephlib, which provides the
> diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
> index c340e2e..c22aa58 100644
> --- a/net/ceph/messenger.c
> +++ b/net/ceph/messenger.c
> @@ -11,6 +11,7 @@
>  #include <linux/string.h>
>  #include <linux/bio.h>
>  #include <linux/blkdev.h>
> +#include <linux/dns_resolver.h>
>  #include <net/tcp.h>
> 
>  #include <linux/ceph/libceph.h>
> @@ -1078,6 +1079,93 @@ static void addr_set_port(struct
> sockaddr_storage *ss, int p)
>  }
> 
>  /*
> + * Unlike other *_pton function semantics, zero indicates success.
> + */
> +static int ceph_pton(const char *str, size_t len, struct sockaddr_storage *ss,
> +		char delim, const char **ipend)
> +{
> +	struct sockaddr_in *in4 = (void *)ss;
> +	struct sockaddr_in6 *in6 = (void *)ss;
> +
> +	memset(ss, 0, sizeof(*ss));
> +
> +	if (in4_pton(str, len, (u8 *)&in4->sin_addr.s_addr, delim, ipend)) {
> +		ss->ss_family = AF_INET;
> +		return 0;
> +	}
> +
> +	if (in6_pton(str, len, (u8 *)&in6->sin6_addr.s6_addr, delim, ipend)) {
> +		ss->ss_family = AF_INET6;
> +		return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +/*
> + * Extract hostname string and resolve using kernel DNS facility.
> + */
> +static int ceph_dns_resolve_name(const char *name, size_t namelen,
> +			struct sockaddr_storage *ss, char delim, const char **ipend)
> +{
> +	const char *end, *delim_p;
> +	char *colon_p, *ip_addr = NULL;
> +	int ip_len, ret;
> +
> +	/*
> +	 * The end of the hostname occurs immediately preceding the delimiter or
> +	 * the port marker (':') where the delimiter takes precedence.
> +	 */
> +	delim_p = memchr(name, delim, namelen);
> +	colon_p = memchr(name, ':', namelen);
> +
> +	if (delim_p && colon_p)
> +		end = delim_p < colon_p ? delim_p : colon_p;
> +	else if (!delim_p && colon_p)
> +		end = colon_p;
> +	else {
> +		end = delim_p;
> +		if (!end) /* case: hostname:/ */
> +			end = name + namelen;
> +	}
> +
> +	if (end <= name)
> +		return -EINVAL;
> +
> +	/* do dns_resolve upcall */
> +	ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL);
> +	if (ip_len > 0)
> +		ret = ceph_pton(ip_addr, ip_len, ss, -1, NULL);
> +	else
> +		ret = -ESRCH;
> +
> +	kfree(ip_addr);
> +
> +	*ipend = end;
> +
> +	pr_info("resolve '%.*s' (ret=%d): %s\n", (int)(end - name), name,
> +			ret, ret ? "failed" : ceph_pr_addr(ss));
> +
> +	return ret;
> +}
> +
> +/*
> + * Parse a server name (IP or hostname). If a valid IP address is not found
> + * then try to extract a hostname to resolve using userspace DNS upcall.
> + */
> +static int ceph_parse_server_name(const char *name, size_t namelen,
> +			struct sockaddr_storage *ss, char delim, const char **ipend)
> +{
> +	int ret;
> +
> +	ret = ceph_pton(name, namelen, ss, delim, ipend);
> +	if (ret)
> +		ret = ceph_dns_resolve_name(name, namelen, ss, delim, ipend);
> +
> +	return ret;
> +}
> +
> +/*
>   * Parse an ip[:port] list into an addr array.  Use the default
>   * monitor port if a port isn't specified.
>   */
> @@ -1085,15 +1173,13 @@ int ceph_parse_ips(const char *c, const char *end,
>  		   struct ceph_entity_addr *addr,
>  		   int max_count, int *count)
>  {
> -	int i;
> +	int i, ret = -EINVAL;
>  	const char *p = c;
> 
>  	dout("parse_ips on '%.*s'\n", (int)(end-c), c);
>  	for (i = 0; i < max_count; i++) {
>  		const char *ipend;
>  		struct sockaddr_storage *ss = &addr[i].in_addr;
> -		struct sockaddr_in *in4 = (void *)ss;
> -		struct sockaddr_in6 *in6 = (void *)ss;
>  		int port;
>  		char delim = ',';
> 
> @@ -1102,15 +1188,11 @@ int ceph_parse_ips(const char *c, const char *end,
>  			p++;
>  		}
> 
> -		memset(ss, 0, sizeof(*ss));
> -		if (in4_pton(p, end - p, (u8 *)&in4->sin_addr.s_addr,
> -			     delim, &ipend))
> -			ss->ss_family = AF_INET;
> -		else if (in6_pton(p, end - p, (u8 *)&in6->sin6_addr.s6_addr,
> -				  delim, &ipend))
> -			ss->ss_family = AF_INET6;
> -		else
> +		ret = ceph_parse_server_name(p, end - p, ss, delim, &ipend);
> +		if (ret)
>  			goto bad;
> +		ret = -EINVAL;
> +
>  		p = ipend;
> 
>  		if (delim == ']') {
> @@ -1155,7 +1237,7 @@ int ceph_parse_ips(const char *c, const char *end,
> 
>  bad:
>  	pr_err("parse_ips bad ip '%.*s'\n", (int)(end - c), c);
> -	return -EINVAL;
> +	return ret;
>  }
>  EXPORT_SYMBOL(ceph_parse_ips);
> 
> -- 
> 1.7.6.1
> --
> To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] ceph: use kernel DNS resolver
  2011-09-22 21:29 ` Sage Weil
@ 2011-09-23 18:51   ` Noah Watkins
  2011-09-23 19:15     ` Sage Weil
  0 siblings, 1 reply; 5+ messages in thread
From: Noah Watkins @ 2011-09-23 18:51 UTC (permalink / raw)
  To: Sage Weil; +Cc: ceph-devel, LKML

On Thu, Sep 22, 2011 at 14:29, Sage Weil <sage@newdream.net> wrote:
> Currently the dns resolution is handled by mount.ceph and 'rbd map/unmap'.
> I don't think that will go away (at the very least need to support old
> kernels).

This is good to know. I never encountered the DNS lookup because I've
always used a non-standard installation path, avoiding mount.ceph.

> Allowing this in the raw kernel interface would be nice, but I don't think
> we want make DNS_RESOLVER a strict dependency, since it's new, kind of
> kludgey, and a ripe target for compiling out of small or secure kernels.
> Can you make it build either with or without it?

I sent out a new version of the patch that defines a libceph specific
configuration
option to use the in-kernel dns resolver.

Thanks for the feedback!
-Noah

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] ceph: use kernel DNS resolver
  2011-09-23 18:51   ` Noah Watkins
@ 2011-09-23 19:15     ` Sage Weil
  2011-09-23 19:34       ` Noah Watkins
  0 siblings, 1 reply; 5+ messages in thread
From: Sage Weil @ 2011-09-23 19:15 UTC (permalink / raw)
  To: Noah Watkins; +Cc: ceph-devel, LKML

On Fri, 23 Sep 2011, Noah Watkins wrote:
> On Thu, Sep 22, 2011 at 14:29, Sage Weil <sage@newdream.net> wrote:
> > Currently the dns resolution is handled by mount.ceph and 'rbd map/unmap'.
> > I don't think that will go away (at the very least need to support old
> > kernels).
> 
> This is good to know. I never encountered the DNS lookup because I've
> always used a non-standard installation path, avoiding mount.ceph.
> 
> > Allowing this in the raw kernel interface would be nice, but I don't think
> > we want make DNS_RESOLVER a strict dependency, since it's new, kind of
> > kludgey, and a ripe target for compiling out of small or secure kernels.
> > Can you make it build either with or without it?
> 
> I sent out a new version of the patch that defines a libceph specific 
> configuration option to use the in-kernel dns resolver.

So I was actually thinking we could just #ifdef off of 
CONFIG_DNS_RESOLVER, but I think your approach might be better because 
you'll see it in the config process and turn it on, vs having to dig 
through to wherever DNS_RESOLVER lives in kconfig.

Maybe it should default y though?

sage

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] ceph: use kernel DNS resolver
  2011-09-23 19:15     ` Sage Weil
@ 2011-09-23 19:34       ` Noah Watkins
  0 siblings, 0 replies; 5+ messages in thread
From: Noah Watkins @ 2011-09-23 19:34 UTC (permalink / raw)
  To: Sage Weil; +Cc: Noah Watkins, ceph-devel, LKML

On 09/23/2011 12:15 PM, Sage Weil wrote:

> So I was actually thinking we could just #ifdef off of 
> CONFIG_DNS_RESOLVER, but I think your approach might be better because 
> you'll see it in the config process and turn it on, vs having to dig 
> through to wherever DNS_RESOLVER lives in kconfig.


Yeh, that was my thinking too. Also, if we just use DNS_RESOLVER then a
Ceph user would have no way of turning off the feature if another
required feature had a dependency on DNS_RESOLVER.

> Maybe it should default y though?


It definitely doesn't hurt anything. I'll send v3 with default y.

-Noah

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-09-23 19:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-22 18:54 [PATCH] ceph: use kernel DNS resolver Noah Watkins
2011-09-22 21:29 ` Sage Weil
2011-09-23 18:51   ` Noah Watkins
2011-09-23 19:15     ` Sage Weil
2011-09-23 19:34       ` Noah Watkins

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.