Skip to content

Commit c4a8616

Browse files
committed
Merge tag 'nfs-for-4.9-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS client updates from Anna Schumaker: "Highlights include: Stable bugfixes: - sunrpc: fix writ espace race causing stalls - NFS: Fix inode corruption in nfs_prime_dcache() - NFSv4: Don't report revoked delegations as valid in nfs_have_delegation() - NFSv4: nfs4_copy_delegation_stateid() must fail if the delegation is invalid - NFSv4: Open state recovery must account for file permission changes - NFSv4.2: Fix a reference leak in nfs42_proc_layoutstats_generic Features: - Add support for tracking multiple layout types with an ordered list - Add support for using multiple backchannel threads on the client - Add support for pNFS file layout session trunking - Delay xprtrdma use of DMA API (for device driver removal) - Add support for xprtrdma remote invalidation - Add support for larger xprtrdma inline thresholds - Use a scatter/gather list for sending xprtrdma RPC calls - Add support for the CB_NOTIFY_LOCK callback - Improve hashing sunrpc auth_creds by using both uid and gid Bugfixes: - Fix xprtrdma use of DMA API - Validate filenames before adding to the dcache - Fix corruption of xdr->nwords in xdr_copy_to_scratch - Fix setting buffer length in xdr_set_next_buffer() - Don't deadlock the state manager on the SEQUENCE status flags - Various delegation and stateid related fixes - Retry operations if an interrupted slot receives EREMOTEIO - Make nfs boot time y2038 safe" * tag 'nfs-for-4.9-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (100 commits) NFSv4.2: Fix a reference leak in nfs42_proc_layoutstats_generic fs: nfs: Make nfs boot time y2038 safe sunrpc: replace generic auth_cred hash with auth-specific function sunrpc: add RPCSEC_GSS hash_cred() function sunrpc: add auth_unix hash_cred() function sunrpc: add generic_auth hash_cred() function sunrpc: add hash_cred() function to rpc_authops struct Retry operation on EREMOTEIO on an interrupted slot pNFS: Fix atime updates on pNFS clients sunrpc: queue work on system_power_efficient_wq NFSv4.1: Even if the stateid is OK, we may need to recover the open modes NFSv4: If recovery failed for a specific open stateid, then don't retry NFSv4: Fix retry issues with nfs41_test/free_stateid NFSv4: Open state recovery must account for file permission changes NFSv4: Mark the lock and open stateids as invalid after freeing them NFSv4: Don't test open_stateid unless it is set NFSv4: nfs4_do_handle_exception() handle revoke/expiry of a single stateid NFS: Always call nfs_inode_find_state_and_recover() when revoking a delegation NFSv4: Fix a race when updating an open_stateid NFSv4: Fix a race in nfs_inode_reclaim_delegation() ...
2 parents 2778556 + 3f807e5 commit c4a8616

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2195
-964
lines changed

Documentation/kernel-parameters.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,6 +2470,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
24702470
nfsrootdebug [NFS] enable nfsroot debugging messages.
24712471
See Documentation/filesystems/nfs/nfsroot.txt.
24722472

2473+
nfs.callback_nr_threads=
2474+
[NFSv4] set the total number of threads that the
2475+
NFS client will assign to service NFSv4 callback
2476+
requests.
2477+
24732478
nfs.callback_tcpport=
24742479
[NFS] set the TCP port on which the NFSv4 callback
24752480
channel should listen.
@@ -2493,6 +2498,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
24932498
of returning the full 64-bit number.
24942499
The default is to return 64-bit inode numbers.
24952500

2501+
nfs.max_session_cb_slots=
2502+
[NFSv4.1] Sets the maximum number of session
2503+
slots the client will assign to the callback
2504+
channel. This determines the maximum number of
2505+
callbacks the client will process in parallel for
2506+
a particular server.
2507+
24962508
nfs.max_session_slots=
24972509
[NFSv4.1] Sets the maximum number of session slots
24982510
the client will attempt to negotiate with the server.

fs/nfs/cache_lib.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static void nfs_dns_cache_revisit(struct cache_deferred_req *d, int toomany)
7676

7777
dreq = container_of(d, struct nfs_cache_defer_req, deferred_req);
7878

79-
complete_all(&dreq->completion);
79+
complete(&dreq->completion);
8080
nfs_cache_defer_req_put(dreq);
8181
}
8282

fs/nfs/callback.c

Lines changed: 54 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
struct nfs_callback_data {
3232
unsigned int users;
3333
struct svc_serv *serv;
34-
struct svc_rqst *rqst;
35-
struct task_struct *task;
3634
};
3735

3836
static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
@@ -89,15 +87,6 @@ nfs4_callback_svc(void *vrqstp)
8987
return 0;
9088
}
9189

