Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86d71014 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (87 commits)
  NFSv4: Disallow 'mount -t nfs4 -overs=2' and 'mount -t nfs4 -overs=3'
  NFS: Allow the "nfs" file system type to support NFSv4
  NFS: Move details of nfs4_get_sb() to a helper
  NFS: Refactor NFSv4 text-based mount option validation
  NFS: Mount option parser should detect missing "port="
  NFS: out of date comment regarding O_EXCL above nfs3_proc_create()
  NFS: Handle a zero-length auth flavor list
  SUNRPC: Ensure that sunrpc gets initialised before nfs, lockd, etc...
  nfs: fix compile error in rpc_pipefs.h
  nfs: Remove reference to generic_osync_inode from a comment
  SUNRPC: cache must take a reference to the cache detail's module on open()
  NFS: Use the DNS resolver in the mount code.
  NFS: Add a dns resolver for use with NFSv4 referrals and migration
  SUNRPC: Fix a typo in cache_pipefs_files
  nfs: nfs4xdr: optimize low level decoding
  nfs: nfs4xdr: get rid of READ_BUF
  nfs: nfs4xdr: simplify decode_exchange_id by reusing decode_opaque_inline
  nfs: nfs4xdr: get rid of COPYMEM
  nfs: nfs4xdr: introduce decode_sessionid helper
  nfs: nfs4xdr: introduce decode_verifier helper
  ...
parents 86373435 ab3bbaa8
Loading
Loading
Loading
Loading
+98 −0
Original line number Diff line number Diff line

The NFS client
==============

The NFS version 2 protocol was first documented in RFC1094 (March 1989).
Since then two more major releases of NFS have been published, with NFSv3
being documented in RFC1813 (June 1995), and NFSv4 in RFC3530 (April
2003).

The Linux NFS client currently supports all the above published versions,
and work is in progress on adding support for minor version 1 of the NFSv4
protocol.

The purpose of this document is to provide information on some of the
upcall interfaces that are used in order to provide the NFS client with
some of the information that it requires in order to fully comply with
the NFS spec.

The DNS resolver
================

NFSv4 allows for one server to refer the NFS client to data that has been
migrated onto another server by means of the special "fs_locations"
attribute. See
	http://tools.ietf.org/html/rfc3530#section-6
and
	http://tools.ietf.org/html/draft-ietf-nfsv4-referrals-00

The fs_locations information can take the form of either an ip address and
a path, or a DNS hostname and a path. The latter requires the NFS client to
do a DNS lookup in order to mount the new volume, and hence the need for an
upcall to allow userland to provide this service.

Assuming that the user has the 'rpc_pipefs' filesystem mounted in the usual
/var/lib/nfs/rpc_pipefs, the upcall consists of the following steps:

   (1) The process checks the dns_resolve cache to see if it contains a
       valid entry. If so, it returns that entry and exits.

   (2) If no valid entry exists, the helper script '/sbin/nfs_cache_getent'
       (may be changed using the 'nfs.cache_getent' kernel boot parameter)
       is run, with two arguments:
		- the cache name, "dns_resolve"
		- the hostname to resolve

   (3) After looking up the corresponding ip address, the helper script
       writes the result into the rpc_pipefs pseudo-file
       '/var/lib/nfs/rpc_pipefs/cache/dns_resolve/channel'
       in the following (text) format:

		"<ip address> <hostname> <ttl>\n"

       Where <ip address> is in the usual IPv4 (123.456.78.90) or IPv6
       (ffee:ddcc:bbaa:9988:7766:5544:3322:1100, ffee::1100, ...) format.
       <hostname> is identical to the second argument of the helper
       script, and <ttl> is the 'time to live' of this cache entry (in
       units of seconds).

       Note: If <ip address> is invalid, say the string "0", then a negative
       entry is created, which will cause the kernel to treat the hostname
       as having no valid DNS translation.




A basic sample /sbin/nfs_cache_getent
=====================================

#!/bin/bash
#
ttl=600
#
cut=/usr/bin/cut
getent=/usr/bin/getent
rpc_pipefs=/var/lib/nfs/rpc_pipefs
#
die()
{
	echo "Usage: $0 cache_name entry_name"
	exit 1
}

[ $# -lt 2 ] && die
cachename="$1"
cache_path=${rpc_pipefs}/cache/${cachename}/channel

case "${cachename}" in
	dns_resolve)
		name="$2"
		result="$(${getent} hosts ${name} | ${cut} -f1 -d\ )"
		[ -z "${result}" ] && result="0"
		;;
	*)
		die
		;;
esac
echo "${result} ${name} ${ttl}" >${cache_path}
+29 −0
Original line number Diff line number Diff line
@@ -1503,6 +1503,14 @@ and is between 256 and 4096 characters. It is defined in the file
			[NFS] set the TCP port on which the NFSv4 callback
			channel should listen.

	nfs.cache_getent=
			[NFS] sets the pathname to the program which is used
			to update the NFS client cache entries.

	nfs.cache_getent_timeout=
			[NFS] sets the timeout after which an attempt to
			update a cache entry is deemed to have failed.

	nfs.idmap_cache_timeout=
			[NFS] set the maximum lifetime for idmapper cache
			entries.
