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

Commit 5f40d420 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
  NFS: NFSROOT should default to "proto=udp"
  nfs4: remove duplicated #include
  NFSv4: nfs4_state_mark_reclaim_nograce() should be static
  NFSv4: Fix the setlk error handler
  NFSv4.1: Fix the handling of the SEQUENCE status bits
  NFSv4/4.1: Fix nfs4_schedule_state_recovery abuses
  NFSv4.1 reclaim complete must wait for completion
  NFSv4: remove duplicate clientid in struct nfs_client
  NFSv4.1: Retry CREATE_SESSION on NFS4ERR_DELAY
  sunrpc: Propagate errors from xs_bind() through xs_create_sock()
  (try3-resend) Fix nfs_compat_user_ino64 so it doesn't cause problems if bit 31 or 63 are set in fileid
  nfs: fix compilation warning
  nfs: add kmalloc return value check in decode_and_add_ds
  SUNRPC: Remove resource leak in svc_rdma_send_error()
  nfs: close NFSv4 COMMIT vs. CLOSE race
  SUNRPC: Close a race in __rpc_wait_for_completion_task()
parents 215fd2fa 53d47375
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <linux/inet.h>
#include <linux/nfs_xdr.h>
#include <linux/slab.h>
#include <linux/compat.h>

#include <asm/system.h>
#include <asm/uaccess.h>
@@ -89,7 +90,11 @@ int nfs_wait_bit_killable(void *word)
 */
u64 nfs_compat_user_ino64(u64 fileid)
{
	int ino;
#ifdef CONFIG_COMPAT
	compat_ulong_t ino;
#else	
	unsigned long ino;
#endif

	if (enable_ino64)
		return fileid;
+7 −3
Original line number Diff line number Diff line
@@ -298,6 +298,11 @@ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp);
#if defined(CONFIG_NFS_V4_1)
struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp);
extern void nfs4_schedule_session_recovery(struct nfs4_session *);
#else
static inline void nfs4_schedule_session_recovery(struct nfs4_session *session)
{
}
#endif /* CONFIG_NFS_V4_1 */

extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
@@ -307,10 +312,9 @@ extern void nfs4_put_open_state(struct nfs4_state *);
extern void nfs4_close_state(struct path *, struct nfs4_state *, fmode_t);
extern void nfs4_close_sync(struct path *, struct nfs4_state *, fmode_t);
extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
extern void nfs4_schedule_state_recovery(struct nfs_client *);
extern void nfs4_schedule_lease_recovery(struct nfs_client *);
extern void nfs4_schedule_state_manager(struct nfs_client *);
extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state);
extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state);
extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
extern void nfs41_handle_recall_slot(struct nfs_client *clp);
extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
+4 −0
Original line number Diff line number Diff line
@@ -219,6 +219,10 @@ decode_and_add_ds(__be32 **pp, struct inode *inode)
		goto out_err;
	}
	buf = kmalloc(rlen + 1, GFP_KERNEL);
	if (!buf) {
		dprintk("%s: Not enough memory\n", __func__);
		goto out_err;
	}
	buf[rlen] = '\0';
	memcpy(buf, r_addr, rlen);

+52 −39
Original line number Diff line number Diff line
@@ -51,7 +51,6 @@
#include <linux/sunrpc/bc_xprt.h>
#include <linux/xattr.h>
#include <linux/utsname.h>
#include <linux/mm.h>

#include "nfs4_fs.h"
#include "delegation.h"
@@ -257,12 +256,13 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
		case -NFS4ERR_OPENMODE:
			if (state == NULL)
				break;
			nfs4_state_mark_reclaim_nograce(clp, state);
			goto do_state_recovery;
			nfs4_schedule_stateid_recovery(server, state);
			goto wait_on_recovery;
		case -NFS4ERR_STALE_STATEID:
		case -NFS4ERR_STALE_CLIENTID:
		case -NFS4ERR_EXPIRED:
			goto do_state_recovery;
			nfs4_schedule_lease_recovery(clp);
			goto wait_on_recovery;
