Commit b678c568 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS client fixes from Trond Myklebust:
 "Highlights include:

  Stable fixes:

   - NFSv4: Ensure we check the return value of update_open_stateid() so
     we correctly track active open state.

   - NFSv4: Fix for delegation state recovery to ensure we recover all
     open modes that are active.

   - NFSv4: Fix an Oops in nfs4_do_setattr

  Fixes:

   - NFS: Fix regression whereby fscache errors are appearing on 'nofsc'
     mounts

   - NFSv4: Fix a potential sleep while atomic in nfs4_do_reclaim()

   - NFSv4: Fix a credential refcount leak in nfs41_check_delegation_stateid

   - pNFS: Report errors from the call to nfs4_select_rw_stateid()

   - NFSv4: Various other delegation and open stateid recovery fixes

   - NFSv4: Fix state recovery behaviour when server connection times
     out"

* tag 'nfs-for-5.3-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  NFSv4: Ensure state recovery handles ETIMEDOUT correctly
  NFS: Fix regression whereby fscache errors are appearing on 'nofsc' mounts
  NFSv4: Fix an Oops in nfs4_do_setattr
  NFSv4: Fix a potential sleep while atomic in nfs4_do_reclaim()
  NFSv4: Check the return value of update_open_stateid()
  NFSv4.1: Only reap expired delegations
  NFSv4.1: Fix open stateid recovery
  NFSv4: Report the error from nfs4_select_rw_stateid()
  NFSv4: When recovering state fails with EAGAIN, retry the same recovery
  NFSv4: Print an error in the syslog when state is marked as irrecoverable
  NFSv4: Fix delegation state recovery
  NFSv4: Fix a credential refcount leak in nfs41_check_delegation_stateid
parents 518a1c2f 67e7b52d
Loading
Loading
Loading
Loading
+18 −7
Original line number Diff line number Diff line
@@ -153,7 +153,7 @@ again:
		/* Block nfs4_proc_unlck */
		mutex_lock(&sp->so_delegreturn_mutex);
		seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
		err = nfs4_open_delegation_recall(ctx, state, stateid, type);
		err = nfs4_open_delegation_recall(ctx, state, stateid);
		if (!err)
			err = nfs_delegation_claim_locks(state, stateid);
		if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
@@ -1046,6 +1046,22 @@ void nfs_test_expired_all_delegations(struct nfs_client *clp)
	nfs4_schedule_state_manager(clp);
}

static void
nfs_delegation_test_free_expired(struct inode *inode,
		nfs4_stateid *stateid,
		const struct cred *cred)
{
	struct nfs_server *server = NFS_SERVER(inode);
	const struct nfs4_minor_version_ops *ops = server->nfs_client->cl_mvops;
	int status;

	if (!cred)
		return;
	status = ops->test_and_free_expired(server, stateid, cred);
	if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID)
		nfs_remove_bad_delegation(inode, stateid);
}

/**
 * nfs_reap_expired_delegations - reap expired delegations
 * @clp: nfs_client to process
@@ -1057,7 +1073,6 @@ void nfs_test_expired_all_delegations(struct nfs_client *clp)
 */
void nfs_reap_expired_delegations(struct nfs_client *clp)
{
	const struct nfs4_minor_version_ops *ops = clp->cl_mvops;
	struct nfs_delegation *delegation;
	struct nfs_server *server;
	struct inode *inode;
@@ -1088,11 +1103,7 @@ restart:
			nfs4_stateid_copy(&stateid, &delegation->stateid);
			clear_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags);
			rcu_read_unlock();
			if (cred != NULL &&
			    ops->test_and_free_expired(server, &stateid, cred) < 0) {
				nfs_revoke_delegation(inode, &stateid);
				nfs_inode_find_state_and_recover(inode, &stateid);
			}
			nfs_delegation_test_free_expired(inode, &stateid, cred);
			put_cred(cred);
			if (nfs4_server_rebooted(clp)) {
				nfs_inode_mark_test_expired_delegation(server,inode);
+1 −1
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ void nfs_reap_expired_delegations(struct nfs_client *clp);

/* NFSv4 delegation-related procedures */
int nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred, const nfs4_stateid *stateid, int issync);
int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid, fmode_t type);
int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid);
bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, const struct cred **cred);
bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
+6 −1
Original line number Diff line number Diff line
@@ -114,6 +114,10 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
	struct rb_node **p, *parent;
	int diff;

	nfss->fscache_key = NULL;
	nfss->fscache = NULL;
	if (!(nfss->options & NFS_OPTION_FSCACHE))
		return;
	if (!uniq) {
		uniq = "";
		ulen = 1;
@@ -226,10 +230,11 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
void nfs_fscache_init_inode(struct inode *inode)
{
	struct nfs_fscache_inode_auxdata auxdata;
	struct nfs_server *nfss = NFS_SERVER(inode);
	struct nfs_inode *nfsi = NFS_I(inode);

	nfsi->fscache = NULL;
	if (!S_ISREG(inode->i_mode))
	if (!(nfss->fscache && S_ISREG(inode->i_mode)))
		return;

	memset(&auxdata, 0, sizeof(auxdata));
+1 −1
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ static inline void nfs_fscache_wait_on_invalidate(struct inode *inode)
 */
static inline const char *nfs_server_fscache_state(struct nfs_server *server)
{
	if (server->fscache && (server->options & NFS_OPTION_FSCACHE))
	if (server->fscache)
		return "yes";
	return "no ";
}
+2 −1
Original line number Diff line number Diff line
@@ -465,7 +465,8 @@ static inline void nfs4_schedule_session_recovery(struct nfs4_session *session,

extern struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *, const struct cred *, gfp_t);
extern void nfs4_put_state_owner(struct nfs4_state_owner *);
extern void nfs4_purge_state_owners(struct nfs_server *);
extern void nfs4_purge_state_owners(struct nfs_server *, struct list_head *);
extern void nfs4_free_state_owners(struct list_head *head);
extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
extern void nfs4_put_open_state(struct nfs4_state *);
extern void nfs4_close_state(struct nfs4_state *, fmode_t);
Loading