92-
/*
93-
* Prepare to bring up the NFSv4 callback service
94-
*/
95-
static struct svc_rqst *
96-
nfs4_callback_up(struct svc_serv *serv)
97-
{
98-
return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
99-
}
100-
10190
#if defined(CONFIG_NFS_V4_1)
10291
/*
10392
* The callback service for NFSv4.1 callbacks
@@ -139,29 +128,6 @@ nfs41_callback_svc(void *vrqstp)
139128
return 0;
140129
}
141130

142-
/*
143-
* Bring up the NFSv4.1 callback service
144-
*/
145-
static struct svc_rqst *
146-
nfs41_callback_up(struct svc_serv *serv)
147-
{
148-
struct svc_rqst *rqstp;
149-
150-
INIT_LIST_HEAD(&serv->sv_cb_list);
151-
spin_lock_init(&serv->sv_cb_lock);
152-
init_waitqueue_head(&serv->sv_cb_waitq);
153-
rqstp = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
154-
dprintk("--> %s return %d\n", __func__, PTR_ERR_OR_ZERO(rqstp));
155-
return rqstp;
156-
}
157-
158-
static void nfs_minorversion_callback_svc_setup(struct svc_serv *serv,
159-
struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp))
160-
{
161-
*rqstpp = nfs41_callback_up(serv);
162-
*callback_svc = nfs41_callback_svc;
163-
}
164-
165131
static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
166132
struct svc_serv *serv)
167133
{
@@ -173,13 +139,6 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
173139
xprt->bc_serv = serv;
174140
}
175141
#else
176-
static void nfs_minorversion_callback_svc_setup(struct svc_serv *serv,
177-
struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp))
178-
{
179-
*rqstpp = ERR_PTR(-ENOTSUPP);
180-
*callback_svc = ERR_PTR(-ENOTSUPP);
181-
}
182-
183142
static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
184143
struct svc_serv *serv)
185144
{
@@ -189,45 +148,22 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
189148
static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
190149
struct svc_serv *serv)
191150
{
192-
struct svc_rqst *rqstp;
193-
int (*callback_svc)(void *vrqstp);
194-
struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
151+
int nrservs = nfs_callback_nr_threads;
195152
int ret;
196153

197154
nfs_callback_bc_serv(minorversion, xprt, serv);
198155

199-
if (cb_info->task)
200-
return 0;
156+
if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS)
157+
nrservs = NFS4_MIN_NR_CALLBACK_THREADS;
201158

202-
switch (minorversion) {
203-
case 0:
204-
/* v4.0 callback setup */
205-
rqstp = nfs4_callback_up(serv);
206-
callback_svc = nfs4_callback_svc;
207-
break;
208-
default:
209-
nfs_minorversion_callback_svc_setup(serv,
210-
&rqstp, &callback_svc);
211-
}
212-
213-
if (IS_ERR(rqstp))
214-
return PTR_ERR(rqstp);
215-
216-
svc_sock_update_bufs(serv);
159+
if (serv->sv_nrthreads-1 == nrservs)
160+
return 0;
217161

218-
cb_info->serv = serv;
219-
cb_info->rqst = rqstp;
220-
cb_info->task = kthread_create(callback_svc, cb_info->rqst,
221-
"nfsv4.%u-svc", minorversion);
222-
if (IS_ERR(cb_info->task)) {
223-
ret = PTR_ERR(cb_info->task);
224-
svc_exit_thread(cb_info->rqst);
225-
cb_info->rqst = NULL;
226-
cb_info->task = NULL;
162+
ret = serv->sv_ops->svo_setup(serv, NULL, nrservs);
163+
if (ret) {
164+
serv->sv_ops->svo_setup(serv, NULL, 0);
227165
return ret;
228166
}
229-
rqstp->rq_task = cb_info->task;
230-
wake_up_process(cb_info->task);
231167
dprintk("nfs_callback_up: service started\n");
232168
return 0;
233169
}
@@ -281,19 +217,41 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv,
281217
return ret;
282218
}
283219

