Commit 17919837 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'nfs-for-2.6.39' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6

* 'nfs-for-2.6.39' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (54 commits)
  RPC: killing RPC tasks races fixed
  xprt: remove redundant check
  SUNRPC: Convert struct rpc_xprt to use atomic_t counters
  SUNRPC: Ensure we always run the tk_callback before tk_action
  sunrpc: fix printk format warning
  xprt: remove redundant null check
  nfs: BKL is no longer needed, so remove the include
  NFS: Fix a warning in fs/nfs/idmap.c
  Cleanup: Factor out some cut-and-paste code.
  cleanup: save 60 lines/100 bytes by combining two mostly duplicate functions.
  NFS: account direct-io into task io accounting
  gss:krb5 only include enctype numbers in gm_upcall_enctypes
  RPCRDMA: Fix FRMR registration/invalidate handling.
  RPCRDMA: Fix to XDR page base interpretation in marshalling logic.
  NFSv4: Send unmapped uid/gids to the server when using auth_sys
  NFSv4: Propagate the error NFS4ERR_BADOWNER to nfs4_do_setattr
  NFSv4: cleanup idmapper functions to take an nfs_server argument
  NFSv4: Send unmapped uid/gids to the server if the idmapper fails
  NFSv4: If the server sends us a numeric uid/gid then accept it
  NFSv4.1: reject zero layout with zeroed stripe unit
  ...
parents 374e5525 8e26de23
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -46,3 +46,10 @@ data server cache
file driver devices refer to data servers, which are kept in a module
file driver devices refer to data servers, which are kept in a module
level cache.  Its reference is held over the lifetime of the deviceid
level cache.  Its reference is held over the lifetime of the deviceid
pointing to it.
pointing to it.

lseg
----
lseg maintains an extra reference corresponding to the NFS_LSEG_VALID
bit which holds it in the pnfs_layout_hdr's list.  When the final lseg
is removed from the pnfs_layout_hdr's list, the NFS_LAYOUT_DESTROYED
bit is set, preventing any new lsegs from being added.
+8 −0
Original line number Original line Diff line number Diff line
@@ -1580,6 +1580,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
			of returning the full 64-bit number.
			of returning the full 64-bit number.
			The default is to return 64-bit inode numbers.
			The default is to return 64-bit inode numbers.


	nfs.nfs4_disable_idmapping=
			[NFSv4] When set, this option disables the NFSv4
			idmapper on the client, but only if the mount
			is using the 'sec=sys' security flavour. This may
			make migration from legacy NFSv2/v3 systems easier
			provided that the server has the appropriate support.
			The default is to always enable NFSv4 idmapping.

	nmi_debug=	[KNL,AVR32,SH] Specify one or more actions to take
	nmi_debug=	[KNL,AVR32,SH] Specify one or more actions to take
			when a NMI is triggered.
			when a NMI is triggered.
			Format: [state][,regs][,debounce][,die]
			Format: [state][,regs][,debounce][,die]
+1 −1
Original line number Original line Diff line number Diff line
@@ -188,10 +188,10 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
			rv = NFS4ERR_DELAY;
			rv = NFS4ERR_DELAY;
		list_del_init(&lo->plh_bulk_recall);
		list_del_init(&lo->plh_bulk_recall);
		spin_unlock(&ino->i_lock);
		spin_unlock(&ino->i_lock);
		pnfs_free_lseg_list(&free_me_list);
		put_layout_hdr(lo);
		put_layout_hdr(lo);
		iput(ino);
		iput(ino);
	}
	}
	pnfs_free_lseg_list(&free_me_list);
	return rv;
	return rv;
}
}


+105 −26
Original line number Original line Diff line number Diff line
@@ -81,6 +81,11 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
}
}
#endif /* CONFIG_NFS_V4 */
#endif /* CONFIG_NFS_V4 */


/*
 * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
 */
static int nfs4_disable_idmapping = 0;

/*
/*
 * RPC cruft for NFS
 * RPC cruft for NFS
 */
 */
@@ -481,7 +486,12 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
 * Look up a client by IP address and protocol version
 * Look up a client by IP address and protocol version
 * - creates a new record if one doesn't yet exist
 * - creates a new record if one doesn't yet exist
 */
 */
