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

Commit 0b08b075 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

Merge branch 'bugfixes' into nfs-for-next

parents 22763c5c 1185a552
Loading
Loading
Loading
Loading
+28 −14
Original line number Original line Diff line number Diff line
@@ -92,7 +92,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
	return status;
	return status;
}
}


static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
{
{
	struct nfs_inode *nfsi = NFS_I(inode);
	struct nfs_inode *nfsi = NFS_I(inode);
	struct nfs_open_context *ctx;
	struct nfs_open_context *ctx;
@@ -116,10 +116,11 @@ static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *
			err = nfs_delegation_claim_locks(ctx, state);
			err = nfs_delegation_claim_locks(ctx, state);
		put_nfs_open_context(ctx);
		put_nfs_open_context(ctx);
		if (err != 0)
		if (err != 0)
			return;
			return err;
		goto again;
		goto again;
	}
	}
	spin_unlock(&inode->i_lock);
	spin_unlock(&inode->i_lock);
	return 0;
}
}


/*
/*
@@ -261,30 +262,34 @@ static void nfs_msync_inode(struct inode *inode)
/*
/*
 * Basic procedure for returning a delegation to the server
 * Basic procedure for returning a delegation to the server
 */
 */
static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
{
{
	struct nfs_inode *nfsi = NFS_I(inode);
	struct nfs_inode *nfsi = NFS_I(inode);
	int err;


	nfs_msync_inode(inode);
	/*
	/*
	 * Guard against new delegated open/lock/unlock calls and against
	 * Guard against new delegated open/lock/unlock calls and against
	 * state recovery
	 * state recovery
	 */
	 */
	down_write(&nfsi->rwsem);
	down_write(&nfsi->rwsem);
	nfs_delegation_claim_opens(inode, &delegation->stateid);
	err = nfs_delegation_claim_opens(inode, &delegation->stateid);
	up_write(&nfsi->rwsem);
	up_write(&nfsi->rwsem);
	nfs_msync_inode(inode);
	if (err)
		goto out;


	return nfs_do_return_delegation(inode, delegation, 1);
	err = nfs_do_return_delegation(inode, delegation, issync);
out:
	return err;
}
}


/*
/*
 * Return all delegations that have been marked for return
 * Return all delegations that have been marked for return
 */
 */
void nfs_client_return_marked_delegations(struct nfs_client *clp)
int nfs_client_return_marked_delegations(struct nfs_client *clp)
{
{
	struct nfs_delegation *delegation;
	struct nfs_delegation *delegation;
	struct inode *inode;
	struct inode *inode;
	int err = 0;


restart:
restart:
	rcu_read_lock();
	rcu_read_lock();
@@ -298,12 +303,18 @@ void nfs_client_return_marked_delegations(struct nfs_client *clp)
		delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
		delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
		spin_unlock(&clp->cl_lock);
		spin_unlock(&clp->cl_lock);
		rcu_read_unlock();
		rcu_read_unlock();
		if (delegation != NULL)
		if (delegation != NULL) {
			__nfs_inode_return_delegation(inode, delegation);
			filemap_flush(inode->i_mapping);
			err = __nfs_inode_return_delegation(inode, delegation, 0);
		}
		iput(inode);
		iput(inode);
		if (!err)
			goto restart;
			goto restart;
		set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
		return err;
	}
	}
	rcu_read_unlock();
	rcu_read_unlock();
	return 0;
}
}