#if defined(CONFIG_NFS_V4_1)
		case -NFS4ERR_BADSESSION:
		case -NFS4ERR_BADSLOT:
@@ -273,7 +273,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
		case -NFS4ERR_SEQ_MISORDERED:
			dprintk("%s ERROR: %d Reset session\n", __func__,
				errorcode);
			nfs4_schedule_state_recovery(clp);
			nfs4_schedule_session_recovery(clp->cl_session);
			exception->retry = 1;
			break;
#endif /* defined(CONFIG_NFS_V4_1) */
@@ -296,8 +296,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
	}
	/* We failed to handle the error */
	return nfs4_map_errors(ret);
do_state_recovery:
	nfs4_schedule_state_recovery(clp);
wait_on_recovery:
	ret = nfs4_wait_clnt_recover(clp);
	if (ret == 0)
		exception->retry = 1;
@@ -436,8 +435,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
		clp = res->sr_session->clp;
		do_renew_lease(clp, timestamp);
		/* Check sequence flags */
		if (atomic_read(&clp->cl_count) > 1)
			nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
		if (res->sr_status_flags != 0)
			nfs4_schedule_lease_recovery(clp);
		break;
	case -NFS4ERR_DELAY:
		/* The server detected a resend of the RPC call and
@@ -1256,14 +1255,13 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
			case -NFS4ERR_BAD_HIGH_SLOT:
			case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
			case -NFS4ERR_DEADSESSION:
				nfs4_schedule_state_recovery(
					server->nfs_client);
				nfs4_schedule_session_recovery(server->nfs_client->cl_session);
				goto out;
			case -NFS4ERR_STALE_CLIENTID:
			case -NFS4ERR_STALE_STATEID:
			case -NFS4ERR_EXPIRED:
				/* Don't recall a delegation if it was lost */
				nfs4_schedule_state_recovery(server->nfs_client);
				nfs4_schedule_lease_recovery(server->nfs_client);
				goto out;
			case -ERESTARTSYS:
				/*
@@ -1272,7 +1270,7 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
				 */
			case -NFS4ERR_ADMIN_REVOKED:
			case -NFS4ERR_BAD_STATEID:
				nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
				nfs4_schedule_stateid_recovery(server, state);
			case -EKEYEXPIRED:
				/*
				 * User RPCSEC_GSS context has expired.
@@ -1588,7 +1586,7 @@ static int nfs4_recover_expired_lease(struct nfs_server *server)
		if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
		    !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state))
			break;
		nfs4_schedule_state_recovery(clp);
		nfs4_schedule_state_manager(clp);
		ret = -EIO;
	}
	return ret;
@@ -3179,7 +3177,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata)
	if (task->tk_status < 0) {
		/* Unless we're shutting down, schedule state recovery! */
		if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0)
			nfs4_schedule_state_recovery(clp);
			nfs4_schedule_lease_recovery(clp);
		return;
	}
	do_renew_lease(clp, timestamp);
@@ -3262,7 +3260,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen,
	spages = pages;

	do {
		len = min(PAGE_CACHE_SIZE, buflen);
		len = min_t(size_t, PAGE_CACHE_SIZE, buflen);
		newpage = alloc_page(GFP_KERNEL);

		if (newpage == NULL)
@@ -3504,12 +3502,13 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
		case -NFS4ERR_OPENMODE:
			if (state == NULL)
				break;
			nfs4_state_mark_reclaim_nograce(clp, state);
			goto do_state_recovery;
			nfs4_schedule_stateid_recovery(server, state);
			goto wait_on_recovery;
		case -NFS4ERR_STALE_STATEID:
		case -NFS4ERR_STALE_CLIENTID:
		case -NFS4ERR_EXPIRED:
			goto do_state_recovery;
			nfs4_schedule_lease_recovery(clp);
			goto wait_on_recovery;
#if defined(CONFIG_NFS_V4_1)
		case -NFS4ERR_BADSESSION:
		case -NFS4ERR_BADSLOT:
@@ -3520,7 +3519,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
		case -NFS4ERR_SEQ_MISORDERED:
			dprintk("%s ERROR %d, Reset session\n", __func__,
				task->tk_status);
			nfs4_schedule_state_recovery(clp);
			nfs4_schedule_session_recovery(clp->cl_session);
			task->tk_status = 0;
			return -EAGAIN;
#endif /* CONFIG_NFS_V4_1 */
@@ -3537,9 +3536,8 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
	}
	task->tk_status = nfs4_map_errors(task->tk_status);
	return 0;
