Commit f07044dd authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull nfsd fixes from Chuck Lever::

 - Revert one v6.13 fix at the author's request (to be done differently)

 - Fix a minor problem with recent NFSv4.2 COPY enhancements

 - Fix an NFSv4.0 callback bug introduced in the v6.13 merge window

* tag 'nfsd-6.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
  nfsd: restore callback functionality for NFSv4.0
  NFSD: fix management of pending async copies
  nfsd: Revert "nfsd: release svc_expkey/svc_export with rcu_work"
parents 4bbf9020 7917f01a
Loading
Loading
Loading
Loading
+6 −25
Original line number Diff line number Diff line
@@ -40,24 +40,15 @@
#define	EXPKEY_HASHMAX		(1 << EXPKEY_HASHBITS)
#define	EXPKEY_HASHMASK		(EXPKEY_HASHMAX -1)

static void expkey_put_work(struct work_struct *work)
static void expkey_put(struct kref *ref)
{
	struct svc_expkey *key =
		container_of(to_rcu_work(work), struct svc_expkey, ek_rcu_work);
	struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);

	if (test_bit(CACHE_VALID, &key->h.flags) &&
	    !test_bit(CACHE_NEGATIVE, &key->h.flags))
		path_put(&key->ek_path);
	auth_domain_put(key->ek_client);
	kfree(key);
}

static void expkey_put(struct kref *ref)
{
	struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);

	INIT_RCU_WORK(&key->ek_rcu_work, expkey_put_work);
	queue_rcu_work(system_wq, &key->ek_rcu_work);
	kfree_rcu(key, ek_rcu);
}

static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
@@ -364,26 +355,16 @@ static void export_stats_destroy(struct export_stats *stats)
					    EXP_STATS_COUNTERS_NUM);
}

static void svc_export_put_work(struct work_struct *work)
static void svc_export_put(struct kref *ref)
{
	struct svc_export *exp =
		container_of(to_rcu_work(work), struct svc_export, ex_rcu_work);

	struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
	path_put(&exp->ex_path);
	auth_domain_put(exp->ex_client);
	nfsd4_fslocs_free(&exp->ex_fslocs);
	export_stats_destroy(exp->ex_stats);
	kfree(exp->ex_stats);
	kfree(exp->ex_uuid);
	kfree(exp);
}

static void svc_export_put(struct kref *ref)
{
	struct svc_export *exp = container_of(ref, struct svc_export, h.ref);

	INIT_RCU_WORK(&exp->ex_rcu_work, svc_export_put_work);
	queue_rcu_work(system_wq, &exp->ex_rcu_work);
	kfree_rcu(exp, ex_rcu);
}

static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
+2 −2
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ struct svc_export {
	u32			ex_layout_types;
	struct nfsd4_deviceid_map *ex_devid_map;
	struct cache_detail	*cd;
	struct rcu_work		ex_rcu_work;
	struct rcu_head		ex_rcu;
	unsigned long		ex_xprtsec_modes;
	struct export_stats	*ex_stats;
};
@@ -92,7 +92,7 @@ struct svc_expkey {
	u32			ek_fsid[6];

	struct path		ek_path;
	struct rcu_work		ek_rcu_work;
	struct rcu_head		ek_rcu;
};

#define EX_ISSYNC(exp)		(!((exp)->ex_flags & NFSEXP_ASYNC))
+1 −3
Original line number Diff line number Diff line
@@ -1100,7 +1100,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
		args.authflavor = clp->cl_cred.cr_flavor;
		clp->cl_cb_ident = conn->cb_ident;
	} else {
		if (!conn->cb_xprt)
		if (!conn->cb_xprt || !ses)
			return -EINVAL;
		clp->cl_cb_session = ses;
		args.bc_xprt = conn->cb_xprt;
@@ -1522,8 +1522,6 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
		ses = c->cn_session;
	}
	spin_unlock(&clp->cl_lock);
	if (!c)
		return;

	err = setup_callback_client(clp, &conn, ses);
	if (err) {
+8 −5
Original line number Diff line number Diff line
@@ -1347,7 +1347,6 @@ static void nfs4_put_copy(struct nfsd4_copy *copy)
{
	if (!refcount_dec_and_test(&copy->refcount))
		return;
	atomic_dec(&copy->cp_nn->pending_async_copies);
	kfree(copy->cp_src);
	kfree(copy);
}
@@ -1870,6 +1869,7 @@ static int nfsd4_do_async_copy(void *data)
	set_bit(NFSD4_COPY_F_COMPLETED, &copy->cp_flags);
	trace_nfsd_copy_async_done(copy);
	nfsd4_send_cb_offload(copy);
	atomic_dec(&copy->cp_nn->pending_async_copies);
	return 0;
}

@@ -1927,19 +1927,19 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
		/* Arbitrary cap on number of pending async copy operations */
		if (atomic_inc_return(&nn->pending_async_copies) >
				(int)rqstp->rq_pool->sp_nrthreads)
			goto out_err;
			goto out_dec_async_copy_err;
		async_copy->cp_src = kmalloc(sizeof(*async_copy->cp_src), GFP_KERNEL);
		if (!async_copy->cp_src)
			goto out_err;
			goto out_dec_async_copy_err;
		if (!nfs4_init_copy_state(nn, copy))
			goto out_err;
			goto out_dec_async_copy_err;
		memcpy(&result->cb_stateid, &copy->cp_stateid.cs_stid,
			sizeof(result->cb_stateid));
		dup_copy_fields(copy, async_copy);
		async_copy->copy_task = kthread_create(nfsd4_do_async_copy,
				async_copy, "%s", "copy thread");
		if (IS_ERR(async_copy->copy_task))
			goto out_err;
			goto out_dec_async_copy_err;
		spin_lock(&async_copy->cp_clp->async_lock);
		list_add(&async_copy->copies,
				&async_copy->cp_clp->async_copies);
@@ -1954,6 +1954,9 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	trace_nfsd_copy_done(copy, status);
	release_copy_files(copy);
	return status;
out_dec_async_copy_err:
	if (async_copy)
		atomic_dec(&nn->pending_async_copies);
out_err:
	if (nfsd4_ssc_is_inter(copy)) {
		/*