/*
/*
@@ -338,8 +349,10 @@ int nfs_inode_return_delegation(struct inode *inode)
		spin_lock(&clp->cl_lock);
		spin_lock(&clp->cl_lock);
		delegation = nfs_detach_delegation_locked(nfsi, NULL);
		delegation = nfs_detach_delegation_locked(nfsi, NULL);
		spin_unlock(&clp->cl_lock);
		spin_unlock(&clp->cl_lock);
		if (delegation != NULL)
		if (delegation != NULL) {
			err = __nfs_inode_return_delegation(inode, delegation);
			nfs_msync_inode(inode);
			err = __nfs_inode_return_delegation(inode, delegation, 1);
		}
	}
	}
	return err;
	return err;
}
}
@@ -368,7 +381,8 @@ void nfs_super_return_all_delegations(struct super_block *sb)
		spin_unlock(&delegation->lock);
		spin_unlock(&delegation->lock);
	}
	}
	rcu_read_unlock();
	rcu_read_unlock();
	nfs_client_return_marked_delegations(clp);
	if (nfs_client_return_marked_delegations(clp) != 0)
		nfs4_schedule_state_manager(clp);
}
}


static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
+1 −1
Original line number Original line Diff line number Diff line
@@ -42,7 +42,7 @@ void nfs_super_return_all_delegations(struct super_block *sb);
void nfs_expire_all_delegations(struct nfs_client *clp);
void nfs_expire_all_delegations(struct nfs_client *clp);
void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
void nfs_handle_cb_pathdown(struct nfs_client *clp);
void nfs_handle_cb_pathdown(struct nfs_client *clp);
void nfs_client_return_marked_delegations(struct nfs_client *clp);
int nfs_client_return_marked_delegations(struct nfs_client *clp);


void nfs_delegation_mark_reclaim(struct nfs_client *clp);
void nfs_delegation_mark_reclaim(struct nfs_client *clp);
void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
+2 −2
Original line number Original line Diff line number Diff line
@@ -146,7 +146,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd,
	return 0;
	return 0;
}
}


struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
static struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
		struct nfs_dns_ent *key)
		struct nfs_dns_ent *key)
{
{
	struct cache_head *ch;
	struct cache_head *ch;
@@ -159,7 +159,7 @@ struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
	return container_of(ch, struct nfs_dns_ent, h);
	return container_of(ch, struct nfs_dns_ent, h);
}
}


struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd,
static struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd,
		struct nfs_dns_ent *new,
		struct nfs_dns_ent *new,
		struct nfs_dns_ent *key)
		struct nfs_dns_ent *key)
{
{
+20 −8
Original line number Original line Diff line number Diff line
@@ -1488,7 +1488,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
	return ret;
	return ret;
}
}


static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
{
{
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs4_exception exception = { };
	struct nfs4_exception exception = { };
@@ -1496,10 +1496,16 @@ static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4


	do {
	do {
		err = _nfs4_open_expired(ctx, state);
		err = _nfs4_open_expired(ctx, state);
		if (err != -NFS4ERR_DELAY)
		switch (err) {
			break;
		default:
			goto out;
		case -NFS4ERR_GRACE:
		case -NFS4ERR_DELAY:
			nfs4_handle_exception(server, err, &exception);
			nfs4_handle_exception(server, err, &exception);
			err = 0;
		}
	} while (exception.retry);
	} while (exception.retry);
out:
	return err;
	return err;
}
}


@@ -1981,7 +1987,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
	return 0;
	return 0;
}
}


void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
{
{
	if (ctx->state == NULL)
	if (ctx->state == NULL)
		return;
		return;
@@ -4049,10 +4055,16 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
			return 0;
			return 0;
		err = _nfs4_do_setlk(state, F_SETLK, request, 0);
		err = _nfs4_do_setlk(state, F_SETLK, request, 0);
		if (err != -NFS4ERR_DELAY)
		switch (err) {
			break;
		default:
			goto out;
		case -NFS4ERR_GRACE:
		case -NFS4ERR_DELAY:
			nfs4_handle_exception(server, err, &exception);
			nfs4_handle_exception(server, err, &exception);
			err = 0;
		}
	} while (exception.retry);
	} while (exception.retry);
out:
	return err;
	return err;
}
}


+31 −36
Original line number Original line Diff line number Diff line
@@ -1046,20 +1046,19 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
	nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
	nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
}
}


static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp)
static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
{
	clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
}

static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
{
{
	switch (error) {
	switch (error) {
		case -NFS4ERR_CB_PATH_DOWN:
		case -NFS4ERR_CB_PATH_DOWN:
			nfs_handle_cb_pathdown(clp);
			nfs_handle_cb_pathdown(clp);
			break;
			return 0;
		case -NFS4ERR_NO_GRACE:
			nfs4_state_end_reclaim_reboot(clp);
			return 0;
		case -NFS4ERR_STALE_CLIENTID:
		case -NFS4ERR_STALE_CLIENTID:
		case -NFS4ERR_LEASE_MOVED:
		case -NFS4ERR_LEASE_MOVED:
			set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
			set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
			nfs4_state_end_reclaim_reboot(clp);
			nfs4_state_start_reclaim_reboot(clp);
			nfs4_state_start_reclaim_reboot(clp);
			break;
			break;
		case -NFS4ERR_EXPIRED:
		case -NFS4ERR_EXPIRED:
@@ -1074,6 +1073,7 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
		case -NFS4ERR_SEQ_MISORDERED:
		case -NFS4ERR_SEQ_MISORDERED:
			set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
			set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
	}
	}
	return error;
}
}


static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops)
static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops)
@@ -1093,8 +1093,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
		if (status < 0) {
		if (status < 0) {
			set_bit(ops->owner_flag_bit, &sp->so_flags);
			set_bit(ops->owner_flag_bit, &sp->so_flags);
			nfs4_put_state_owner(sp);
			nfs4_put_state_owner(sp);
			nfs4_recovery_handle_error(clp, status);
			return nfs4_recovery_handle_error(clp, status);
			return status;
		}
		}
		nfs4_put_state_owner(sp);
		nfs4_put_state_owner(sp);
		goto restart;
		goto restart;
@@ -1124,8 +1123,7 @@ static int nfs4_check_lease(struct nfs_client *clp)
	status = ops->renew_lease(clp, cred);
	status = ops->renew_lease(clp, cred);
	put_rpccred(cred);
	put_rpccred(cred);
out:
out:
	nfs4_recovery_handle_error(clp, status);
	return nfs4_recovery_handle_error(clp, status);
	return status;
}
}


static int nfs4_reclaim_lease(struct nfs_client *clp)
static int nfs4_reclaim_lease(struct nfs_client *clp)
@@ -1234,7 +1232,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
			status = nfs4_reclaim_lease(clp);
			status = nfs4_reclaim_lease(clp);
			if (status) {
			if (status) {
				nfs4_set_lease_expired(clp, status);
				nfs4_set_lease_expired(clp, status);
				if (status == -EAGAIN)
				if (test_bit(NFS4CLNT_LEASE_EXPIRED,
							&clp->cl_state))
					continue;
					continue;
				if (clp->cl_cons_state ==
				if (clp->cl_cons_state ==
							NFS_CS_SESSION_INITING)
							NFS_CS_SESSION_INITING)
@@ -1246,9 +1245,12 @@ static void nfs4_state_manager(struct nfs_client *clp)


		if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
		if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
			status = nfs4_check_lease(clp);
			status = nfs4_check_lease(clp);
			if (status != 0)
			if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
				continue;
				continue;
			if (status < 0 && status != -NFS4ERR_CB_PATH_DOWN)
				goto out_error;
		}
		}

		/* Initialize or reset the session */
		/* Initialize or reset the session */
		if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)
		if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)
		   && nfs4_has_session(clp)) {
		   && nfs4_has_session(clp)) {
@@ -1256,41 +1258,36 @@ static void nfs4_state_manager(struct nfs_client *clp)
				status = nfs4_initialize_session(clp);
				status = nfs4_initialize_session(clp);
			else
			else
				status = nfs4_reset_session(clp);
				status = nfs4_reset_session(clp);
			if (status) {
			if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
				if (status == -NFS4ERR_STALE_CLIENTID)
				continue;
				continue;
			if (status < 0)
				goto out_error;
				goto out_error;
		}
		}
		}

		/* First recover reboot state... */
		/* First recover reboot state... */
		if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
		if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
			status = nfs4_do_reclaim(clp,
			status = nfs4_do_reclaim(clp,
				nfs4_reboot_recovery_ops[clp->cl_minorversion]);
				nfs4_reboot_recovery_ops[clp->cl_minorversion]);
			if (status == -NFS4ERR_STALE_CLIENTID)
			if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
				continue;
			    test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
			if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
				continue;
				continue;
			nfs4_state_end_reclaim_reboot(clp);
			nfs4_state_end_reclaim_reboot(clp);
			if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state))
				continue;
				continue;
			if (status < 0)
				goto out_error;
		}
		}


		/* Now recover expired state... */
		/* Now recover expired state... */
		if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
		if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
			status = nfs4_do_reclaim(clp,
			status = nfs4_do_reclaim(clp,
				nfs4_nograce_recovery_ops[clp->cl_minorversion]);
				nfs4_nograce_recovery_ops[clp->cl_minorversion]);
			if (status < 0) {
			if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
				set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
			    test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) ||
				if (status == -NFS4ERR_STALE_CLIENTID)
			    test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
					continue;
				if (status == -NFS4ERR_EXPIRED)
					continue;
				if (test_bit(NFS4CLNT_SESSION_SETUP,
								&clp->cl_state))
				continue;
				continue;
			if (status < 0)
				goto out_error;
				goto out_error;
			} else
				nfs4_state_end_reclaim_nograce(clp);
			continue;
		}
		}


		if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
		if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
@@ -1309,8 +1306,6 @@ static void nfs4_state_manager(struct nfs_client *clp)
out_error:
out_error:
	printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
	printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
			" with error %d\n", clp->cl_hostname, -status);
			" with error %d\n", clp->cl_hostname, -status);
	if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
		nfs4_state_end_reclaim_reboot(clp);
	nfs4_clear_state_manager_bit(clp);
	nfs4_clear_state_manager_bit(clp);
}
}


Loading