284-
static struct svc_serv_ops nfs_cb_sv_ops = {
220+
static struct svc_serv_ops nfs40_cb_sv_ops = {
221+
.svo_function = nfs4_callback_svc,
285222
.svo_enqueue_xprt = svc_xprt_do_enqueue,
223+
.svo_setup = svc_set_num_threads,
224+
.svo_module = THIS_MODULE,
225+
};
226+
#if defined(CONFIG_NFS_V4_1)
227+
static struct svc_serv_ops nfs41_cb_sv_ops = {
228+
.svo_function = nfs41_callback_svc,
229+
.svo_enqueue_xprt = svc_xprt_do_enqueue,
230+
.svo_setup = svc_set_num_threads,
231+
.svo_module = THIS_MODULE,
232+
};
233+
234+
struct svc_serv_ops *nfs4_cb_sv_ops[] = {
235+
[0] = &nfs40_cb_sv_ops,
236+
[1] = &nfs41_cb_sv_ops,
237+
};
238+
#else
239+
struct svc_serv_ops *nfs4_cb_sv_ops[] = {
240+
[0] = &nfs40_cb_sv_ops,
241+
[1] = NULL,
286242
};
243+
#endif
287244

288245
static struct svc_serv *nfs_callback_create_svc(int minorversion)
289246
{
290247
struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
291248
struct svc_serv *serv;
249+
struct svc_serv_ops *sv_ops;
292250

293251
/*
294252
* Check whether we're already up and running.
295253
*/
296-
if (cb_info->task) {
254+
if (cb_info->serv) {
297255
/*
298256
* Note: increase service usage, because later in case of error
299257
* svc_destroy() will be called.
@@ -302,6 +260,17 @@ static struct svc_serv *nfs_callback_create_svc(int minorversion)
302260
return cb_info->serv;
303261
}
304262

263+
switch (minorversion) {
264+
case 0:
265+
sv_ops = nfs4_cb_sv_ops[0];
266+
break;
267+
default:
268+
sv_ops = nfs4_cb_sv_ops[1];
269+
}
270+
271+
if (sv_ops == NULL)
272+
return ERR_PTR(-ENOTSUPP);
273+
305274
/*
306275
* Sanity check: if there's no task,
307276
* we should be the first user ...
@@ -310,11 +279,12 @@ static struct svc_serv *nfs_callback_create_svc(int minorversion)
310279
printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
311280
cb_info->users);
312281

313-
serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, &nfs_cb_sv_ops);
282+
serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);
314283
if (!serv) {
315284
printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
316285
return ERR_PTR(-ENOMEM);
317286
}
287+
cb_info->serv = serv;
318288
/* As there is only one thread we need to over-ride the
319289
* default maximum of 80 connections
320290
*/
@@ -357,6 +327,8 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
357327
* thread exits.
358328
*/
359329
err_net:
330+
if (!cb_info->users)
331+
cb_info->serv = NULL;
360332
svc_destroy(serv);
361333
err_create:
362334
mutex_unlock(&nfs_callback_mutex);
@@ -374,18 +346,18 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
374346
void nfs_callback_down(int minorversion, struct net *net)
375347
{
376348
struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
349+
struct svc_serv *serv;
377350

378351
mutex_lock(&nfs_callback_mutex);
379-
nfs_callback_down_net(minorversion, cb_info->serv, net);
352+
serv = cb_info->serv;
353+
nfs_callback_down_net(minorversion, serv, net);
380354
cb_info->users--;
381-
if (cb_info->users == 0 && cb_info->task != NULL) {
382-
kthread_stop(cb_info->task);
383-
dprintk("nfs_callback_down: service stopped\n");
384-
svc_exit_thread(cb_info->rqst);
355+
if (cb_info->users == 0) {
356+
svc_get(serv);
357+
serv->sv_ops->svo_setup(serv, NULL, 0);
358+
svc_destroy(serv);
385359
dprintk("nfs_callback_down: service destroyed\n");
386360
cb_info->serv = NULL;
387-
cb_info->rqst = NULL;
388-
cb_info->task = NULL;
389361
}
390362
mutex_unlock(&nfs_callback_mutex);
391363
}

fs/nfs/callback.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,15 @@ extern __be32 nfs4_callback_devicenotify(
179179
struct cb_devicenotifyargs *args,
180180
void *dummy, struct cb_process_state *cps);
181181

182+
struct cb_notify_lock_args {
183+
struct nfs_fh cbnl_fh;
184+
struct nfs_lowner cbnl_owner;
185+
bool cbnl_valid;
186+
};
187+
188+
extern __be32 nfs4_callback_notify_lock(struct cb_notify_lock_args *args,
189+
void *dummy,
190+
struct cb_process_state *cps);
182191
#endif /* CONFIG_NFS_V4_1 */
183192
extern int check_gss_callback_principal(struct nfs_client *, struct svc_rqst *);
184193
extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args,
@@ -198,6 +207,9 @@ extern void nfs_callback_down(int minorversion, struct net *net);
198207
#define NFS41_BC_MIN_CALLBACKS 1
199208
#define NFS41_BC_MAX_CALLBACKS 1
200209

210+
#define NFS4_MIN_NR_CALLBACK_THREADS 1
211+
201212
extern unsigned int nfs_callback_set_tcpport;
213+
extern unsigned short nfs_callback_nr_threads;
202214

203215
#endif /* __LINUX_FS_NFS_CALLBACK_H */

fs/nfs/callback_proc.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,4 +628,20 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy,
628628
dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
629629
return status;
630630
}
631+
632+
__be32 nfs4_callback_notify_lock(struct cb_notify_lock_args *args, void *dummy,
633+
struct cb_process_state *cps)
634+
{
635+
if (!cps->clp) /* set in cb_sequence */
636+
return htonl(NFS4ERR_OP_NOT_IN_SESSION);
637+
638+
dprintk_rcu("NFS: CB_NOTIFY_LOCK request from %s\n",
639+
rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
640+
641+
/* Don't wake anybody if the string looked bogus */
642+
if (args->cbnl_valid)
643+
__wake_up(&cps->clp->cl_lock_waitq, TASK_NORMAL, 0, args);
644+
645+
return htonl(NFS4_OK);
646+
}
631647
#endif /* CONFIG_NFS_V4_1 */

0 commit comments

Comments
 (0)