@@ -2395,6 +2403,18 @@ and is between 256 and 4096 characters. It is defined in the file
	stifb=		[HW]
			Format: bpp:<bpp1>[:<bpp2>[:<bpp3>...]]

	sunrpc.min_resvport=
	sunrpc.max_resvport=
			[NFS,SUNRPC]
			SunRPC servers often require that client requests
			originate from a privileged port (i.e. a port in the
			range 0 < portnr < 1024).
			An administrator who wishes to reserve some of these
			ports for other uses may adjust the range that the
			kernel's sunrpc client considers to be privileged
			using these two parameters to set the minimum and
			maximum port values.

	sunrpc.pool_mode=
			[NFS]
			Control how the NFS server code allocates CPUs to
@@ -2411,6 +2431,15 @@ and is between 256 and 4096 characters. It is defined in the file
			pernode	    one pool for each NUMA node (equivalent
				    to global on non-NUMA machines)

	sunrpc.tcp_slot_table_entries=
	sunrpc.udp_slot_table_entries=
			[NFS,SUNRPC]
			Sets the upper limit on the number of simultaneous
			RPC calls that can be sent from the client to a
			server. Increasing these values may allow you to
			improve throughput, but will also increase the
			amount of memory reserved for use by the client.

	swiotlb=	[IA-64] Number of I/O TLB slabs

	switches=	[HW,M68k]
+1 −13
Original line number Diff line number Diff line
@@ -87,18 +87,6 @@ static unsigned int nlm_hash_address(const struct sockaddr *sap)
	return hash & (NLM_HOST_NRHASH - 1);
}

static void nlm_clear_port(struct sockaddr *sap)
{
	switch (sap->sa_family) {
	case AF_INET:
		((struct sockaddr_in *)sap)->sin_port = 0;
		break;
	case AF_INET6:
		((struct sockaddr_in6 *)sap)->sin6_port = 0;
		break;
	}
}

/*
 * Common host lookup routine for server & client
 */
@@ -177,7 +165,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
	host->h_addrbuf    = nsm->sm_addrbuf;
	memcpy(nlm_addr(host), ni->sap, ni->salen);
	host->h_addrlen = ni->salen;
	nlm_clear_port(nlm_addr(host));
	rpc_set_port(nlm_addr(host), 0);
	memcpy(nlm_srcaddr(host), ni->src_sap, ni->src_len);
	host->h_version    = ni->version;
	host->h_proto      = ni->protocol;
+5 −39
Original line number Diff line number Diff line
@@ -61,43 +61,6 @@ static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
	return (struct sockaddr *)&nsm->sm_addr;
}

static void nsm_display_ipv4_address(const struct sockaddr *sap, char *buf,
				     const size_t len)
{
	const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
	snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr);
}

static void nsm_display_ipv6_address(const struct sockaddr *sap, char *buf,
				     const size_t len)
{
	const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;

	if (ipv6_addr_v4mapped(&sin6->sin6_addr))
		snprintf(buf, len, "%pI4", &sin6->sin6_addr.s6_addr32[3]);
	else if (sin6->sin6_scope_id != 0)
		snprintf(buf, len, "%pI6%%%u", &sin6->sin6_addr,
				sin6->sin6_scope_id);
	else
		snprintf(buf, len, "%pI6", &sin6->sin6_addr);
}

static void nsm_display_address(const struct sockaddr *sap,
				char *buf, const size_t len)
{
	switch (sap->sa_family) {
	case AF_INET:
		nsm_display_ipv4_address(sap, buf, len);
		break;
	case AF_INET6:
		nsm_display_ipv6_address(sap, buf, len);
		break;
	default:
		snprintf(buf, len, "unsupported address family");
		break;
	}
}

static struct rpc_clnt *nsm_create(void)
{
	struct sockaddr_in sin = {
@@ -307,8 +270,11 @@ static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
	memcpy(nsm_addr(new), sap, salen);
	new->sm_addrlen = salen;
	nsm_init_private(new);
	nsm_display_address((const struct sockaddr *)&new->sm_addr,
				new->sm_addrbuf, sizeof(new->sm_addrbuf));

	if (rpc_ntop(nsm_addr(new), new->sm_addrbuf,
					sizeof(new->sm_addrbuf)) == 0)
		(void)snprintf(new->sm_addrbuf, sizeof(new->sm_addrbuf),
				"unsupported address family");
	memcpy(new->sm_name, hostname, hostname_len);
	new->sm_name[hostname_len] = '\0';

+2 −1
Original line number Diff line number Diff line
@@ -6,7 +6,8 @@ obj-$(CONFIG_NFS_FS) += nfs.o

nfs-y 			:= client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
			   direct.o pagelist.o proc.o read.o symlink.o unlink.o \
			   write.o namespace.o mount_clnt.o
			   write.o namespace.o mount_clnt.o \
			   dns_resolve.o cache_lib.o
nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.o
nfs-$(CONFIG_NFS_V3)	+= nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL)	+= nfs3acl.o
Loading