static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
static struct nfs_client *
nfs_get_client(const struct nfs_client_initdata *cl_init,
	       const struct rpc_timeout *timeparms,
	       const char *ip_addr,
	       rpc_authflavor_t authflavour,
	       int noresvport)
{
{
	struct nfs_client *clp, *new = NULL;
	struct nfs_client *clp, *new = NULL;
	int error;
	int error;
@@ -512,6 +522,13 @@ static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_in
	clp = new;
	clp = new;
	list_add(&clp->cl_share_link, &nfs_client_list);
	list_add(&clp->cl_share_link, &nfs_client_list);
	spin_unlock(&nfs_client_lock);
	spin_unlock(&nfs_client_lock);

	error = cl_init->rpc_ops->init_client(clp, timeparms, ip_addr,
					      authflavour, noresvport);
	if (error < 0) {
		nfs_put_client(clp);
		return ERR_PTR(error);
	}
	dprintk("--> nfs_get_client() = %p [new]\n", clp);
	dprintk("--> nfs_get_client() = %p [new]\n", clp);
	return clp;
	return clp;


@@ -767,9 +784,9 @@ static int nfs_init_server_rpcclient(struct nfs_server *server,
/*
/*
 * Initialise an NFS2 or NFS3 client
 * Initialise an NFS2 or NFS3 client
 */
 */
static int nfs_init_client(struct nfs_client *clp,
int nfs_init_client(struct nfs_client *clp, const struct rpc_timeout *timeparms,
			   const struct rpc_timeout *timeparms,
		    const char *ip_addr, rpc_authflavor_t authflavour,
			   const struct nfs_parsed_mount_data *data)
		    int noresvport)
{
{
	int error;
	int error;


@@ -784,7 +801,7 @@ static int nfs_init_client(struct nfs_client *clp,
	 * - RFC 2623, sec 2.3.2
	 * - RFC 2623, sec 2.3.2
	 */
	 */
	error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX,
	error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX,
				      0, data->flags & NFS_MOUNT_NORESVPORT);
				      0, noresvport);
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;
	nfs_mark_client_ready(clp, NFS_CS_READY);
	nfs_mark_client_ready(clp, NFS_CS_READY);
@@ -820,19 +837,17 @@ static int nfs_init_server(struct nfs_server *server,
		cl_init.rpc_ops = &nfs_v3_clientops;
		cl_init.rpc_ops = &nfs_v3_clientops;
#endif
#endif


	nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
			data->timeo, data->retrans);

	/* Allocate or find a client reference we can use */
	/* Allocate or find a client reference we can use */
	clp = nfs_get_client(&cl_init);
	clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX,
			     data->flags & NFS_MOUNT_NORESVPORT);
	if (IS_ERR(clp)) {
	if (IS_ERR(clp)) {
		dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
		dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
		return PTR_ERR(clp);
		return PTR_ERR(clp);
	}
	}


	nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
			data->timeo, data->retrans);
	error = nfs_init_client(clp, &timeparms, data);
	if (error < 0)
		goto error;

	server->nfs_client = clp;
	server->nfs_client = clp;


	/* Initialise the client representation from the mount data */
	/* Initialise the client representation from the mount data */
@@ -1009,14 +1024,19 @@ static void nfs_server_insert_lists(struct nfs_server *server)
	spin_lock(&nfs_client_lock);
	spin_lock(&nfs_client_lock);
	list_add_tail_rcu(&server->client_link, &clp->cl_superblocks);
	list_add_tail_rcu(&server->client_link, &clp->cl_superblocks);
	list_add_tail(&server->master_link, &nfs_volume_list);
	list_add_tail(&server->master_link, &nfs_volume_list);
	clear_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
	spin_unlock(&nfs_client_lock);
	spin_unlock(&nfs_client_lock);


}
}


static void nfs_server_remove_lists(struct nfs_server *server)
static void nfs_server_remove_lists(struct nfs_server *server)
{
{
	struct nfs_client *clp = server->nfs_client;

	spin_lock(&nfs_client_lock);
	spin_lock(&nfs_client_lock);
	list_del_rcu(&server->client_link);
	list_del_rcu(&server->client_link);
	if (clp && list_empty(&clp->cl_superblocks))
		set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
	list_del(&server->master_link);
	list_del(&server->master_link);
	spin_unlock(&nfs_client_lock);
	spin_unlock(&nfs_client_lock);


@@ -1307,11 +1327,11 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp)
/*
/*
 * Initialise an NFS4 client record
 * Initialise an NFS4 client record
 */
 */
static int nfs4_init_client(struct nfs_client *clp,
int nfs4_init_client(struct nfs_client *clp,
		     const struct rpc_timeout *timeparms,
		     const struct rpc_timeout *timeparms,
		     const char *ip_addr,
		     const char *ip_addr,
		     rpc_authflavor_t authflavour,
		     rpc_authflavor_t authflavour,
		int flags)
		     int noresvport)
{
{
	int error;
	int error;


@@ -1325,7 +1345,7 @@ static int nfs4_init_client(struct nfs_client *clp,
	clp->rpc_ops = &nfs_v4_clientops;
	clp->rpc_ops = &nfs_v4_clientops;


	error = nfs_create_rpc_client(clp, timeparms, authflavour,
	error = nfs_create_rpc_client(clp, timeparms, authflavour,
				      1, flags & NFS_MOUNT_NORESVPORT);
				      1, noresvport);
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;
	strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
	strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
@@ -1378,27 +1398,71 @@ static int nfs4_set_client(struct nfs_server *server,
	dprintk("--> nfs4_set_client()\n");
	dprintk("--> nfs4_set_client()\n");


	/* Allocate or find a client reference we can use */
	/* Allocate or find a client reference we can use */
	clp = nfs_get_client(&cl_init);
	clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour,
			     server->flags & NFS_MOUNT_NORESVPORT);
	if (IS_ERR(clp)) {
	if (IS_ERR(clp)) {
		error = PTR_ERR(clp);
		error = PTR_ERR(clp);
		goto error;
		goto error;
	}
	}
	error = nfs4_init_client(clp, timeparms, ip_addr, authflavour,

					server->flags);
	/*
	if (error < 0)
	 * Query for the lease time on clientid setup or renewal
		goto error_put;
	 *
	 * Note that this will be set on nfs_clients that were created
	 * only for the DS role and did not set this bit, but now will
	 * serve a dual role.
	 */
	set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);


	server->nfs_client = clp;
	server->nfs_client = clp;
	dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
	dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
	return 0;
	return 0;

error_put:
	nfs_put_client(clp);
error:
error:
	dprintk("<-- nfs4_set_client() = xerror %d\n", error);
	dprintk("<-- nfs4_set_client() = xerror %d\n", error);
	return error;
	return error;
}
}


/*
 * Set up a pNFS Data Server client.
 *
 * Return any existing nfs_client that matches server address,port,version
 * and minorversion.
 *
 * For a new nfs_client, use a soft mount (default), a low retrans and a
 * low timeout interval so that if a connection is lost, we retry through
 * the MDS.
 */
struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
		const struct sockaddr *ds_addr,
		int ds_addrlen, int ds_proto)
{
	struct nfs_client_initdata cl_init = {
		.addr = ds_addr,
		.addrlen = ds_addrlen,
		.rpc_ops = &nfs_v4_clientops,
		.proto = ds_proto,
		.minorversion = mds_clp->cl_minorversion,
	};
	struct rpc_timeout ds_timeout = {
		.to_initval = 15 * HZ,
		.to_maxval = 15 * HZ,
		.to_retries = 1,
		.to_exponential = 1,
	};
	struct nfs_client *clp;

	/*
	 * Set an authflavor equual to the MDS value. Use the MDS nfs_client
	 * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
	 * (section 13.1 RFC 5661).
	 */
	clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
			     mds_clp->cl_rpcclient->cl_auth->au_flavor, 0);

	dprintk("<-- %s %p\n", __func__, clp);
	return clp;
}
EXPORT_SYMBOL(nfs4_set_ds_client);