do_state_recovery:
wait_on_recovery:
	rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
	nfs4_schedule_state_recovery(clp);
	if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
		rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
	task->tk_status = 0;
@@ -4150,7 +4148,7 @@ static void nfs4_lock_release(void *calldata)
		task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
				data->arg.lock_seqid);
		if (!IS_ERR(task))
			rpc_put_task(task);
			rpc_put_task_async(task);
		dprintk("%s: cancelling lock!\n", __func__);
	} else
		nfs_free_seqid(data->arg.lock_seqid);
@@ -4174,23 +4172,18 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = {

static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
{
	struct nfs_client *clp = server->nfs_client;
	struct nfs4_state *state = lsp->ls_state;

	switch (error) {
	case -NFS4ERR_ADMIN_REVOKED:
	case -NFS4ERR_BAD_STATEID:
	case -NFS4ERR_EXPIRED:
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
		if (new_lock_owner != 0 ||
		   (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
			nfs4_state_mark_reclaim_nograce(clp, state);
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
			nfs4_schedule_stateid_recovery(server, lsp->ls_state);
		break;
	case -NFS4ERR_STALE_STATEID:
		if (new_lock_owner != 0 ||
		    (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
			nfs4_state_mark_reclaim_reboot(clp, state);
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
	case -NFS4ERR_EXPIRED:
		nfs4_schedule_lease_recovery(server->nfs_client);
	};
}

@@ -4406,12 +4399,14 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
			case -NFS4ERR_EXPIRED:
			case -NFS4ERR_STALE_CLIENTID:
			case -NFS4ERR_STALE_STATEID:
				nfs4_schedule_lease_recovery(server->nfs_client);
				goto out;
			case -NFS4ERR_BADSESSION:
			case -NFS4ERR_BADSLOT:
			case -NFS4ERR_BAD_HIGH_SLOT:
			case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
			case -NFS4ERR_DEADSESSION:
				nfs4_schedule_state_recovery(server->nfs_client);
				nfs4_schedule_session_recovery(server->nfs_client->cl_session);
				goto out;
			case -ERESTARTSYS:
				/*
@@ -4421,7 +4416,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
			case -NFS4ERR_ADMIN_REVOKED:
			case -NFS4ERR_BAD_STATEID:
			case -NFS4ERR_OPENMODE:
				nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
				nfs4_schedule_stateid_recovery(server, state);
				err = 0;
				goto out;
			case -EKEYEXPIRED:
@@ -5028,10 +5023,20 @@ int nfs4_proc_create_session(struct nfs_client *clp)
	int status;
	unsigned *ptr;
	struct nfs4_session *session = clp->cl_session;
	long timeout = 0;
	int err;

	dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);

	do {
		status = _nfs4_proc_create_session(clp);
		if (status == -NFS4ERR_DELAY) {
			err = nfs4_delay(clp->cl_rpcclient, &timeout);
			if (err)
				status = err;
		}
	} while (status == -NFS4ERR_DELAY);

	if (status)
		goto out;

@@ -5140,7 +5145,7 @@ static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client
		rpc_delay(task, NFS4_POLL_RETRY_MAX);
		return -EAGAIN;
	default:
		nfs4_schedule_state_recovery(clp);
		nfs4_schedule_lease_recovery(clp);
	}
	return 0;
}
@@ -5227,7 +5232,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr
	if (IS_ERR(task))
		ret = PTR_ERR(task);
	else
		rpc_put_task(task);
		rpc_put_task_async(task);
	dprintk("<-- %s status=%d\n", __func__, ret);
	return ret;
}
@@ -5243,8 +5248,13 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
		goto out;
	}
	ret = rpc_wait_for_completion_task(task);
	if (!ret)
	if (!ret) {
		struct nfs4_sequence_res *res = task->tk_msg.rpc_resp;

		if (task->tk_status == 0)
			nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
		ret = task->tk_status;
	}
	rpc_put_task(task);
out:
	dprintk("<-- %s status=%d\n", __func__, ret);
@@ -5281,7 +5291,7 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
		rpc_delay(task, NFS4_POLL_RETRY_MAX);
		return -EAGAIN;
	default:
		nfs4_schedule_state_recovery(clp);
		nfs4_schedule_lease_recovery(clp);
	}
	return 0;
}
@@ -5349,6 +5359,9 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
		status = PTR_ERR(task);
		goto out;
	}
	status = nfs4_wait_for_completion_rpc_task(task);
	if (status == 0)
		status = task->tk_status;
	rpc_put_task(task);
	return 0;
out:
+21 −8
Original line number Diff line number Diff line
@@ -1007,9 +1007,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
}

/*
 * Schedule a state recovery attempt
 * Schedule a lease recovery attempt
 */
void nfs4_schedule_state_recovery(struct nfs_client *clp)
void nfs4_schedule_lease_recovery(struct nfs_client *clp)
{
	if (!clp)
		return;
@@ -1018,7 +1018,7 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp)
	nfs4_schedule_state_manager(clp);
}

int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state)
static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state)
{

	set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);
@@ -1032,7 +1032,7 @@ int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *st
	return 1;
}

int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state)
static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state)
{
	set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags);
	clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);
@@ -1041,6 +1041,14 @@ int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *s
	return 1;
}

void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state)
{
	struct nfs_client *clp = server->nfs_client;

	nfs4_state_mark_reclaim_nograce(clp, state);
	nfs4_schedule_state_manager(clp);
}

static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops)
{
	struct inode *inode = state->inode;
@@ -1436,10 +1444,15 @@ static int nfs4_reclaim_lease(struct nfs_client *clp)
}

#ifdef CONFIG_NFS_V4_1
void nfs4_schedule_session_recovery(struct nfs4_session *session)
{
	nfs4_schedule_lease_recovery(session->clp);
}

void nfs41_handle_recall_slot(struct nfs_client *clp)
{
	set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
	nfs4_schedule_state_recovery(clp);
	nfs4_schedule_state_manager(clp);
}

static void nfs4_reset_all_state(struct nfs_client *clp)
@@ -1447,7 +1460,7 @@ static void nfs4_reset_all_state(struct nfs_client *clp)
	if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
		clp->cl_boot_time = CURRENT_TIME;
		nfs4_state_start_reclaim_nograce(clp);
		nfs4_schedule_state_recovery(clp);
		nfs4_schedule_state_manager(clp);
	}
}

@@ -1455,7 +1468,7 @@ static void nfs41_handle_server_reboot(struct nfs_client *clp)
{
	if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
		nfs4_state_start_reclaim_reboot(clp);
		nfs4_schedule_state_recovery(clp);
		nfs4_schedule_state_manager(clp);
	}
}

@@ -1475,7 +1488,7 @@ static void nfs41_handle_cb_path_down(struct nfs_client *clp)
{
	nfs_expire_all_delegations(clp);
	if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0)
		nfs4_schedule_state_recovery(clp);
		nfs4_schedule_state_manager(clp);
}

void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
Loading