/*
/*
 * Session has been established, and the client marked ready.
 * Session has been established, and the client marked ready.
@@ -1435,6 +1499,10 @@ static int nfs4_server_common_setup(struct nfs_server *server,
	BUG_ON(!server->nfs_client->rpc_ops);
	BUG_ON(!server->nfs_client->rpc_ops);
	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);


	/* data servers support only a subset of NFSv4.1 */
	if (is_ds_only_client(server->nfs_client))
		return -EPROTONOSUPPORT;

	fattr = nfs_alloc_fattr();
	fattr = nfs_alloc_fattr();
	if (fattr == NULL)
	if (fattr == NULL)
		return -ENOMEM;
		return -ENOMEM;
@@ -1504,6 +1572,13 @@ static int nfs4_init_server(struct nfs_server *server,
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;


	/*
	 * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
	 * authentication.
	 */
	if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX)
		server->caps |= NFS_CAP_UIDGID_NOMAP;

	if (data->rsize)
	if (data->rsize)
		server->rsize = nfs_block_size(data->rsize, NULL);
		server->rsize = nfs_block_size(data->rsize, NULL);
	if (data->wsize)
	if (data->wsize)
@@ -1921,3 +1996,7 @@ void nfs_fs_proc_exit(void)
}
}


#endif /* CONFIG_PROC_FS */
#endif /* CONFIG_PROC_FS */

module_param(nfs4_disable_idmapping, bool, 0644);
MODULE_PARM_DESC(nfs4_disable_idmapping,
		"Turn off NFSv4 idmapping when using 'sec=sys'");
+6 −2
Original line number Original line Diff line number Diff line
@@ -45,6 +45,7 @@
#include <linux/pagemap.h>
#include <linux/pagemap.h>
#include <linux/kref.h>
#include <linux/kref.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/task_io_accounting_ops.h>


#include <linux/nfs_fs.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
#include <linux/nfs_page.h>
@@ -649,8 +650,7 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
{
{
	struct nfs_write_data *data = calldata;
	struct nfs_write_data *data = calldata;


	if (nfs_writeback_done(task, data) != 0)
	nfs_writeback_done(task, data);
		return;
}
}


/*
/*
@@ -938,6 +938,8 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
	if (retval)
	if (retval)
		goto out;
		goto out;


	task_io_account_read(count);

	retval = nfs_direct_read(iocb, iov, nr_segs, pos);
	retval = nfs_direct_read(iocb, iov, nr_segs, pos);
	if (retval > 0)
	if (retval > 0)
		iocb->ki_pos = pos + retval;
		iocb->ki_pos = pos + retval;
@@ -999,6 +1001,8 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
	if (retval)
	if (retval)
		goto out;
		goto out;


	task_io_account_write(count);

	retval = nfs_direct_write(iocb, iov, nr_segs, pos, count);
	retval = nfs_direct_write(iocb, iov, nr_segs, pos, count);


	if (retval > 0)
	if (retval > 0)
Loading