History

Merge tag 'nfsd-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

Pull nfsd updates from Chuck Lever: "Bruce has announced he is leaving Red Hat at the end of the month and is stepping back from his role as NFSD co-maintainer. As a result, this includes a patch removing him from the MAINTAINERS file. There is one patch in here that Jeff Layton was carrying in the locks tree. Since he had only one for this cycle, he asked us to send it to you via the nfsd tree. There continues to be 0-day reports from Robert Morris @MIT. This time we include a fix for a crash in the COPY_NOTIFY operation. Highlights: - Bruce steps down as NFSD maintainer - Prepare for dynamic nfsd thread management - More work on supporting re-exporting NFS mounts - One fs/locks patch on behalf of Jeff Layton Notable bug fixes: - Fix zero-length NFSv3 WRITEs - Fix directory cinfo on FS's that do not support iversion - Fix WRITE verifiers for stable writes - Fix crash on COPY_NOTIFY with a special state ID" * tag 'nfsd-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (51 commits) SUNRPC: Fix sockaddr handling in svcsock_accept_class trace points SUNRPC: Fix sockaddr handling in the svc_xprt_create_error trace point fs/locks: fix fcntl_getlk64/fcntl_setlk64 stub prototypes nfsd: fix crash on COPY_NOTIFY with special stateid MAINTAINERS: remove bfields NFSD: Move fill_pre_wcc() and fill_post_wcc() Revert "nfsd: skip some unnecessary stats in the v4 case" NFSD: Trace boot verifier resets NFSD: Rename boot verifier functions NFSD: Clean up the nfsd_net::nfssvc_boot field NFSD: Write verifier might go backwards nfsd: Add a tracepoint for errors in nfsd4_clone_file_range() NFSD: De-duplicate net_generic(nf->nf_net, nfsd_net_id) NFSD: De-duplicate net_generic(SVC_NET(rqstp), nfsd_net_id) NFSD: Clean up nfsd_vfs_write() nfsd: Replace use of rwsem with errseq_t NFSD: Fix verifier returned in stable WRITEs nfsd: Retry once in nfsd_open on an -EOPENSTALE return nfsd: Add errno mapping for EREMOTEIO nfsd: map EBADF ...

Linus Torvalds committed 4 years ago

Commit 175398a2 parents 49ad227 167208633 files · +702 −749Browse files

Unified · Split

33 files
  1. MAINTAINERS +1 −3
  2. fs/lockd/svc.c +61 −139
  3. fs/lockd/svclock.c +4 −2
  4. fs/nfs/callback.c +9 −23
  5. fs/nfs/export.c +1 −1
  6. fs/nfsd/filecache.c +16 −63
  7. fs/nfsd/filecache.h +0 −1
  8. fs/nfsd/netns.h +16 −11
  9. fs/nfsd/nfs3proc.c +1 −5
  10. fs/nfsd/nfs3xdr.c +0 −65
  11. fs/nfsd/nfs4proc.c +13 −11
  12. fs/nfsd/nfs4state.c +49 −14
  13. fs/nfsd/nfs4xdr.c +5 −16
  14. fs/nfsd/nfscache.c +1 −1
  15. fs/nfsd/nfsctl.c +12 −15
  16. fs/nfsd/nfsd.h +1 −1
  17. fs/nfsd/nfsfh.c +65 −1
  18. fs/nfsd/nfsfh.h +26 −14
  19. fs/nfsd/nfsproc.c +3 −5
  20. fs/nfsd/nfssvc.c +126 −94
  21. fs/nfsd/state.h +5 −0
  22. fs/nfsd/stats.c +1 −1
  23. fs/nfsd/stats.h +1 −3
  24. fs/nfsd/trace.h +85 −21
  25. fs/nfsd/vfs.c +65 −57
  26. fs/nfsd/vfs.h +2 −1
  27. include/linux/exportfs.h +0 −2
  28. include/linux/fs.h +2 −2
  29. include/linux/lockd/lockd.h +7 −2
  30. include/linux/sunrpc/svc.h +39 −40
  31. include/trace/events/sunrpc.h +8 −29
  32. net/sunrpc/svc.c +74 −101
  33. net/sunrpc/svc_xprt.c +3 −5
MAINTAINERS+1−3
@@ -7417,7 +7417,6 @@ F: include/uapi/scsi/fc/ · 7416 unmodified lines
7417 7417
7418FILE LOCKING (flock() and fcntl()/lockf())7418FILE LOCKING (flock() and fcntl()/lockf())
7419M: Jeff Layton <jlayton@kernel.org>7419M: Jeff Layton <jlayton@kernel.org>
7420M: "J. Bruce Fields" <bfields@fieldses.org>
7421L: linux-fsdevel@vger.kernel.org7420L: linux-fsdevel@vger.kernel.org
7422S: Maintained7421S: Maintained
7423F: fs/fcntl.c7422F: fs/fcntl.c
@@ -10428,12 +10427,11 @@ S: Odd Fixes · 3004 unmodified lines
10428W: http://kernelnewbies.org/KernelJanitors10427W: http://kernelnewbies.org/KernelJanitors
10429 10428
10430KERNEL NFSD, SUNRPC, AND LOCKD SERVERS10429KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
10431M: "J. Bruce Fields" <bfields@fieldses.org>
10432M: Chuck Lever <chuck.lever@oracle.com>10430M: Chuck Lever <chuck.lever@oracle.com>
10433L: linux-nfs@vger.kernel.org10431L: linux-nfs@vger.kernel.org
10434S: Supported10432S: Supported
10435W: http://nfs.sourceforge.net/10433W: http://nfs.sourceforge.net/
10436T: git git://linux-nfs.org/~bfields/linux.git10434T: git git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux.git
10437F: fs/lockd/10435F: fs/lockd/
10438F: fs/nfs_common/10436F: fs/nfs_common/
10439F: fs/nfsd/10437F: fs/nfsd/
fs/lockd/svc.c+61−139
@@ -54,13 +54,9 @@ EXPORT_SYMBOL_GPL(nlmsvc_ops); · 53 unmodified lines
54 54
55static DEFINE_MUTEX(nlmsvc_mutex);55static DEFINE_MUTEX(nlmsvc_mutex);
56static unsigned int nlmsvc_users;56static unsigned int nlmsvc_users;
57static struct task_struct *nlmsvc_task;57static struct svc_serv *nlmsvc_serv;
58static struct svc_rqst *nlmsvc_rqst;
59unsigned long nlmsvc_timeout;58unsigned long nlmsvc_timeout;
60 59
61static atomic_t nlm_ntf_refcnt = ATOMIC_INIT(0);
62static DECLARE_WAIT_QUEUE_HEAD(nlm_ntf_wq);
63
64unsigned int lockd_net_id;60unsigned int lockd_net_id;
65 61
66/*62/*
@@ -184,7 +180,12 @@ lockd(void *vrqstp) · 117 unmodified lines
184 nlm_shutdown_hosts();180 nlm_shutdown_hosts();
185 cancel_delayed_work_sync(&ln->grace_period_end);181 cancel_delayed_work_sync(&ln->grace_period_end);
186 locks_end_grace(&ln->lockd_manager);182 locks_end_grace(&ln->lockd_manager);
187 return 0;183
184 dprintk("lockd_down: service stopped\n");
185
186 svc_exit_thread(rqstp);
187
188 module_put_and_exit(0);
188}189}
189 190
190static int create_lockd_listener(struct svc_serv *serv, const char *name,191static int create_lockd_listener(struct svc_serv *serv, const char *name,
@@ -290,8 +291,8 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net) · 99 unmodified lines
290 __func__, net->ns.inum);291 __func__, net->ns.inum);
291 }292 }
292 } else {293 } else {
293 pr_err("%s: no users! task=%p, net=%x\n",294 pr_err("%s: no users! net=%x\n",
294 __func__, nlmsvc_task, net->ns.inum);295 __func__, net->ns.inum);
295 BUG();296 BUG();
296 }297 }
297}298}
@@ -302,20 +303,16 @@ static int lockd_inetaddr_event(struct notifier_block *this, · 4 unmodified lines
302 struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;303 struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
303 struct sockaddr_in sin;304 struct sockaddr_in sin;
304 305
305 if ((event != NETDEV_DOWN) ||306 if (event != NETDEV_DOWN)
306 !atomic_inc_not_zero(&nlm_ntf_refcnt))
307 goto out;307 goto out;
308 308
309 if (nlmsvc_rqst) {309 if (nlmsvc_serv) {
310 dprintk("lockd_inetaddr_event: removed %pI4\n",310 dprintk("lockd_inetaddr_event: removed %pI4\n",
311 &ifa->ifa_local);311 &ifa->ifa_local);
312 sin.sin_family = AF_INET;312 sin.sin_family = AF_INET;
313 sin.sin_addr.s_addr = ifa->ifa_local;313 sin.sin_addr.s_addr = ifa->ifa_local;
314 svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,314 svc_age_temp_xprts_now(nlmsvc_serv, (struct sockaddr *)&sin);
315 (struct sockaddr *)&sin);
316 }315 }
317 atomic_dec(&nlm_ntf_refcnt);
318 wake_up(&nlm_ntf_wq);
319 316
320out:317out:
321 return NOTIFY_DONE;318 return NOTIFY_DONE;
@@ -332,21 +329,17 @@ static int lockd_inet6addr_event(struct notifier_block *this, · 10 unmodified lines
332 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;329 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
333 struct sockaddr_in6 sin6;330 struct sockaddr_in6 sin6;
334 331
335 if ((event != NETDEV_DOWN) ||332 if (event != NETDEV_DOWN)
336 !atomic_inc_not_zero(&nlm_ntf_refcnt))
337 goto out;333 goto out;
338 334
339 if (nlmsvc_rqst) {335 if (nlmsvc_serv) {
340 dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr);336 dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr);
341 sin6.sin6_family = AF_INET6;337 sin6.sin6_family = AF_INET6;
342 sin6.sin6_addr = ifa->addr;338 sin6.sin6_addr = ifa->addr;
343 if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)339 if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
344 sin6.sin6_scope_id = ifa->idev->dev->ifindex;340 sin6.sin6_scope_id = ifa->idev->dev->ifindex;
345 svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,341 svc_age_temp_xprts_now(nlmsvc_serv, (struct sockaddr *)&sin6);
346 (struct sockaddr *)&sin6);
347 }342 }
348 atomic_dec(&nlm_ntf_refcnt);
349 wake_up(&nlm_ntf_wq);
350 343
351out:344out:
352 return NOTIFY_DONE;345 return NOTIFY_DONE;
@@ -357,86 +350,22 @@ static struct notifier_block lockd_inet6addr_notifier = { · 4 unmodified lines
357};350};
358#endif351#endif
359 352
360static void lockd_unregister_notifiers(void)
361{
362 unregister_inetaddr_notifier(&lockd_inetaddr_notifier);
363#if IS_ENABLED(CONFIG_IPV6)
364 unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
365#endif
366 wait_event(nlm_ntf_wq, atomic_read(&nlm_ntf_refcnt) == 0);
367}
368
369static void lockd_svc_exit_thread(void)
370{
371 atomic_dec(&nlm_ntf_refcnt);
372 lockd_unregister_notifiers();
373 svc_exit_thread(nlmsvc_rqst);
374}
375
376static int lockd_start_svc(struct svc_serv *serv)
377{
378 int error;
379
380 if (nlmsvc_rqst)
381 return 0;
382
383 /*
384 * Create the kernel thread and wait for it to start.
385 */
386 nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
387 if (IS_ERR(nlmsvc_rqst)) {
388 error = PTR_ERR(nlmsvc_rqst);
389 printk(KERN_WARNING
390 "lockd_up: svc_rqst allocation failed, error=%d\n",
391 error);
392 lockd_unregister_notifiers();
393 goto out_rqst;
394 }
395
396 atomic_inc(&nlm_ntf_refcnt);
397 svc_sock_update_bufs(serv);
398 serv->sv_maxconn = nlm_max_connections;
399
400 nlmsvc_task = kthread_create(lockd, nlmsvc_rqst, "%s", serv->sv_name);
401 if (IS_ERR(nlmsvc_task)) {
402 error = PTR_ERR(nlmsvc_task);
403 printk(KERN_WARNING
404 "lockd_up: kthread_run failed, error=%d\n", error);
405 goto out_task;
406 }
407 nlmsvc_rqst->rq_task = nlmsvc_task;
408 wake_up_process(nlmsvc_task);
409
410 dprintk("lockd_up: service started\n");
411 return 0;
412
413out_task:
414 lockd_svc_exit_thread();
415 nlmsvc_task = NULL;
416out_rqst:
417 nlmsvc_rqst = NULL;
418 return error;
419}
420
421static const struct svc_serv_ops lockd_sv_ops = {353static const struct svc_serv_ops lockd_sv_ops = {
422 .svo_shutdown = svc_rpcb_cleanup,354 .svo_shutdown = svc_rpcb_cleanup,
355 .svo_function = lockd,
423 .svo_enqueue_xprt = svc_xprt_do_enqueue,356 .svo_enqueue_xprt = svc_xprt_do_enqueue,
357 .svo_module = THIS_MODULE,
424};358};
425 359
426static struct svc_serv *lockd_create_svc(void)360static int lockd_get(void)
427{361{
428 struct svc_serv *serv;362 struct svc_serv *serv;
363 int error;
429 364
430 /*365 if (nlmsvc_serv) {
431 * Check whether we're already up and running.366 svc_get(nlmsvc_serv);
432 */367 nlmsvc_users++;
433 if (nlmsvc_rqst) {368 return 0;
434 /*
435 * Note: increase service usage, because later in case of error
436 * svc_destroy() will be called.
437 */
438 svc_get(nlmsvc_rqst->rq_server);
439 return nlmsvc_rqst->rq_server;
440 }369 }
441 370
442 /*371 /*
@@ -454,14 +383,41 @@ static struct svc_serv *lockd_create_svc(void) · 11 unmodified lines
454 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, &lockd_sv_ops);383 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, &lockd_sv_ops);
455 if (!serv) {384 if (!serv) {
456 printk(KERN_WARNING "lockd_up: create service failed\n");385 printk(KERN_WARNING "lockd_up: create service failed\n");
457 return ERR_PTR(-ENOMEM);386 return -ENOMEM;
458 }387 }
388
389 serv->sv_maxconn = nlm_max_connections;
390 error = svc_set_num_threads(serv, NULL, 1);
391 /* The thread now holds the only reference */
392 svc_put(serv);
393 if (error < 0)
394 return error;
395
396 nlmsvc_serv = serv;
459 register_inetaddr_notifier(&lockd_inetaddr_notifier);397 register_inetaddr_notifier(&lockd_inetaddr_notifier);
460#if IS_ENABLED(CONFIG_IPV6)398#if IS_ENABLED(CONFIG_IPV6)
461 register_inet6addr_notifier(&lockd_inet6addr_notifier);399 register_inet6addr_notifier(&lockd_inet6addr_notifier);
462#endif400#endif
463 dprintk("lockd_up: service created\n");401 dprintk("lockd_up: service created\n");
464 return serv;402 nlmsvc_users++;
403 return 0;
404}
405
406static void lockd_put(void)
407{
408 if (WARN(nlmsvc_users <= 0, "lockd_down: no users!\n"))
409 return;
410 if (--nlmsvc_users)
411 return;
412
413 unregister_inetaddr_notifier(&lockd_inetaddr_notifier);
414#if IS_ENABLED(CONFIG_IPV6)
415 unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
416#endif
417
418 svc_set_num_threads(nlmsvc_serv, NULL, 0);
419 nlmsvc_serv = NULL;
420 dprintk("lockd_down: service destroyed\n");
465}421}
466 422
467/*423/*
@@ -469,36 +425,21 @@ static struct svc_serv *lockd_create_svc(void) · 1 unmodified line
469 */425 */
470int lockd_up(struct net *net, const struct cred *cred)426int lockd_up(struct net *net, const struct cred *cred)
471{427{
472 struct svc_serv *serv;
473 int error;428 int error;
474 429
475 mutex_lock(&nlmsvc_mutex);430 mutex_lock(&nlmsvc_mutex);
476 431
477 serv = lockd_create_svc();432 error = lockd_get();
478 if (IS_ERR(serv)) {433 if (error)
479 error = PTR_ERR(serv);434 goto err;
480 goto err_create;
481 }
482 435
483 error = lockd_up_net(serv, net, cred);436 error = lockd_up_net(nlmsvc_serv, net, cred);
484 if (error < 0) {437 if (error < 0) {
485 lockd_unregister_notifiers();438 lockd_put();
486 goto err_put;439 goto err;
487 }440 }
488 441
489 error = lockd_start_svc(serv);442err:
490 if (error < 0) {
491 lockd_down_net(serv, net);
492 goto err_put;
493 }
494 nlmsvc_users++;
495 /*
496 * Note: svc_serv structures have an initial use count of 1,
497 * so we exit through here on both success and failure.
498 */
499err_put:
500 svc_destroy(serv);
501err_create:
502 mutex_unlock(&nlmsvc_mutex);443 mutex_unlock(&nlmsvc_mutex);
503 return error;444 return error;
504}445}
@@ -511,27 +452,8 @@ void · 6 unmodified lines
511lockd_down(struct net *net)452lockd_down(struct net *net)
512{453{
513 mutex_lock(&nlmsvc_mutex);454 mutex_lock(&nlmsvc_mutex);
514 lockd_down_net(nlmsvc_rqst->rq_server, net);455 lockd_down_net(nlmsvc_serv, net);
515 if (nlmsvc_users) {456 lockd_put();
516 if (--nlmsvc_users)
517 goto out;
518 } else {
519 printk(KERN_ERR "lockd_down: no users! task=%p\n",
520 nlmsvc_task);
521 BUG();
522 }
523
524 if (!nlmsvc_task) {
525 printk(KERN_ERR "lockd_down: no lockd running.\n");
526 BUG();
527 }
528 kthread_stop(nlmsvc_task);
529 dprintk("lockd_down: service stopped\n");
530 lockd_svc_exit_thread();
531 dprintk("lockd_down: service destroyed\n");
532 nlmsvc_task = NULL;
533 nlmsvc_rqst = NULL;
534out:
535 mutex_unlock(&nlmsvc_mutex);457 mutex_unlock(&nlmsvc_mutex);
536}458}
537EXPORT_SYMBOL_GPL(lockd_down);459EXPORT_SYMBOL_GPL(lockd_down);
fs/lockd/svclock.c+4−2
@@ -470,8 +470,10 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, · 469 unmodified lines
470 struct nlm_host *host, struct nlm_lock *lock, int wait,470 struct nlm_host *host, struct nlm_lock *lock, int wait,
471 struct nlm_cookie *cookie, int reclaim)471 struct nlm_cookie *cookie, int reclaim)
472{472{
473 struct nlm_block *block = NULL;473#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
474 struct inode *inode = nlmsvc_file_inode(file);474 struct inode *inode = nlmsvc_file_inode(file);
475#endif
476 struct nlm_block *block = NULL;
475 int error;477 int error;
476 int mode;478 int mode;
477 int async_block = 0;479 int async_block = 0;
@@ -484,7 +486,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, · 6 unmodified lines
484 (long long)lock->fl.fl_end,486 (long long)lock->fl.fl_end,
485 wait);487 wait);
486 488
487 if (inode->i_sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS) {489 if (nlmsvc_file_file(file)->f_op->lock) {
488 async_block = wait;490 async_block = wait;
489 wait = 0;491 wait = 0;
490 }492 }
fs/nfs/callback.c+9−23
@@ -169,12 +169,12 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, · 168 unmodified lines
169 if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS)169 if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS)
170 nrservs = NFS4_MIN_NR_CALLBACK_THREADS;170 nrservs = NFS4_MIN_NR_CALLBACK_THREADS;
171 171
172 if (serv->sv_nrthreads-1 == nrservs)172 if (serv->sv_nrthreads == nrservs)
173 return 0;173 return 0;
174 174
175 ret = serv->sv_ops->svo_setup(serv, NULL, nrservs);175 ret = svc_set_num_threads(serv, NULL, nrservs);
176 if (ret) {176 if (ret) {
177 serv->sv_ops->svo_setup(serv, NULL, 0);177 svc_set_num_threads(serv, NULL, 0);
178 return ret;178 return ret;
179 }179 }
180 dprintk("nfs_callback_up: service started\n");180 dprintk("nfs_callback_up: service started\n");
@@ -235,14 +235,12 @@ err_bind: · 54 unmodified lines
235static const struct svc_serv_ops nfs40_cb_sv_ops = {235static const struct svc_serv_ops nfs40_cb_sv_ops = {
236 .svo_function = nfs4_callback_svc,236 .svo_function = nfs4_callback_svc,
237 .svo_enqueue_xprt = svc_xprt_do_enqueue,237 .svo_enqueue_xprt = svc_xprt_do_enqueue,
238 .svo_setup = svc_set_num_threads_sync,
239 .svo_module = THIS_MODULE,238 .svo_module = THIS_MODULE,
240};239};
241#if defined(CONFIG_NFS_V4_1)240#if defined(CONFIG_NFS_V4_1)
242static const struct svc_serv_ops nfs41_cb_sv_ops = {241static const struct svc_serv_ops nfs41_cb_sv_ops = {
243 .svo_function = nfs41_callback_svc,242 .svo_function = nfs41_callback_svc,
244 .svo_enqueue_xprt = svc_xprt_do_enqueue,243 .svo_enqueue_xprt = svc_xprt_do_enqueue,
245 .svo_setup = svc_set_num_threads_sync,
246 .svo_module = THIS_MODULE,244 .svo_module = THIS_MODULE,
247};245};
248 246
@@ -266,14 +264,8 @@ static struct svc_serv *nfs_callback_create_svc(int minorversion) · 17 unmodified lines
266 /*264 /*
267 * Check whether we're already up and running.265 * Check whether we're already up and running.
268 */266 */
269 if (cb_info->serv) {267 if (cb_info->serv)
270 /*268 return svc_get(cb_info->serv);
271 * Note: increase service usage, because later in case of error
272 * svc_destroy() will be called.
273 */
274 svc_get(cb_info->serv);
275 return cb_info->serv;
276 }
277 269
278 switch (minorversion) {270 switch (minorversion) {
279 case 0:271 case 0:
@@ -294,7 +286,7 @@ static struct svc_serv *nfs_callback_create_svc(int minorversion) · 14 unmodified lines
294 printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",286 printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
295 cb_info->users);287 cb_info->users);
296 288
297 serv = svc_create_pooled(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);289 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);
298 if (!serv) {290 if (!serv) {
299 printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");291 printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
300 return ERR_PTR(-ENOMEM);292 return ERR_PTR(-ENOMEM);
@@ -335,16 +327,10 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) · 34 unmodified lines
335 goto err_start;327 goto err_start;
336 328
337 cb_info->users++;329 cb_info->users++;
338 /*
339 * svc_create creates the svc_serv with sv_nrthreads == 1, and then
340 * svc_prepare_thread increments that. So we need to call svc_destroy
341 * on both success and failure so that the refcount is 1 when the
342 * thread exits.
343 */
344err_net:330err_net:
345 if (!cb_info->users)331 if (!cb_info->users)
346 cb_info->serv = NULL;332 cb_info->serv = NULL;
347 svc_destroy(serv);333 svc_put(serv);
348err_create:334err_create:
349 mutex_unlock(&nfs_callback_mutex);335 mutex_unlock(&nfs_callback_mutex);
350 return ret;336 return ret;
@@ -369,8 +355,8 @@ void nfs_callback_down(int minorversion, struct net *net) · 18 unmodified lines
369 cb_info->users--;355 cb_info->users--;
370 if (cb_info->users == 0) {356 if (cb_info->users == 0) {
371 svc_get(serv);357 svc_get(serv);
372 serv->sv_ops->svo_setup(serv, NULL, 0);358 svc_set_num_threads(serv, NULL, 0);
373 svc_destroy(serv);359 svc_put(serv);
374 dprintk("nfs_callback_down: service destroyed\n");360 dprintk("nfs_callback_down: service destroyed\n");
375 cb_info->serv = NULL;361 cb_info->serv = NULL;
376 }362 }
fs/nfs/export.c+1−1
@@ -158,5 +158,5 @@ const struct export_operations nfs_export_ops = { · 157 unmodified lines
158 .fetch_iversion = nfs_fetch_iversion,158 .fetch_iversion = nfs_fetch_iversion,
159 .flags = EXPORT_OP_NOWCC|EXPORT_OP_NOSUBTREECHK|159 .flags = EXPORT_OP_NOWCC|EXPORT_OP_NOSUBTREECHK|
160 EXPORT_OP_CLOSE_BEFORE_UNLINK|EXPORT_OP_REMOTE_FS|160 EXPORT_OP_CLOSE_BEFORE_UNLINK|EXPORT_OP_REMOTE_FS|
161 EXPORT_OP_NOATOMIC_ATTR|EXPORT_OP_SYNC_LOCKS,161 EXPORT_OP_NOATOMIC_ATTR,
162};162};
fs/nfsd/filecache.c+16−63
@@ -44,12 +44,9 @@ struct nfsd_fcache_bucket { · 43 unmodified lines
44static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits);44static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits);
45 45
46struct nfsd_fcache_disposal {46struct nfsd_fcache_disposal {
47 struct list_head list;
48 struct work_struct work;47 struct work_struct work;
49 struct net *net;
50 spinlock_t lock;48 spinlock_t lock;
51 struct list_head freeme;49 struct list_head freeme;
52 struct rcu_head rcu;
53};50};
54 51
55static struct workqueue_struct *nfsd_filecache_wq __read_mostly;52static struct workqueue_struct *nfsd_filecache_wq __read_mostly;
@@ -62,8 +59,6 @@ static long nfsd_file_lru_flags; · 6 unmodified lines
62static struct fsnotify_group *nfsd_file_fsnotify_group;59static struct fsnotify_group *nfsd_file_fsnotify_group;
63static atomic_long_t nfsd_filecache_count;60static atomic_long_t nfsd_filecache_count;
64static struct delayed_work nfsd_filecache_laundrette;61static struct delayed_work nfsd_filecache_laundrette;
65static DEFINE_SPINLOCK(laundrette_lock);
66static LIST_HEAD(laundrettes);
67 62
68static void nfsd_file_gc(void);63static void nfsd_file_gc(void);
69 64
@@ -194,7 +189,6 @@ nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval, · 124 unmodified lines
194 __set_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags);189 __set_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags);
195 }190 }
196 nf->nf_mark = NULL;191 nf->nf_mark = NULL;
197 init_rwsem(&nf->nf_rwsem);
198 trace_nfsd_file_alloc(nf);192 trace_nfsd_file_alloc(nf);
199 }193 }
200 return nf;194 return nf;
@@ -249,7 +243,7 @@ nfsd_file_do_unhash(struct nfsd_file *nf) · 48 unmodified lines
249 trace_nfsd_file_unhash(nf);243 trace_nfsd_file_unhash(nf);
250 244
251 if (nfsd_file_check_write_error(nf))245 if (nfsd_file_check_write_error(nf))
252 nfsd_reset_boot_verifier(net_generic(nf->nf_net, nfsd_net_id));246 nfsd_reset_write_verifier(net_generic(nf->nf_net, nfsd_net_id));
253 --nfsd_file_hashtbl[nf->nf_hashval].nfb_count;247 --nfsd_file_hashtbl[nf->nf_hashval].nfb_count;
254 hlist_del_rcu(&nf->nf_node);248 hlist_del_rcu(&nf->nf_node);
255 atomic_long_dec(&nfsd_filecache_count);249 atomic_long_dec(&nfsd_filecache_count);
@@ -367,19 +361,13 @@ nfsd_file_list_remove_disposal(struct list_head *dst, · 111 unmodified lines
367static void361static void
368nfsd_file_list_add_disposal(struct list_head *files, struct net *net)362nfsd_file_list_add_disposal(struct list_head *files, struct net *net)
369{363{
370 struct nfsd_fcache_disposal *l;364 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
365 struct nfsd_fcache_disposal *l = nn->fcache_disposal;
371 366
372 rcu_read_lock();367 spin_lock(&l->lock);
373 list_for_each_entry_rcu(l, &laundrettes, list) {368 list_splice_tail_init(files, &l->freeme);
374 if (l->net == net) {369 spin_unlock(&l->lock);
375 spin_lock(&l->lock);370 queue_work(nfsd_filecache_wq, &l->work);
376 list_splice_tail_init(files, &l->freeme);
377 spin_unlock(&l->lock);
378 queue_work(nfsd_filecache_wq, &l->work);
379 break;
380 }
381 }
382 rcu_read_unlock();
383}371}
384 372
385static void373static void
@@ -755,7 +743,7 @@ nfsd_file_cache_purge(struct net *net) · 369 unmodified lines
755}743}
756 744
757static struct nfsd_fcache_disposal *745static struct nfsd_fcache_disposal *
758nfsd_alloc_fcache_disposal(struct net *net)746nfsd_alloc_fcache_disposal(void)
759{747{
760 struct nfsd_fcache_disposal *l;748 struct nfsd_fcache_disposal *l;
761 749
@@ -763,7 +751,6 @@ nfsd_alloc_fcache_disposal(struct net *net) · 1 unmodified line
763 if (!l)751 if (!l)
764 return NULL;752 return NULL;
765 INIT_WORK(&l->work, nfsd_file_delayed_close);753 INIT_WORK(&l->work, nfsd_file_delayed_close);
766 l->net = net;
767 spin_lock_init(&l->lock);754 spin_lock_init(&l->lock);
768 INIT_LIST_HEAD(&l->freeme);755 INIT_LIST_HEAD(&l->freeme);
769 return l;756 return l;
@@ -772,61 +759,27 @@ nfsd_alloc_fcache_disposal(struct net *net) · 2 unmodified lines
772static void759static void
773nfsd_free_fcache_disposal(struct nfsd_fcache_disposal *l)760nfsd_free_fcache_disposal(struct nfsd_fcache_disposal *l)
774{761{
775 rcu_assign_pointer(l->net, NULL);
776 cancel_work_sync(&l->work);762 cancel_work_sync(&l->work);
777 nfsd_file_dispose_list(&l->freeme);763 nfsd_file_dispose_list(&l->freeme);
778 kfree_rcu(l, rcu);764 kfree(l);
779}
780
781static void
782nfsd_add_fcache_disposal(struct nfsd_fcache_disposal *l)
783{
784 spin_lock(&laundrette_lock);
785 list_add_tail_rcu(&l->list, &laundrettes);
786 spin_unlock(&laundrette_lock);
787}
788
789static void
790nfsd_del_fcache_disposal(struct nfsd_fcache_disposal *l)
791{
792 spin_lock(&laundrette_lock);
793 list_del_rcu(&l->list);
794 spin_unlock(&laundrette_lock);
795}
796
797static int
798nfsd_alloc_fcache_disposal_net(struct net *net)
799{
800 struct nfsd_fcache_disposal *l;
801
802 l = nfsd_alloc_fcache_disposal(net);
803 if (!l)
804 return -ENOMEM;
805 nfsd_add_fcache_disposal(l);
806 return 0;
807}765}
808 766
809static void767static void
810nfsd_free_fcache_disposal_net(struct net *net)768nfsd_free_fcache_disposal_net(struct net *net)
811{769{
812 struct nfsd_fcache_disposal *l;770 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
771 struct nfsd_fcache_disposal *l = nn->fcache_disposal;
813 772
814 rcu_read_lock();773 nfsd_free_fcache_disposal(l);
815 list_for_each_entry_rcu(l, &laundrettes, list) {
816 if (l->net != net)
817 continue;
818 nfsd_del_fcache_disposal(l);
819 rcu_read_unlock();
820 nfsd_free_fcache_disposal(l);
821 return;
822 }
823 rcu_read_unlock();
824}774}
825 775
826int776int
827nfsd_file_cache_start_net(struct net *net)777nfsd_file_cache_start_net(struct net *net)
828{778{
829 return nfsd_alloc_fcache_disposal_net(net);779 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
780
781 nn->fcache_disposal = nfsd_alloc_fcache_disposal();
782 return nn->fcache_disposal ? 0 : -ENOMEM;
830}783}
831 784
832void785void
fs/nfsd/filecache.h+0−1
@@ -46,7 +46,6 @@ struct nfsd_file { · 45 unmodified lines
46 refcount_t nf_ref;46 refcount_t nf_ref;
47 unsigned char nf_may;47 unsigned char nf_may;
48 struct nfsd_file_mark *nf_mark;48 struct nfsd_file_mark *nf_mark;
49 struct rw_semaphore nf_rwsem;
50};49};
51 50
52int nfsd_file_cache_init(void);51int nfsd_file_cache_init(void);
fs/nfsd/netns.h+16−11
@@ -11,6 +11,7 @@ · 10 unmodified lines
11#include <net/net_namespace.h>11#include <net/net_namespace.h>
12#include <net/netns/generic.h>12#include <net/netns/generic.h>
13#include <linux/percpu_counter.h>13#include <linux/percpu_counter.h>
14#include <linux/siphash.h>
14 15
15/* Hash tables for nfs4_clientid state */16/* Hash tables for nfs4_clientid state */
16#define CLIENT_HASH_BITS 417#define CLIENT_HASH_BITS 4
@@ -108,9 +109,8 @@ struct nfsd_net { · 91 unmodified lines
108 bool nfsd_net_up;109 bool nfsd_net_up;
109 bool lockd_up;110 bool lockd_up;
110 111
111 /* Time of server startup */112 seqlock_t writeverf_lock;
112 struct timespec64 nfssvc_boot;113 unsigned char writeverf[8];
113 seqlock_t boot_lock;
114 114
115 /*115 /*
116 * Max number of connections this nfsd container will allow. Defaults116 * Max number of connections this nfsd container will allow. Defaults
@@ -123,12 +123,13 @@ struct nfsd_net { · 6 unmodified lines
123 u32 clverifier_counter;123 u32 clverifier_counter;
124 124
125 struct svc_serv *nfsd_serv;125 struct svc_serv *nfsd_serv;
126 126 /* When a listening socket is added to nfsd, keep_active is set
127 wait_queue_head_t ntf_wq;127 * and this justifies a reference on nfsd_serv. This stops
128 atomic_t ntf_refcnt;128 * nfsd_serv from being freed. When the number of threads is
129 129 * set, keep_active is cleared and the reference is dropped. So
130 /* Allow umount to wait for nfsd state cleanup */130 * when the last thread exits, the service will be destroyed.
131 struct completion nfsd_shutdown_complete;131 */
132 int keep_active;
132 133
133 /*134 /*
134 * clientid and stateid data for construction of net unique COPY135 * clientid and stateid data for construction of net unique COPY
@@ -184,6 +185,10 @@ struct nfsd_net { · 49 unmodified lines
184 185
185 /* utsname taken from the process that starts the server */186 /* utsname taken from the process that starts the server */
186 char nfsd_name[UNX_MAXNODENAME+1];187 char nfsd_name[UNX_MAXNODENAME+1];
188
189 struct nfsd_fcache_disposal *fcache_disposal;
190
191 siphash_key_t siphash_key;
187};192};
188 193
189/* Simple check to find out if a given net was properly initialized */194/* Simple check to find out if a given net was properly initialized */
@@ -193,6 +198,6 @@ extern void nfsd_netns_free_versions(struct nfsd_net *nn); · 3 unmodified lines
193 198
194extern unsigned int nfsd_net_id;199extern unsigned int nfsd_net_id;
195 200
196void nfsd_copy_boot_verifier(__be32 verf[2], struct nfsd_net *nn);201void nfsd_copy_write_verifier(__be32 verf[2], struct nfsd_net *nn);
197void nfsd_reset_boot_verifier(struct nfsd_net *nn);202void nfsd_reset_write_verifier(struct nfsd_net *nn);
198#endif /* __NFSD_NETNS_H__ */203#endif /* __NFSD_NETNS_H__ */
fs/nfsd/nfs3proc.c+1−5
@@ -202,15 +202,11 @@ nfsd3_proc_write(struct svc_rqst *rqstp) · 201 unmodified lines
202 fh_copy(&resp->fh, &argp->fh);202 fh_copy(&resp->fh, &argp->fh);
203 resp->committed = argp->stable;203 resp->committed = argp->stable;
204 nvecs = svc_fill_write_vector(rqstp, &argp->payload);204 nvecs = svc_fill_write_vector(rqstp, &argp->payload);
205 if (!nvecs) {205
206 resp->status = nfserr_io;
207 goto out;
208 }
209 resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,206 resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
210 rqstp->rq_vec, nvecs, &cnt,207 rqstp->rq_vec, nvecs, &cnt,
211 resp->committed, resp->verf);208 resp->committed, resp->verf);
212 resp->count = cnt;209 resp->count = cnt;
213out:
214 return rpc_success;210 return rpc_success;
215}211}
216 212
fs/nfsd/nfs3xdr.c+0−65
@@ -487,71 +487,6 @@ neither: · 486 unmodified lines
487 return true;487 return true;
488}488}
489 489
490static bool fs_supports_change_attribute(struct super_block *sb)
491{
492 return sb->s_flags & SB_I_VERSION || sb->s_export_op->fetch_iversion;
493}
494
495/*
496 * Fill in the pre_op attr for the wcc data
497 */
498void fill_pre_wcc(struct svc_fh *fhp)
499{
500 struct inode *inode;
501 struct kstat stat;
502 bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE);
503
504 if (fhp->fh_no_wcc || fhp->fh_pre_saved)
505 return;
506 inode = d_inode(fhp->fh_dentry);
507 if (fs_supports_change_attribute(inode->i_sb) || !v4) {
508 __be32 err = fh_getattr(fhp, &stat);
509
510 if (err) {
511 /* Grab the times from inode anyway */
512 stat.mtime = inode->i_mtime;
513 stat.ctime = inode->i_ctime;
514 stat.size = inode->i_size;
515 }
516 fhp->fh_pre_mtime = stat.mtime;
517 fhp->fh_pre_ctime = stat.ctime;
518 fhp->fh_pre_size = stat.size;
519 }
520 if (v4)
521 fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode);
522
523 fhp->fh_pre_saved = true;
524}
525
526/*
527 * Fill in the post_op attr for the wcc data
528 */
529void fill_post_wcc(struct svc_fh *fhp)
530{
531 bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE);
532 struct inode *inode = d_inode(fhp->fh_dentry);
533
534 if (fhp->fh_no_wcc)
535 return;
536
537 if (fhp->fh_post_saved)
538 printk("nfsd: inode locked twice during operation.\n");
539
540 fhp->fh_post_saved = true;
541
542 if (fs_supports_change_attribute(inode->i_sb) || !v4) {
543 __be32 err = fh_getattr(fhp, &fhp->fh_post_attr);
544
545 if (err) {
546 fhp->fh_post_saved = false;
547 fhp->fh_post_attr.ctime = inode->i_ctime;
548 }
549 }
550 if (v4)
551 fhp->fh_post_change =
552 nfsd4_change_attribute(&fhp->fh_post_attr, inode);
553}
554
555/*490/*
556 * XDR decode functions491 * XDR decode functions
557 */492 */
fs/nfsd/nfs4proc.c+13−11
@@ -598,7 +598,7 @@ static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net) · 597 unmodified lines
598 598
599 BUILD_BUG_ON(2*sizeof(*verf) != sizeof(verifier->data));599 BUILD_BUG_ON(2*sizeof(*verf) != sizeof(verifier->data));
600 600
601 nfsd_copy_boot_verifier(verf, net_generic(net, nfsd_net_id));601 nfsd_copy_write_verifier(verf, net_generic(net, nfsd_net_id));
602}602}
603 603
604static __be32604static __be32
@@ -1101,7 +1101,7 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 496 unmodified lines
1101 if (status)1101 if (status)
1102 goto out;1102 goto out;
1103 1103
1104 status = nfsd4_clone_file_range(src, clone->cl_src_pos,1104 status = nfsd4_clone_file_range(rqstp, src, clone->cl_src_pos,
1105 dst, clone->cl_dst_pos, clone->cl_count,1105 dst, clone->cl_dst_pos, clone->cl_count,
1106 EX_ISSYNC(cstate->current_fh.fh_export));1106 EX_ISSYNC(cstate->current_fh.fh_export));
1107 1107
@@ -1510,11 +1510,14 @@ static void nfsd4_init_copy_res(struct nfsd4_copy *copy, bool sync) · 402 unmodified lines
1510 1510
1511static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy)1511static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy)
1512{1512{
1513 struct file *dst = copy->nf_dst->nf_file;
1514 struct file *src = copy->nf_src->nf_file;
1515 errseq_t since;
1513 ssize_t bytes_copied = 0;1516 ssize_t bytes_copied = 0;
1514 u64 bytes_total = copy->cp_count;1517 u64 bytes_total = copy->cp_count;
1515 u64 src_pos = copy->cp_src_pos;1518 u64 src_pos = copy->cp_src_pos;
1516 u64 dst_pos = copy->cp_dst_pos;1519 u64 dst_pos = copy->cp_dst_pos;
1517 __be32 status;1520 int status;
1518 1521
1519 /* See RFC 7862 p.67: */1522 /* See RFC 7862 p.67: */
1520 if (bytes_total == 0)1523 if (bytes_total == 0)
@@ -1522,9 +1525,8 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy) · 1 unmodified line
1522 do {1525 do {
1523 if (kthread_should_stop())1526 if (kthread_should_stop())
1524 break;1527 break;
1525 bytes_copied = nfsd_copy_file_range(copy->nf_src->nf_file,1528 bytes_copied = nfsd_copy_file_range(src, src_pos, dst, dst_pos,
1526 src_pos, copy->nf_dst->nf_file, dst_pos,1529 bytes_total);
1527 bytes_total);
1528 if (bytes_copied <= 0)1530 if (bytes_copied <= 0)
1529 break;1531 break;
1530 bytes_total -= bytes_copied;1532 bytes_total -= bytes_copied;
@@ -1534,11 +1536,11 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy) · 3 unmodified lines
1534 } while (bytes_total > 0 && !copy->cp_synchronous);1536 } while (bytes_total > 0 && !copy->cp_synchronous);
1535 /* for a non-zero asynchronous copy do a commit of data */1537 /* for a non-zero asynchronous copy do a commit of data */
1536 if (!copy->cp_synchronous && copy->cp_res.wr_bytes_written > 0) {1538 if (!copy->cp_synchronous && copy->cp_res.wr_bytes_written > 0) {
1537 down_write(&copy->nf_dst->nf_rwsem);1539 since = READ_ONCE(dst->f_wb_err);
1538 status = vfs_fsync_range(copy->nf_dst->nf_file,1540 status = vfs_fsync_range(dst, copy->cp_dst_pos,
1539 copy->cp_dst_pos,
1540 copy->cp_res.wr_bytes_written, 0);1541 copy->cp_res.wr_bytes_written, 0);
1541 up_write(&copy->nf_dst->nf_rwsem);1542 if (!status)
1543 status = filemap_check_wb_err(dst->f_mapping, since);
1542 if (!status)1544 if (!status)
1543 copy->committed = true;1545 copy->committed = true;
1544 }1546 }
@@ -2528,7 +2530,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) · 983 unmodified lines
2528 goto encode_op;2530 goto encode_op;
2529 }2531 }
2530 2532
2531 fh_clear_wcc(current_fh);2533 fh_clear_pre_post_attrs(current_fh);
2532 2534
2533 /* If op is non-idempotent */2535 /* If op is non-idempotent */
2534 if (op->opdesc->op_flags & OP_MODIFIES_SOMETHING) {2536 if (op->opdesc->op_flags & OP_MODIFIES_SOMETHING) {
fs/nfsd/nfs4state.c+49−14
@@ -246,6 +246,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh, · 245 unmodified lines
246 list_for_each_entry(cur, &lo->lo_blocked, nbl_list) {246 list_for_each_entry(cur, &lo->lo_blocked, nbl_list) {
247 if (fh_match(fh, &cur->nbl_fh)) {247 if (fh_match(fh, &cur->nbl_fh)) {
248 list_del_init(&cur->nbl_list);248 list_del_init(&cur->nbl_list);
249 WARN_ON(list_empty(&cur->nbl_lru));
249 list_del_init(&cur->nbl_lru);250 list_del_init(&cur->nbl_lru);
250 found = cur;251 found = cur;
251 break;252 break;
@@ -271,6 +272,7 @@ find_or_allocate_block(struct nfs4_lockowner *lo, struct knfsd_fh *fh, · 19 unmodified lines
271 INIT_LIST_HEAD(&nbl->nbl_lru);272 INIT_LIST_HEAD(&nbl->nbl_lru);
272 fh_copy_shallow(&nbl->nbl_fh, fh);273 fh_copy_shallow(&nbl->nbl_fh, fh);
273 locks_init_lock(&nbl->nbl_lock);274 locks_init_lock(&nbl->nbl_lock);
275 kref_init(&nbl->nbl_kref);
274 nfsd4_init_cb(&nbl->nbl_cb, lo->lo_owner.so_client,276 nfsd4_init_cb(&nbl->nbl_cb, lo->lo_owner.so_client,
275 &nfsd4_cb_notify_lock_ops,277 &nfsd4_cb_notify_lock_ops,
276 NFSPROC4_CLNT_CB_NOTIFY_LOCK);278 NFSPROC4_CLNT_CB_NOTIFY_LOCK);
@@ -279,12 +281,21 @@ find_or_allocate_block(struct nfs4_lockowner *lo, struct knfsd_fh *fh, · 2 unmodified lines
279 return nbl;281 return nbl;
280}282}
281 283
284static void
285free_nbl(struct kref *kref)
286{
287 struct nfsd4_blocked_lock *nbl;
288
289 nbl = container_of(kref, struct nfsd4_blocked_lock, nbl_kref);
290 kfree(nbl);
291}
292
282static void293static void
283free_blocked_lock(struct nfsd4_blocked_lock *nbl)294free_blocked_lock(struct nfsd4_blocked_lock *nbl)
284{295{
285 locks_delete_block(&nbl->nbl_lock);296 locks_delete_block(&nbl->nbl_lock);
286 locks_release_private(&nbl->nbl_lock);297 locks_release_private(&nbl->nbl_lock);
287 kfree(nbl);298 kref_put(&nbl->nbl_kref, free_nbl);
288}299}
289 300
290static void301static void
@@ -302,6 +313,7 @@ remove_blocked_locks(struct nfs4_lockowner *lo) · 11 unmodified lines
302 struct nfsd4_blocked_lock,313 struct nfsd4_blocked_lock,
303 nbl_list);314 nbl_list);
304 list_del_init(&nbl->nbl_list);315 list_del_init(&nbl->nbl_list);
316 WARN_ON(list_empty(&nbl->nbl_lru));
305 list_move(&nbl->nbl_lru, &reaplist);317 list_move(&nbl->nbl_lru, &reaplist);
306 }318 }
307 spin_unlock(&nn->blocked_locks_lock);319 spin_unlock(&nn->blocked_locks_lock);
@@ -360,11 +372,13 @@ static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops = { · 52 unmodified lines
360 * st_{access,deny}_bmap field of the stateid, in order to track not372 * st_{access,deny}_bmap field of the stateid, in order to track not
361 * only what share bits are currently in force, but also what373 * only what share bits are currently in force, but also what
362 * combinations of share bits previous opens have used. This allows us374 * combinations of share bits previous opens have used. This allows us
363 * to enforce the recommendation of rfc 3530 14.2.19 that the server375 * to enforce the recommendation in
364 * return an error if the client attempt to downgrade to a combination376 * https://datatracker.ietf.org/doc/html/rfc7530#section-16.19.4 that
365 * of share bits not explicable by closing some of its previous opens.377 * the server return an error if the client attempt to downgrade to a
378 * combination of share bits not explicable by closing some of its
379 * previous opens.
366 *380 *
367 * XXX: This enforcement is actually incomplete, since we don't keep381 * This enforcement is arguably incomplete, since we don't keep
368 * track of access/deny bit combinations; so, e.g., we allow:382 * track of access/deny bit combinations; so, e.g., we allow:
369 *383 *
370 * OPEN allow read, deny write384 * OPEN allow read, deny write
@@ -372,6 +386,10 @@ static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops = { · 1 unmodified line
372 * DOWNGRADE allow read, deny none386 * DOWNGRADE allow read, deny none
373 *387 *
374 * which we should reject.388 * which we should reject.
389 *
390 * But you could also argue that our current code is already overkill,
391 * since it only exists to return NFS4ERR_INVAL on incorrect client
392 * behavior.
375 */393 */
376static unsigned int394static unsigned int
377bmap_to_share_mode(unsigned long bmap)395bmap_to_share_mode(unsigned long bmap)
@@ -6040,7 +6058,11 @@ nfs4_preprocess_stateid_op(struct svc_rqst *rqstp, · 5662 unmodified lines
6040 *nfp = NULL;6058 *nfp = NULL;
6041 6059
6042 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {6060 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
6043 status = check_special_stateids(net, fhp, stateid, flags);6061 if (cstid)
6062 status = nfserr_bad_stateid;
6063 else
6064 status = check_special_stateids(net, fhp, stateid,
6065 flags);
6044 goto done;6066 goto done;
6045 }6067 }
6046 6068
@@ -6836,7 +6858,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 789 unmodified lines
6836 struct nfsd4_blocked_lock *nbl = NULL;6858 struct nfsd4_blocked_lock *nbl = NULL;
6837 struct file_lock *file_lock = NULL;6859 struct file_lock *file_lock = NULL;
6838 struct file_lock *conflock = NULL;6860 struct file_lock *conflock = NULL;
6839 struct super_block *sb;
6840 __be32 status = 0;6861 __be32 status = 0;
6841 int lkflg;6862 int lkflg;
6842 int err;6863 int err;
@@ -6858,7 +6879,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 15 unmodified lines
6858 dprintk("NFSD: nfsd4_lock: permission denied!\n");6879 dprintk("NFSD: nfsd4_lock: permission denied!\n");
6859 return status;6880 return status;
6860 }6881 }
6861 sb = cstate->current_fh.fh_dentry->d_sb;
6862 6882
6863 if (lock->lk_is_new) {6883 if (lock->lk_is_new) {
6864 if (nfsd4_has_session(cstate))6884 if (nfsd4_has_session(cstate))
@@ -6910,8 +6930,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 45 unmodified lines
6910 fp = lock_stp->st_stid.sc_file;6930 fp = lock_stp->st_stid.sc_file;
6911 switch (lock->lk_type) {6931 switch (lock->lk_type) {
6912 case NFS4_READW_LT:6932 case NFS4_READW_LT:
6913 if (nfsd4_has_session(cstate) &&6933 if (nfsd4_has_session(cstate))
6914 !(sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS))
6915 fl_flags |= FL_SLEEP;6934 fl_flags |= FL_SLEEP;
6916 fallthrough;6935 fallthrough;
6917 case NFS4_READ_LT:6936 case NFS4_READ_LT:
@@ -6923,8 +6942,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 5 unmodified lines
6923 fl_type = F_RDLCK;6942 fl_type = F_RDLCK;
6924 break;6943 break;
6925 case NFS4_WRITEW_LT:6944 case NFS4_WRITEW_LT:
6926 if (nfsd4_has_session(cstate) &&6945 if (nfsd4_has_session(cstate))
6927 !(sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS))
6928 fl_flags |= FL_SLEEP;6946 fl_flags |= FL_SLEEP;
6929 fallthrough;6947 fallthrough;
6930 case NFS4_WRITE_LT:6948 case NFS4_WRITE_LT:
@@ -6945,6 +6963,16 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 14 unmodified lines
6945 goto out;6963 goto out;
6946 }6964 }
6947 6965
6966 /*
6967 * Most filesystems with their own ->lock operations will block
6968 * the nfsd thread waiting to acquire the lock. That leads to
6969 * deadlocks (we don't want every nfsd thread tied up waiting
6970 * for file locks), so don't attempt blocking lock notifications
6971 * on those filesystems:
6972 */
6973 if (nf->nf_file->f_op->lock)
6974 fl_flags &= ~FL_SLEEP;
6975
6948 nbl = find_or_allocate_block(lock_sop, &fp->fi_fhandle, nn);6976 nbl = find_or_allocate_block(lock_sop, &fp->fi_fhandle, nn);
6949 if (!nbl) {6977 if (!nbl) {
6950 dprintk("NFSD: %s: unable to allocate block!\n", __func__);6978 dprintk("NFSD: %s: unable to allocate block!\n", __func__);
@@ -6975,6 +7003,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 24 unmodified lines
6975 spin_lock(&nn->blocked_locks_lock);7003 spin_lock(&nn->blocked_locks_lock);
6976 list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked);7004 list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked);
6977 list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru);7005 list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru);
7006 kref_get(&nbl->nbl_kref);
6978 spin_unlock(&nn->blocked_locks_lock);7007 spin_unlock(&nn->blocked_locks_lock);
6979 }7008 }
6980 7009
@@ -6987,6 +7016,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 6 unmodified lines
6987 nn->somebody_reclaimed = true;7016 nn->somebody_reclaimed = true;
6988 break;7017 break;
6989 case FILE_LOCK_DEFERRED:7018 case FILE_LOCK_DEFERRED:
7019 kref_put(&nbl->nbl_kref, free_nbl);
6990 nbl = NULL;7020 nbl = NULL;
6991 fallthrough;7021 fallthrough;
6992 case -EAGAIN: /* conflock holds conflicting lock */7022 case -EAGAIN: /* conflock holds conflicting lock */
@@ -7007,8 +7037,13 @@ out: · 14 unmodified lines
7007 /* dequeue it if we queued it before */7037 /* dequeue it if we queued it before */
7008 if (fl_flags & FL_SLEEP) {7038 if (fl_flags & FL_SLEEP) {
7009 spin_lock(&nn->blocked_locks_lock);7039 spin_lock(&nn->blocked_locks_lock);
7010 list_del_init(&nbl->nbl_list);7040 if (!list_empty(&nbl->nbl_list) &&
7011 list_del_init(&nbl->nbl_lru);7041 !list_empty(&nbl->nbl_lru)) {
7042 list_del_init(&nbl->nbl_list);
7043 list_del_init(&nbl->nbl_lru);
7044 kref_put(&nbl->nbl_kref, free_nbl);
7045 }
7046 /* nbl can use one of lists to be linked to reaplist */
7012 spin_unlock(&nn->blocked_locks_lock);7047 spin_unlock(&nn->blocked_locks_lock);
7013 }7048 }
7014 free_blocked_lock(nbl);7049 free_blocked_lock(nbl);
fs/nfsd/nfs4xdr.c+5−16
@@ -277,21 +277,10 @@ nfsd4_decode_verifier4(struct nfsd4_compoundargs *argp, nfs4_verifier *verf) · 276 unmodified lines
277static __be32277static __be32
278nfsd4_decode_bitmap4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen)278nfsd4_decode_bitmap4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen)
279{279{
280 u32 i, count;280 ssize_t status;
281 __be32 *p;
282
283 if (xdr_stream_decode_u32(argp->xdr, &count) < 0)
284 return nfserr_bad_xdr;
285 /* request sanity */
286 if (count > 1000)
287 return nfserr_bad_xdr;
288 p = xdr_inline_decode(argp->xdr, count << 2);
289 if (!p)
290 return nfserr_bad_xdr;
291 for (i = 0; i < bmlen; i++)
292 bmval[i] = (i < count) ? be32_to_cpup(p++) : 0;
293 281
294 return nfs_ok;282 status = xdr_stream_decode_uint32_array(argp->xdr, bmval, bmlen);
283 return status == -EBADMSG ? nfserr_bad_xdr : nfs_ok;
295}284}
296 285
297static __be32286static __be32
@@ -4804,8 +4793,8 @@ nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp, · 4506 unmodified lines
4804 return nfserr_resource;4793 return nfserr_resource;
4805 4794
4806 *p++ = htonl(NFS4_CONTENT_HOLE);4795 *p++ = htonl(NFS4_CONTENT_HOLE);
4807 p = xdr_encode_hyper(p, read->rd_offset);4796 p = xdr_encode_hyper(p, read->rd_offset);
4808 p = xdr_encode_hyper(p, count);4797 p = xdr_encode_hyper(p, count);
4809 4798
4810 *eof = (read->rd_offset + count) >= f_size;4799 *eof = (read->rd_offset + count) >= f_size;
4811 *maxcount = min_t(unsigned long, count, *maxcount);4800 *maxcount = min_t(unsigned long, count, *maxcount);
fs/nfsd/nfscache.c+1−1
@@ -87,7 +87,7 @@ nfsd_hashsize(unsigned int limit) · 86 unmodified lines
87static u3287static u32
88nfsd_cache_hash(__be32 xid, struct nfsd_net *nn)88nfsd_cache_hash(__be32 xid, struct nfsd_net *nn)
89{89{
90 return hash_32(be32_to_cpu(xid), nn->maskbits);90 return hash_32((__force u32)xid, nn->maskbits);
91}91}
92 92
93static struct svc_cacherep *93static struct svc_cacherep *
fs/nfsd/nfsctl.c+12−15
@@ -742,13 +742,12 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred · 741 unmodified lines
742 return err;742 return err;
743 743
744 err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred);744 err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred);
745 if (err < 0) {
746 nfsd_destroy(net);
747 return err;
748 }
749 745
750 /* Decrease the count, but don't shut down the service */746 if (err >= 0 &&
751 nn->nfsd_serv->sv_nrthreads--;747 !nn->nfsd_serv->sv_nrthreads && !xchg(&nn->keep_active, 1))
748 svc_get(nn->nfsd_serv);
749
750 nfsd_put(net);
752 return err;751 return err;
753}752}
754 753
@@ -783,8 +782,10 @@ static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct cr · 28 unmodified lines
783 if (err < 0 && err != -EAFNOSUPPORT)782 if (err < 0 && err != -EAFNOSUPPORT)
784 goto out_close;783 goto out_close;
785 784
786 /* Decrease the count, but don't shut down the service */785 if (!nn->nfsd_serv->sv_nrthreads && !xchg(&nn->keep_active, 1))
787 nn->nfsd_serv->sv_nrthreads--;786 svc_get(nn->nfsd_serv);
787
788 nfsd_put(net);
788 return 0;789 return 0;
789out_close:790out_close:
790 xprt = svc_find_xprt(nn->nfsd_serv, transport, net, PF_INET, port);791 xprt = svc_find_xprt(nn->nfsd_serv, transport, net, PF_INET, port);
@@ -793,10 +794,7 @@ out_close: · 2 unmodified lines
793 svc_xprt_put(xprt);794 svc_xprt_put(xprt);
794 }795 }
795out_err:796out_err:
796 if (!list_empty(&nn->nfsd_serv->sv_permsocks))797 nfsd_put(net);
797 nn->nfsd_serv->sv_nrthreads--;
798 else
799 nfsd_destroy(net);
800 return err;798 return err;
801}799}
802 800
@@ -1485,9 +1483,8 @@ static __net_init int nfsd_init_net(struct net *net) · 682 unmodified lines
1485 nn->clientid_counter = nn->clientid_base + 1;1483 nn->clientid_counter = nn->clientid_base + 1;
1486 nn->s2s_cp_cl_id = nn->clientid_counter++;1484 nn->s2s_cp_cl_id = nn->clientid_counter++;
1487 1485
1488 atomic_set(&nn->ntf_refcnt, 0);1486 get_random_bytes(&nn->siphash_key, sizeof(nn->siphash_key));
1489 init_waitqueue_head(&nn->ntf_wq);1487 seqlock_init(&nn->writeverf_lock);
1490 seqlock_init(&nn->boot_lock);
1491 1488
1492 return 0;1489 return 0;
1493 1490
fs/nfsd/nfsd.h+1−1
@@ -97,7 +97,7 @@ int nfsd_pool_stats_open(struct inode *, struct file *); · 96 unmodified lines
97int nfsd_pool_stats_release(struct inode *, struct file *);97int nfsd_pool_stats_release(struct inode *, struct file *);
98void nfsd_shutdown_threads(struct net *net);98void nfsd_shutdown_threads(struct net *net);
99 99
100void nfsd_destroy(struct net *net);100void nfsd_put(struct net *net);
101 101
102bool i_am_nfsd(void);102bool i_am_nfsd(void);
103 103
fs/nfsd/nfsfh.c+65−1
@@ -611,6 +611,70 @@ out_negative: · 610 unmodified lines
611 return nfserr_serverfault;611 return nfserr_serverfault;
612}612}
613 613
614#ifdef CONFIG_NFSD_V3
615
616/**
617 * fh_fill_pre_attrs - Fill in pre-op attributes
618 * @fhp: file handle to be updated
619 *
620 */
621void fh_fill_pre_attrs(struct svc_fh *fhp)
622{
623 bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE);
624 struct inode *inode;
625 struct kstat stat;
626 __be32 err;
627
628 if (fhp->fh_no_wcc || fhp->fh_pre_saved)
629 return;
630
631 inode = d_inode(fhp->fh_dentry);
632 err = fh_getattr(fhp, &stat);
633 if (err) {
634 /* Grab the times from inode anyway */
635 stat.mtime = inode->i_mtime;
636 stat.ctime = inode->i_ctime;
637 stat.size = inode->i_size;
638 }
639 if (v4)
640 fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode);
641
642 fhp->fh_pre_mtime = stat.mtime;
643 fhp->fh_pre_ctime = stat.ctime;
644 fhp->fh_pre_size = stat.size;
645 fhp->fh_pre_saved = true;
646}
647
648/**
649 * fh_fill_post_attrs - Fill in post-op attributes
650 * @fhp: file handle to be updated
651 *
652 */
653void fh_fill_post_attrs(struct svc_fh *fhp)
654{
655 bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE);
656 struct inode *inode = d_inode(fhp->fh_dentry);
657 __be32 err;
658
659 if (fhp->fh_no_wcc)
660 return;
661
662 if (fhp->fh_post_saved)
663 printk("nfsd: inode locked twice during operation.\n");
664
665 err = fh_getattr(fhp, &fhp->fh_post_attr);
666 if (err) {
667 fhp->fh_post_saved = false;
668 fhp->fh_post_attr.ctime = inode->i_ctime;
669 } else
670 fhp->fh_post_saved = true;
671 if (v4)
672 fhp->fh_post_change =
673 nfsd4_change_attribute(&fhp->fh_post_attr, inode);
674}
675
676#endif /* CONFIG_NFSD_V3 */
677
614/*678/*
615 * Release a file handle.679 * Release a file handle.
616 */680 */
@@ -623,7 +687,7 @@ fh_put(struct svc_fh *fhp) · 6 unmodified lines
623 fh_unlock(fhp);687 fh_unlock(fhp);
624 fhp->fh_dentry = NULL;688 fhp->fh_dentry = NULL;
625 dput(dentry);689 dput(dentry);
626 fh_clear_wcc(fhp);690 fh_clear_pre_post_attrs(fhp);
627 }691 }
628 fh_drop_write(fhp);692 fh_drop_write(fhp);
629 if (exp) {693 if (exp) {
fs/nfsd/nfsfh.h+26−14
@@ -284,12 +284,13 @@ static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) · 283 unmodified lines
284#endif284#endif
285 285
286#ifdef CONFIG_NFSD_V3286#ifdef CONFIG_NFSD_V3
287/*287
288 * The wcc data stored in current_fh should be cleared288/**
289 * between compound ops.289 * fh_clear_pre_post_attrs - Reset pre/post attributes
290 * @fhp: file handle to be updated
291 *
290 */292 */
291static inline void293static inline void fh_clear_pre_post_attrs(struct svc_fh *fhp)
292fh_clear_wcc(struct svc_fh *fhp)
293{294{
294 fhp->fh_post_saved = false;295 fhp->fh_post_saved = false;
295 fhp->fh_pre_saved = false;296 fhp->fh_pre_saved = false;
@@ -323,13 +324,24 @@ static inline u64 nfsd4_change_attribute(struct kstat *stat, · 27 unmodified lines
323 return time_to_chattr(&stat->ctime);324 return time_to_chattr(&stat->ctime);
324}325}
325 326
326extern void fill_pre_wcc(struct svc_fh *fhp);327extern void fh_fill_pre_attrs(struct svc_fh *fhp);
327extern void fill_post_wcc(struct svc_fh *fhp);328extern void fh_fill_post_attrs(struct svc_fh *fhp);
328#else329
329#define fh_clear_wcc(ignored)330#else /* !CONFIG_NFSD_V3 */
330#define fill_pre_wcc(ignored)331
331#define fill_post_wcc(notused)332static inline void fh_clear_pre_post_attrs(struct svc_fh *fhp)
332#endif /* CONFIG_NFSD_V3 */333{
334}
335
336static inline void fh_fill_pre_attrs(struct svc_fh *fhp)
337{
338}
339
340static inline void fh_fill_post_attrs(struct svc_fh *fhp)
341{
342}
343
344#endif /* !CONFIG_NFSD_V3 */
333 345
334 346
335/*347/*
@@ -355,7 +367,7 @@ fh_lock_nested(struct svc_fh *fhp, unsigned int subclass) · 19 unmodified lines
355 367
356 inode = d_inode(dentry);368 inode = d_inode(dentry);
357 inode_lock_nested(inode, subclass);369 inode_lock_nested(inode, subclass);
358 fill_pre_wcc(fhp);370 fh_fill_pre_attrs(fhp);
359 fhp->fh_locked = true;371 fhp->fh_locked = true;
360}372}
361 373
@@ -372,7 +384,7 @@ static inline void · 10 unmodified lines
372fh_unlock(struct svc_fh *fhp)384fh_unlock(struct svc_fh *fhp)
373{385{
374 if (fhp->fh_locked) {386 if (fhp->fh_locked) {
375 fill_post_wcc(fhp);387 fh_fill_post_attrs(fhp);
376 inode_unlock(d_inode(fhp->fh_dentry));388 inode_unlock(d_inode(fhp->fh_dentry));
377 fhp->fh_locked = false;389 fhp->fh_locked = false;
378 }390 }
fs/nfsd/nfsproc.c+3−5
@@ -235,10 +235,6 @@ nfsd_proc_write(struct svc_rqst *rqstp) · 234 unmodified lines
235 argp->len, argp->offset);235 argp->len, argp->offset);
236 236
237 nvecs = svc_fill_write_vector(rqstp, &argp->payload);237 nvecs = svc_fill_write_vector(rqstp, &argp->payload);
238 if (!nvecs) {
239 resp->status = nfserr_io;
240 goto out;
241 }
242 238
243 resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),239 resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
244 argp->offset, rqstp->rq_vec, nvecs,240 argp->offset, rqstp->rq_vec, nvecs,
@@ -247,7 +243,6 @@ nfsd_proc_write(struct svc_rqst *rqstp) · 2 unmodified lines
247 resp->status = fh_getattr(&resp->fh, &resp->stat);243 resp->status = fh_getattr(&resp->fh, &resp->stat);
248 else if (resp->status == nfserr_jukebox)244 else if (resp->status == nfserr_jukebox)
249 return rpc_drop_reply;245 return rpc_drop_reply;
250out:
251 return rpc_success;246 return rpc_success;
252}247}
253 248
@@ -850,6 +845,7 @@ nfserrno (int errno) · 596 unmodified lines
850 { nfserr_io, -EIO },845 { nfserr_io, -EIO },
851 { nfserr_nxio, -ENXIO },846 { nfserr_nxio, -ENXIO },
852 { nfserr_fbig, -E2BIG },847 { nfserr_fbig, -E2BIG },
848 { nfserr_stale, -EBADF },
853 { nfserr_acces, -EACCES },849 { nfserr_acces, -EACCES },
854 { nfserr_exist, -EEXIST },850 { nfserr_exist, -EEXIST },
855 { nfserr_xdev, -EXDEV },851 { nfserr_xdev, -EXDEV },
@@ -878,6 +874,8 @@ nfserrno (int errno) · 22 unmodified lines
878 { nfserr_toosmall, -ETOOSMALL },874 { nfserr_toosmall, -ETOOSMALL },
879 { nfserr_serverfault, -ESERVERFAULT },875 { nfserr_serverfault, -ESERVERFAULT },
880 { nfserr_serverfault, -ENFILE },876 { nfserr_serverfault, -ENFILE },
877 { nfserr_io, -EREMOTEIO },
878 { nfserr_stale, -EOPENSTALE },
881 { nfserr_io, -EUCLEAN },879 { nfserr_io, -EUCLEAN },
882 { nfserr_perm, -ENOKEY },880 { nfserr_perm, -ENOKEY },
883 { nfserr_no_grace, -ENOGRACE},881 { nfserr_no_grace, -ENOGRACE},
fs/nfsd/nfssvc.c+126−94
@@ -12,6 +12,7 @@ · 11 unmodified lines
12#include <linux/module.h>12#include <linux/module.h>
13#include <linux/fs_struct.h>13#include <linux/fs_struct.h>
14#include <linux/swap.h>14#include <linux/swap.h>
15#include <linux/siphash.h>
15 16
16#include <linux/sunrpc/stats.h>17#include <linux/sunrpc/stats.h>
17#include <linux/sunrpc/svcsock.h>18#include <linux/sunrpc/svcsock.h>
@@ -55,18 +56,17 @@ static __be32 nfsd_init_request(struct svc_rqst *, · 37 unmodified lines
55 struct svc_process_info *);56 struct svc_process_info *);
56 57
57/*58/*
58 * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members59 * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and some members
59 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some60 * of the svc_serv struct such as ->sv_temp_socks and ->sv_permsocks.
60 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
61 *61 *
62 * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a62 * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a
63 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number63 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0 (unless
64 * of nfsd threads must exist and each must listed in ->sp_all_threads in each64 * nn->keep_active is set). That number of nfsd threads must
65 * entry of ->sv_pools[].65 * exist and each must be listed in ->sp_all_threads in some entry of
66 * ->sv_pools[].
66 *67 *
67 * Transitions of the thread count between zero and non-zero are of particular68 * Each active thread holds a counted reference on nn->nfsd_serv, as does
68 * interest since the svc_serv needs to be created and initialized at that69 * the nn->keep_active flag and various transient calls to svc_get().
69 * point, or freed.
70 *70 *
71 * Finally, the nfsd_mutex also protects some of the global variables that are71 * Finally, the nfsd_mutex also protects some of the global variables that are
72 * accessed when nfsd starts and that are settable via the write_* routines in72 * accessed when nfsd starts and that are settable via the write_* routines in
@@ -345,33 +345,57 @@ static bool nfsd_needs_lockd(struct nfsd_net *nn) · 272 unmodified lines
345 return nfsd_vers(nn, 2, NFSD_TEST) || nfsd_vers(nn, 3, NFSD_TEST);345 return nfsd_vers(nn, 2, NFSD_TEST) || nfsd_vers(nn, 3, NFSD_TEST);
346}346}
347 347
348void nfsd_copy_boot_verifier(__be32 verf[2], struct nfsd_net *nn)348/**
349 * nfsd_copy_write_verifier - Atomically copy a write verifier
350 * @verf: buffer in which to receive the verifier cookie
351 * @nn: NFS net namespace
352 *
353 * This function provides a wait-free mechanism for copying the
354 * namespace's write verifier without tearing it.
355 */
356void nfsd_copy_write_verifier(__be32 verf[2], struct nfsd_net *nn)
349{357{
350 int seq = 0;358 int seq = 0;
351 359
352 do {360 do {
353 read_seqbegin_or_lock(&nn->boot_lock, &seq);361 read_seqbegin_or_lock(&nn->writeverf_lock, &seq);
354 /*362 memcpy(verf, nn->writeverf, sizeof(*verf));
355 * This is opaque to client, so no need to byte-swap. Use363 } while (need_seqretry(&nn->writeverf_lock, seq));
356 * __force to keep sparse happy. y2038 time_t overflow is364 done_seqretry(&nn->writeverf_lock, seq);
357 * irrelevant in this usage
358 */
359 verf[0] = (__force __be32)nn->nfssvc_boot.tv_sec;
360 verf[1] = (__force __be32)nn->nfssvc_boot.tv_nsec;
361 } while (need_seqretry(&nn->boot_lock, seq));
362 done_seqretry(&nn->boot_lock, seq);
363}365}
364 366
365static void nfsd_reset_boot_verifier_locked(struct nfsd_net *nn)367static void nfsd_reset_write_verifier_locked(struct nfsd_net *nn)
366{368{
367 ktime_get_real_ts64(&nn->nfssvc_boot);369 struct timespec64 now;
370 u64 verf;
371
372 /*
373 * Because the time value is hashed, y2038 time_t overflow
374 * is irrelevant in this usage.
375 */
376 ktime_get_raw_ts64(&now);
377 verf = siphash_2u64(now.tv_sec, now.tv_nsec, &nn->siphash_key);
378 memcpy(nn->writeverf, &verf, sizeof(nn->writeverf));
368}379}
369 380
370void nfsd_reset_boot_verifier(struct nfsd_net *nn)381/**
382 * nfsd_reset_write_verifier - Generate a new write verifier
383 * @nn: NFS net namespace
384 *
385 * This function updates the ->writeverf field of @nn. This field
386 * contains an opaque cookie that, according to Section 18.32.3 of
387 * RFC 8881, "the client can use to determine whether a server has
388 * changed instance state (e.g., server restart) between a call to
389 * WRITE and a subsequent call to either WRITE or COMMIT. This
390 * cookie MUST be unchanged during a single instance of the NFSv4.1
391 * server and MUST be unique between instances of the NFSv4.1
392 * server."
393 */
394void nfsd_reset_write_verifier(struct nfsd_net *nn)
371{395{
372 write_seqlock(&nn->boot_lock);396 write_seqlock(&nn->writeverf_lock);
373 nfsd_reset_boot_verifier_locked(nn);397 nfsd_reset_write_verifier_locked(nn);
374 write_sequnlock(&nn->boot_lock);398 write_sequnlock(&nn->writeverf_lock);
375}399}
376 400
377static int nfsd_startup_net(struct net *net, const struct cred *cred)401static int nfsd_startup_net(struct net *net, const struct cred *cred)
@@ -435,6 +459,7 @@ static void nfsd_shutdown_net(struct net *net) · 57 unmodified lines
435 nfsd_shutdown_generic();459 nfsd_shutdown_generic();
436}460}
437 461
462static DEFINE_SPINLOCK(nfsd_notifier_lock);
438static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event,463static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event,
439 void *ptr)464 void *ptr)
440{465{
@@ -444,18 +469,17 @@ static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event, · 3 unmodified lines
444 struct nfsd_net *nn = net_generic(net, nfsd_net_id);469 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
445 struct sockaddr_in sin;470 struct sockaddr_in sin;
446 471
447 if ((event != NETDEV_DOWN) ||472 if (event != NETDEV_DOWN || !nn->nfsd_serv)
448 !atomic_inc_not_zero(&nn->ntf_refcnt))
449 goto out;473 goto out;
450 474
475 spin_lock(&nfsd_notifier_lock);
451 if (nn->nfsd_serv) {476 if (nn->nfsd_serv) {
452 dprintk("nfsd_inetaddr_event: removed %pI4\n", &ifa->ifa_local);477 dprintk("nfsd_inetaddr_event: removed %pI4\n", &ifa->ifa_local);
453 sin.sin_family = AF_INET;478 sin.sin_family = AF_INET;
454 sin.sin_addr.s_addr = ifa->ifa_local;479 sin.sin_addr.s_addr = ifa->ifa_local;
455 svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin);480 svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin);
456 }481 }
457 atomic_dec(&nn->ntf_refcnt);482 spin_unlock(&nfsd_notifier_lock);
458 wake_up(&nn->ntf_wq);
459 483
460out:484out:
461 return NOTIFY_DONE;485 return NOTIFY_DONE;
@@ -475,10 +499,10 @@ static int nfsd_inet6addr_event(struct notifier_block *this, · 13 unmodified lines
475 struct nfsd_net *nn = net_generic(net, nfsd_net_id);499 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
476 struct sockaddr_in6 sin6;500 struct sockaddr_in6 sin6;
477 501
478 if ((event != NETDEV_DOWN) ||502 if (event != NETDEV_DOWN || !nn->nfsd_serv)
479 !atomic_inc_not_zero(&nn->ntf_refcnt))
480 goto out;503 goto out;
481 504
505 spin_lock(&nfsd_notifier_lock);
482 if (nn->nfsd_serv) {506 if (nn->nfsd_serv) {
483 dprintk("nfsd_inet6addr_event: removed %pI6\n", &ifa->addr);507 dprintk("nfsd_inet6addr_event: removed %pI6\n", &ifa->addr);
484 sin6.sin6_family = AF_INET6;508 sin6.sin6_family = AF_INET6;
@@ -487,8 +511,8 @@ static int nfsd_inet6addr_event(struct notifier_block *this, · 2 unmodified lines
487 sin6.sin6_scope_id = ifa->idev->dev->ifindex;511 sin6.sin6_scope_id = ifa->idev->dev->ifindex;
488 svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin6);512 svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin6);
489 }513 }
490 atomic_dec(&nn->ntf_refcnt);514 spin_unlock(&nfsd_notifier_lock);
491 wake_up(&nn->ntf_wq);515
492out:516out:
493 return NOTIFY_DONE;517 return NOTIFY_DONE;
494}518}
@@ -505,7 +529,6 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net) · 10 unmodified lines
505{529{
506 struct nfsd_net *nn = net_generic(net, nfsd_net_id);530 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
507 531
508 atomic_dec(&nn->ntf_refcnt);
509 /* check if the notifier still has clients */532 /* check if the notifier still has clients */
510 if (atomic_dec_return(&nfsd_notifier_refcount) == 0) {533 if (atomic_dec_return(&nfsd_notifier_refcount) == 0) {
511 unregister_inetaddr_notifier(&nfsd_inetaddr_notifier);534 unregister_inetaddr_notifier(&nfsd_inetaddr_notifier);
@@ -513,7 +536,6 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net) · 1 unmodified line
513 unregister_inet6addr_notifier(&nfsd_inet6addr_notifier);536 unregister_inet6addr_notifier(&nfsd_inet6addr_notifier);
514#endif537#endif
515 }538 }
516 wait_event(nn->ntf_wq, atomic_read(&nn->ntf_refcnt) == 0);
517 539
518 /*540 /*
519 * write_ports can create the server without actually starting541 * write_ports can create the server without actually starting
@@ -594,20 +616,9 @@ static const struct svc_serv_ops nfsd_thread_sv_ops = { · 74 unmodified lines
594 .svo_shutdown = nfsd_last_thread,616 .svo_shutdown = nfsd_last_thread,
595 .svo_function = nfsd,617 .svo_function = nfsd,
596 .svo_enqueue_xprt = svc_xprt_do_enqueue,618 .svo_enqueue_xprt = svc_xprt_do_enqueue,
597 .svo_setup = svc_set_num_threads,
598 .svo_module = THIS_MODULE,619 .svo_module = THIS_MODULE,
599};620};
600 621
601static void nfsd_complete_shutdown(struct net *net)
602{
603 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
604
605 WARN_ON(!mutex_is_locked(&nfsd_mutex));
606
607 nn->nfsd_serv = NULL;
608 complete(&nn->nfsd_shutdown_complete);
609}
610
611void nfsd_shutdown_threads(struct net *net)622void nfsd_shutdown_threads(struct net *net)
612{623{
613 struct nfsd_net *nn = net_generic(net, nfsd_net_id);624 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
@@ -622,11 +633,9 @@ void nfsd_shutdown_threads(struct net *net) · 8 unmodified lines
622 633
623 svc_get(serv);634 svc_get(serv);
624 /* Kill outstanding nfsd threads */635 /* Kill outstanding nfsd threads */
625 serv->sv_ops->svo_setup(serv, NULL, 0);636 svc_set_num_threads(serv, NULL, 0);
626 nfsd_destroy(net);637 nfsd_put(net);
627 mutex_unlock(&nfsd_mutex);638 mutex_unlock(&nfsd_mutex);
628 /* Wait for shutdown of nfsd_serv to complete */
629 wait_for_completion(&nn->nfsd_shutdown_complete);
630}639}
631 640
632bool i_am_nfsd(void)641bool i_am_nfsd(void)
@@ -638,6 +647,7 @@ int nfsd_create_serv(struct net *net) · 5 unmodified lines
638{647{
639 int error;648 int error;
640 struct nfsd_net *nn = net_generic(net, nfsd_net_id);649 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
650 struct svc_serv *serv;
641 651
642 WARN_ON(!mutex_is_locked(&nfsd_mutex));652 WARN_ON(!mutex_is_locked(&nfsd_mutex));
643 if (nn->nfsd_serv) {653 if (nn->nfsd_serv) {
@@ -647,19 +657,23 @@ int nfsd_create_serv(struct net *net) · 3 unmodified lines
647 if (nfsd_max_blksize == 0)657 if (nfsd_max_blksize == 0)
648 nfsd_max_blksize = nfsd_get_default_max_blksize();658 nfsd_max_blksize = nfsd_get_default_max_blksize();
649 nfsd_reset_versions(nn);659 nfsd_reset_versions(nn);
650 nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,660 serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
651 &nfsd_thread_sv_ops);661 &nfsd_thread_sv_ops);
652 if (nn->nfsd_serv == NULL)662 if (serv == NULL)
653 return -ENOMEM;663 return -ENOMEM;
654 init_completion(&nn->nfsd_shutdown_complete);
655 664
656 nn->nfsd_serv->sv_maxconn = nn->max_connections;665 serv->sv_maxconn = nn->max_connections;
657 error = svc_bind(nn->nfsd_serv, net);666 error = svc_bind(serv, net);
658 if (error < 0) {667 if (error < 0) {
659 svc_destroy(nn->nfsd_serv);668 /* NOT nfsd_put() as notifiers (see below) haven't
660 nfsd_complete_shutdown(net);669 * been set up yet.
670 */
671 svc_put(serv);
661 return error;672 return error;
662 }673 }
674 spin_lock(&nfsd_notifier_lock);
675 nn->nfsd_serv = serv;
676 spin_unlock(&nfsd_notifier_lock);
663 677
664 set_max_drc();678 set_max_drc();
665 /* check if the notifier is already set */679 /* check if the notifier is already set */
@@ -669,8 +683,7 @@ int nfsd_create_serv(struct net *net) · 3 unmodified lines
669 register_inet6addr_notifier(&nfsd_inet6addr_notifier);683 register_inet6addr_notifier(&nfsd_inet6addr_notifier);
670#endif684#endif
671 }685 }
672 atomic_inc(&nn->ntf_refcnt);686 nfsd_reset_write_verifier(nn);
673 nfsd_reset_boot_verifier(nn);
674 return 0;687 return 0;
675}688}
676 689
@@ -697,16 +710,26 @@ int nfsd_get_nrthreads(int n, int *nthreads, struct net *net) · 20 unmodified lines
697 return 0;710 return 0;
698}711}
699 712
700void nfsd_destroy(struct net *net)713/* This is the callback for kref_put() below.
714 * There is no code here as the first thing to be done is
715 * call svc_shutdown_net(), but we cannot get the 'net' from
716 * the kref. So do all the work when kref_put returns true.
717 */
718static void nfsd_noop(struct kref *ref)
719{
720}
721
722void nfsd_put(struct net *net)
701{723{
702 struct nfsd_net *nn = net_generic(net, nfsd_net_id);724 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
703 int destroy = (nn->nfsd_serv->sv_nrthreads == 1);
704 725
705 if (destroy)726 if (kref_put(&nn->nfsd_serv->sv_refcnt, nfsd_noop)) {
706 svc_shutdown_net(nn->nfsd_serv, net);727 svc_shutdown_net(nn->nfsd_serv, net);
707 svc_destroy(nn->nfsd_serv);728 svc_destroy(&nn->nfsd_serv->sv_refcnt);
708 if (destroy)729 spin_lock(&nfsd_notifier_lock);
709 nfsd_complete_shutdown(net);730 nn->nfsd_serv = NULL;
731 spin_unlock(&nfsd_notifier_lock);
732 }
710}733}
711 734
712int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)735int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
@@ -733,7 +756,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net) · 20 unmodified lines
733 if (tot > NFSD_MAXSERVS) {756 if (tot > NFSD_MAXSERVS) {
734 /* total too large: scale down requested numbers */757 /* total too large: scale down requested numbers */
735 for (i = 0; i < n && tot > 0; i++) {758 for (i = 0; i < n && tot > 0; i++) {
736 int new = nthreads[i] * NFSD_MAXSERVS / tot;759 int new = nthreads[i] * NFSD_MAXSERVS / tot;
737 tot -= (nthreads[i] - new);760 tot -= (nthreads[i] - new);
738 nthreads[i] = new;761 nthreads[i] = new;
739 }762 }
@@ -753,12 +776,13 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net) · 13 unmodified lines
753 /* apply the new numbers */776 /* apply the new numbers */
754 svc_get(nn->nfsd_serv);777 svc_get(nn->nfsd_serv);
755 for (i = 0; i < n; i++) {778 for (i = 0; i < n; i++) {
756 err = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv,779 err = svc_set_num_threads(nn->nfsd_serv,
757 &nn->nfsd_serv->sv_pools[i], nthreads[i]);780 &nn->nfsd_serv->sv_pools[i],
781 nthreads[i]);
758 if (err)782 if (err)
759 break;783 break;
760 }784 }
761 nfsd_destroy(net);785 nfsd_put(net);
762 return err;786 return err;
763}787}
764 788
@@ -795,21 +819,19 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred) · 30 unmodified lines
795 819
796 error = nfsd_startup_net(net, cred);820 error = nfsd_startup_net(net, cred);
797 if (error)821 if (error)
798 goto out_destroy;822 goto out_put;
799 error = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv,823 error = svc_set_num_threads(nn->nfsd_serv, NULL, nrservs);
800 NULL, nrservs);
801 if (error)824 if (error)
802 goto out_shutdown;825 goto out_shutdown;
803 /* We are holding a reference to nn->nfsd_serv which826 error = nn->nfsd_serv->sv_nrthreads;
804 * we don't want to count in the return value,
805 * so subtract 1
806 */
807 error = nn->nfsd_serv->sv_nrthreads - 1;
808out_shutdown:827out_shutdown:
809 if (error < 0 && !nfsd_up_before)828 if (error < 0 && !nfsd_up_before)
810 nfsd_shutdown_net(net);829 nfsd_shutdown_net(net);
811out_destroy:830out_put:
812 nfsd_destroy(net); /* Release server */831 /* Threads now hold service active */
832 if (xchg(&nn->keep_active, 0))
833 nfsd_put(net);
834 nfsd_put(net);
813out:835out:
814 mutex_unlock(&nfsd_mutex);836 mutex_unlock(&nfsd_mutex);
815 return error;837 return error;
@@ -923,9 +945,6 @@ nfsd(void *vrqstp) · 107 unmodified lines
923 struct nfsd_net *nn = net_generic(net, nfsd_net_id);945 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
924 int err;946 int err;
925 947
926 /* Lock module and set up kernel thread */
927 mutex_lock(&nfsd_mutex);
928
929 /* At this point, the thread shares current->fs948 /* At this point, the thread shares current->fs
930 * with the init process. We need to create files with the949 * with the init process. We need to create files with the
931 * umask as defined by the client instead of init's umask. */950 * umask as defined by the client instead of init's umask. */
@@ -945,8 +964,7 @@ nfsd(void *vrqstp) · 13 unmodified lines
945 allow_signal(SIGINT);964 allow_signal(SIGINT);
946 allow_signal(SIGQUIT);965 allow_signal(SIGQUIT);
947 966
948 nfsdstats.th_cnt++;967 atomic_inc(&nfsdstats.th_cnt);
949 mutex_unlock(&nfsd_mutex);
950 968
951 set_freezable();969 set_freezable();
952 970
@@ -973,19 +991,35 @@ nfsd(void *vrqstp) · 20 unmodified lines
973 /* Clear signals before calling svc_exit_thread() */991 /* Clear signals before calling svc_exit_thread() */
974 flush_signals(current);992 flush_signals(current);
975 993
976 mutex_lock(&nfsd_mutex);994 atomic_dec(&nfsdstats.th_cnt);
977 nfsdstats.th_cnt --;
978 995
979out:996out:
980 rqstp->rq_server = NULL;997 /* Take an extra ref so that the svc_put in svc_exit_thread()
998 * doesn't call svc_destroy()
999 */
1000 svc_get(nn->nfsd_serv);
981 1001
982 /* Release the thread */1002 /* Release the thread */
983 svc_exit_thread(rqstp);1003 svc_exit_thread(rqstp);
984 1004
985 nfsd_destroy(net);1005 /* We need to drop a ref, but may not drop the last reference
1006 * without holding nfsd_mutex, and we cannot wait for nfsd_mutex as that
1007 * could deadlock with nfsd_shutdown_threads() waiting for us.
1008 * So three options are:
1009 * - drop a non-final reference,
1010 * - get the mutex without waiting
1011 * - sleep briefly andd try the above again
1012 */
1013 while (!svc_put_not_last(nn->nfsd_serv)) {
1014 if (mutex_trylock(&nfsd_mutex)) {
1015 nfsd_put(net);
1016 mutex_unlock(&nfsd_mutex);
1017 break;
1018 }
1019 msleep(20);
1020 }
986 1021
987 /* Release module */1022 /* Release module */
988 mutex_unlock(&nfsd_mutex);
989 module_put_and_exit(0);1023 module_put_and_exit(0);
990 return 0;1024 return 0;
991}1025}
@@ -1096,7 +1130,6 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file) · 104 unmodified lines
1096 mutex_unlock(&nfsd_mutex);1130 mutex_unlock(&nfsd_mutex);
1097 return -ENODEV;1131 return -ENODEV;
1098 }1132 }
1099 /* bump up the psudo refcount while traversing */
1100 svc_get(nn->nfsd_serv);1133 svc_get(nn->nfsd_serv);
1101 ret = svc_pool_stats_open(nn->nfsd_serv, file);1134 ret = svc_pool_stats_open(nn->nfsd_serv, file);
1102 mutex_unlock(&nfsd_mutex);1135 mutex_unlock(&nfsd_mutex);
@@ -1109,8 +1142,7 @@ int nfsd_pool_stats_release(struct inode *inode, struct file *file) · 6 unmodified lines
1109 struct net *net = inode->i_sb->s_fs_info;1142 struct net *net = inode->i_sb->s_fs_info;
1110 1143
1111 mutex_lock(&nfsd_mutex);1144 mutex_lock(&nfsd_mutex);
1112 /* this function really, really should have been called svc_put() */1145 nfsd_put(net);
1113 nfsd_destroy(net);
1114 mutex_unlock(&nfsd_mutex);1146 mutex_unlock(&nfsd_mutex);
1115 return ret;1147 return ret;
1116}1148}
fs/nfsd/state.h+5−0
@@ -568,6 +568,10 @@ struct nfs4_ol_stateid { · 567 unmodified lines
568 struct list_head st_locks;568 struct list_head st_locks;
569 struct nfs4_stateowner *st_stateowner;569 struct nfs4_stateowner *st_stateowner;
570 struct nfs4_clnt_odstate *st_clnt_odstate;570 struct nfs4_clnt_odstate *st_clnt_odstate;
571/*
572 * These bitmasks use 3 separate bits for READ, ALLOW, and BOTH; see the
573 * comment above bmap_to_share_mode() for explanation:
574 */
571 unsigned char st_access_bmap;575 unsigned char st_access_bmap;
572 unsigned char st_deny_bmap;576 unsigned char st_deny_bmap;
573 struct nfs4_ol_stateid *st_openstp;577 struct nfs4_ol_stateid *st_openstp;
@@ -629,6 +633,7 @@ struct nfsd4_blocked_lock { · 55 unmodified lines
629 struct file_lock nbl_lock;633 struct file_lock nbl_lock;
630 struct knfsd_fh nbl_fh;634 struct knfsd_fh nbl_fh;
631 struct nfsd4_callback nbl_cb;635 struct nfsd4_callback nbl_cb;
636 struct kref nbl_kref;
632};637};
633 638
634struct nfsd4_compound_state;639struct nfsd4_compound_state;
fs/nfsd/stats.c+1−1
@@ -45,7 +45,7 @@ static int nfsd_proc_show(struct seq_file *seq, void *v) · 44 unmodified lines
45 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_IO_WRITE]));45 percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_IO_WRITE]));
46 46
47 /* thread usage: */47 /* thread usage: */
48 seq_printf(seq, "th %u 0", nfsdstats.th_cnt);48 seq_printf(seq, "th %u 0", atomic_read(&nfsdstats.th_cnt));
49 49
50 /* deprecated thread usage histogram stats */50 /* deprecated thread usage histogram stats */
51 for (i = 0; i < 10; i++)51 for (i = 0; i < 10; i++)
fs/nfsd/stats.h+1−3
@@ -29,11 +29,9 @@ enum { · 28 unmodified lines
29struct nfsd_stats {29struct nfsd_stats {
30 struct percpu_counter counter[NFSD_STATS_COUNTERS_NUM];30 struct percpu_counter counter[NFSD_STATS_COUNTERS_NUM];
31 31
32 /* Protected by nfsd_mutex */32 atomic_t th_cnt; /* number of available threads */
33 unsigned int th_cnt; /* number of available threads */
34};33};
35 34
36
37extern struct nfsd_stats nfsdstats;35extern struct nfsd_stats nfsdstats;
38 36
39extern struct svc_stat nfsd_svcstats;37extern struct svc_stat nfsd_svcstats;
fs/nfsd/trace.h+85−21
@@ -47,7 +47,7 @@ · 46 unmodified lines
47 rqstp->rq_xprt->xpt_remotelen); \47 rqstp->rq_xprt->xpt_remotelen); \
48 } while (0);48 } while (0);
49 49
50TRACE_EVENT(nfsd_garbage_args_err,50DECLARE_EVENT_CLASS(nfsd_xdr_err_class,
51 TP_PROTO(51 TP_PROTO(
52 const struct svc_rqst *rqstp52 const struct svc_rqst *rqstp
53 ),53 ),
@@ -69,27 +69,13 @@ TRACE_EVENT(nfsd_garbage_args_err, · 15 unmodified lines
69 )69 )
70);70);
71 71
72TRACE_EVENT(nfsd_cant_encode_err,72#define DEFINE_NFSD_XDR_ERR_EVENT(name) \
73 TP_PROTO(73DEFINE_EVENT(nfsd_xdr_err_class, nfsd_##name##_err, \
74 const struct svc_rqst *rqstp74 TP_PROTO(const struct svc_rqst *rqstp), \
75 ),75 TP_ARGS(rqstp))
76 TP_ARGS(rqstp),
77 TP_STRUCT__entry(
78 NFSD_TRACE_PROC_ARG_FIELDS
79
80 __field(u32, vers)
81 __field(u32, proc)
82 ),
83 TP_fast_assign(
84 NFSD_TRACE_PROC_ARG_ASSIGNMENTS
85 76
86 __entry->vers = rqstp->rq_vers;77DEFINE_NFSD_XDR_ERR_EVENT(garbage_args);
87 __entry->proc = rqstp->rq_proc;78DEFINE_NFSD_XDR_ERR_EVENT(cant_encode);
88 ),
89 TP_printk("xid=0x%08x vers=%u proc=%u",
90 __entry->xid, __entry->vers, __entry->proc
91 )
92);
93 79
94#define show_nfsd_may_flags(x) \80#define show_nfsd_may_flags(x) \
95 __print_flags(x, "|", \81 __print_flags(x, "|", \
@@ -413,6 +399,56 @@ TRACE_EVENT(nfsd_dirent, · 317 unmodified lines
413 )399 )
414)400)
415 401
402DECLARE_EVENT_CLASS(nfsd_copy_err_class,
403 TP_PROTO(struct svc_rqst *rqstp,
404 struct svc_fh *src_fhp,
405 loff_t src_offset,
406 struct svc_fh *dst_fhp,
407 loff_t dst_offset,
408 u64 count,
409 int status),
410 TP_ARGS(rqstp, src_fhp, src_offset, dst_fhp, dst_offset, count, status),
411 TP_STRUCT__entry(
412 __field(u32, xid)
413 __field(u32, src_fh_hash)
414 __field(loff_t, src_offset)
415 __field(u32, dst_fh_hash)
416 __field(loff_t, dst_offset)
417 __field(u64, count)
418 __field(int, status)
419 ),
420 TP_fast_assign(
421 __entry->xid = be32_to_cpu(rqstp->rq_xid);
422 __entry->src_fh_hash = knfsd_fh_hash(&src_fhp->fh_handle);
423 __entry->src_offset = src_offset;
424 __entry->dst_fh_hash = knfsd_fh_hash(&dst_fhp->fh_handle);
425 __entry->dst_offset = dst_offset;
426 __entry->count = count;
427 __entry->status = status;
428 ),
429 TP_printk("xid=0x%08x src_fh_hash=0x%08x src_offset=%lld "
430 "dst_fh_hash=0x%08x dst_offset=%lld "
431 "count=%llu status=%d",
432 __entry->xid, __entry->src_fh_hash, __entry->src_offset,
433 __entry->dst_fh_hash, __entry->dst_offset,
434 (unsigned long long)__entry->count,
435 __entry->status)
436)
437
438#define DEFINE_NFSD_COPY_ERR_EVENT(name) \
439DEFINE_EVENT(nfsd_copy_err_class, nfsd_##name, \
440 TP_PROTO(struct svc_rqst *rqstp, \
441 struct svc_fh *src_fhp, \
442 loff_t src_offset, \
443 struct svc_fh *dst_fhp, \
444 loff_t dst_offset, \
445 u64 count, \
446 int status), \
447 TP_ARGS(rqstp, src_fhp, src_offset, dst_fhp, dst_offset, \
448 count, status))
449
450DEFINE_NFSD_COPY_ERR_EVENT(clone_file_range_err);
451
416#include "state.h"452#include "state.h"
417#include "filecache.h"453#include "filecache.h"
418#include "vfs.h"454#include "vfs.h"
@@ -538,6 +574,34 @@ DEFINE_EVENT(nfsd_net_class, nfsd_##name, \ · 119 unmodified lines
538DEFINE_NET_EVENT(grace_start);574DEFINE_NET_EVENT(grace_start);
539DEFINE_NET_EVENT(grace_complete);575DEFINE_NET_EVENT(grace_complete);
540 576
577TRACE_EVENT(nfsd_writeverf_reset,
578 TP_PROTO(
579 const struct nfsd_net *nn,
580 const struct svc_rqst *rqstp,
581 int error
582 ),
583 TP_ARGS(nn, rqstp, error),
584 TP_STRUCT__entry(
585 __field(unsigned long long, boot_time)
586 __field(u32, xid)
587 __field(int, error)
588 __array(unsigned char, verifier, NFS4_VERIFIER_SIZE)
589 ),
590 TP_fast_assign(
591 __entry->boot_time = nn->boot_time;
592 __entry->xid = be32_to_cpu(rqstp->rq_xid);
593 __entry->error = error;
594
595 /* avoid seqlock inside TP_fast_assign */
596 memcpy(__entry->verifier, nn->writeverf,
597 NFS4_VERIFIER_SIZE);
598 ),
599 TP_printk("boot_time=%16llx xid=0x%08x error=%d new verifier=0x%s",
600 __entry->boot_time, __entry->xid, __entry->error,
601 __print_hex_str(__entry->verifier, NFS4_VERIFIER_SIZE)
602 )
603);
604
541TRACE_EVENT(nfsd_clid_cred_mismatch,605TRACE_EVENT(nfsd_clid_cred_mismatch,
542 TP_PROTO(606 TP_PROTO(
543 const struct nfs4_client *clp,607 const struct nfs4_client *clp,
fs/nfsd/vfs.c+65−57
@@ -40,6 +40,7 @@ · 39 unmodified lines
40#include "../internal.h"40#include "../internal.h"
41#include "acl.h"41#include "acl.h"
42#include "idmap.h"42#include "idmap.h"
43#include "xdr4.h"
43#endif /* CONFIG_NFSD_V4 */44#endif /* CONFIG_NFSD_V4 */
44 45
45#include "nfsd.h"46#include "nfsd.h"
@@ -517,15 +518,23 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, · 471 unmodified lines
517}518}
518#endif519#endif
519 520
520__be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,521static struct nfsd4_compound_state *nfsd4_get_cstate(struct svc_rqst *rqstp)
521 struct nfsd_file *nf_dst, u64 dst_pos, u64 count, bool sync)522{
523 return &((struct nfsd4_compoundres *)rqstp->rq_resp)->cstate;
524}
525
526__be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,
527 struct nfsd_file *nf_src, u64 src_pos,
528 struct nfsd_file *nf_dst, u64 dst_pos,
529 u64 count, bool sync)
522{530{
523 struct file *src = nf_src->nf_file;531 struct file *src = nf_src->nf_file;
524 struct file *dst = nf_dst->nf_file;532 struct file *dst = nf_dst->nf_file;
533 errseq_t since;
525 loff_t cloned;534 loff_t cloned;
526 __be32 ret = 0;535 __be32 ret = 0;
527 536
528 down_write(&nf_dst->nf_rwsem);537 since = READ_ONCE(dst->f_wb_err);
529 cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count, 0);538 cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count, 0);
530 if (cloned < 0) {539 if (cloned < 0) {
531 ret = nfserrno(cloned);540 ret = nfserrno(cloned);
@@ -539,16 +548,26 @@ __be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos, · 7 unmodified lines
539 loff_t dst_end = count ? dst_pos + count - 1 : LLONG_MAX;548 loff_t dst_end = count ? dst_pos + count - 1 : LLONG_MAX;
540 int status = vfs_fsync_range(dst, dst_pos, dst_end, 0);549 int status = vfs_fsync_range(dst, dst_pos, dst_end, 0);
541 550
551 if (!status)
552 status = filemap_check_wb_err(dst->f_mapping, since);
542 if (!status)553 if (!status)
543 status = commit_inode_metadata(file_inode(src));554 status = commit_inode_metadata(file_inode(src));
544 if (status < 0) {555 if (status < 0) {
545 nfsd_reset_boot_verifier(net_generic(nf_dst->nf_net,556 struct nfsd_net *nn = net_generic(nf_dst->nf_net,
546 nfsd_net_id));557 nfsd_net_id);
558
559 trace_nfsd_clone_file_range_err(rqstp,
560 &nfsd4_get_cstate(rqstp)->save_fh,
561 src_pos,
562 &nfsd4_get_cstate(rqstp)->current_fh,
563 dst_pos,
564 count, status);
565 nfsd_reset_write_verifier(nn);
566 trace_nfsd_writeverf_reset(nn, rqstp, status);
547 ret = nfserrno(status);567 ret = nfserrno(status);
548 }568 }
549 }569 }
550out_err:570out_err:
551 up_write(&nf_dst->nf_rwsem);
552 return ret;571 return ret;
553}572}
554 573
@@ -777,6 +796,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, · 222 unmodified lines
777 int may_flags, struct file **filp)796 int may_flags, struct file **filp)
778{797{
779 __be32 err;798 __be32 err;
799 bool retried = false;
780 800
781 validate_process_creds();801 validate_process_creds();
782 /*802 /*
@@ -792,9 +812,16 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, · 9 unmodified lines
792 */812 */
793 if (type == S_IFREG)813 if (type == S_IFREG)
794 may_flags |= NFSD_MAY_OWNER_OVERRIDE;814 may_flags |= NFSD_MAY_OWNER_OVERRIDE;
815retry:
795 err = fh_verify(rqstp, fhp, type, may_flags);816 err = fh_verify(rqstp, fhp, type, may_flags);
796 if (!err)817 if (!err) {
797 err = __nfsd_open(rqstp, fhp, type, may_flags, filp);818 err = __nfsd_open(rqstp, fhp, type, may_flags, filp);
819 if (err == nfserr_stale && !retried) {
820 retried = true;
821 fh_put(fhp);
822 goto retry;
823 }
824 }
798 validate_process_creds();825 validate_process_creds();
799 return err;826 return err;
800}827}
@@ -944,10 +971,12 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, · 143 unmodified lines
944 unsigned long *cnt, int stable,971 unsigned long *cnt, int stable,
945 __be32 *verf)972 __be32 *verf)
946{973{
974 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
947 struct file *file = nf->nf_file;975 struct file *file = nf->nf_file;
948 struct super_block *sb = file_inode(file)->i_sb;976 struct super_block *sb = file_inode(file)->i_sb;
949 struct svc_export *exp;977 struct svc_export *exp;
950 struct iov_iter iter;978 struct iov_iter iter;
979 errseq_t since;
951 __be32 nfserr;980 __be32 nfserr;
952 int host_err;981 int host_err;
953 int use_wgather;982 int use_wgather;
@@ -985,36 +1014,28 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, · 31 unmodified lines
985 flags |= RWF_SYNC;1014 flags |= RWF_SYNC;
986 1015
987 iov_iter_kvec(&iter, WRITE, vec, vlen, *cnt);1016 iov_iter_kvec(&iter, WRITE, vec, vlen, *cnt);
988 if (flags & RWF_SYNC) {1017 since = READ_ONCE(file->f_wb_err);
989 down_write(&nf->nf_rwsem);1018 if (verf)
990 host_err = vfs_iter_write(file, &iter, &pos, flags);1019 nfsd_copy_write_verifier(verf, nn);
991 if (host_err < 0)1020 host_err = vfs_iter_write(file, &iter, &pos, flags);
992 nfsd_reset_boot_verifier(net_generic(SVC_NET(rqstp),
993 nfsd_net_id));
994 up_write(&nf->nf_rwsem);
995 } else {
996 down_read(&nf->nf_rwsem);
997 if (verf)
998 nfsd_copy_boot_verifier(verf,
999 net_generic(SVC_NET(rqstp),
1000 nfsd_net_id));
1001 host_err = vfs_iter_write(file, &iter, &pos, flags);
1002 up_read(&nf->nf_rwsem);
1003 }
1004 if (host_err < 0) {1021 if (host_err < 0) {
1005 nfsd_reset_boot_verifier(net_generic(SVC_NET(rqstp),1022 nfsd_reset_write_verifier(nn);
1006 nfsd_net_id));1023 trace_nfsd_writeverf_reset(nn, rqstp, host_err);
1007 goto out_nfserr;1024 goto out_nfserr;
1008 }1025 }
1009 *cnt = host_err;1026 *cnt = host_err;
1010 nfsd_stats_io_write_add(exp, *cnt);1027 nfsd_stats_io_write_add(exp, *cnt);
1011 fsnotify_modify(file);1028 fsnotify_modify(file);
1029 host_err = filemap_check_wb_err(file->f_mapping, since);
1030 if (host_err < 0)
1031 goto out_nfserr;
1012 1032
1013 if (stable && use_wgather) {1033 if (stable && use_wgather) {
1014 host_err = wait_for_concurrent_writes(file);1034 host_err = wait_for_concurrent_writes(file);
1015 if (host_err < 0)1035 if (host_err < 0) {
1016 nfsd_reset_boot_verifier(net_generic(SVC_NET(rqstp),1036 nfsd_reset_write_verifier(nn);
1017 nfsd_net_id));1037 trace_nfsd_writeverf_reset(nn, rqstp, host_err);
1038 }
1018 }1039 }
1019 1040
1020out_nfserr:1041out_nfserr:
@@ -1089,19 +1110,6 @@ out: · 68 unmodified lines
1089}1110}
1090 1111
1091#ifdef CONFIG_NFSD_V31112#ifdef CONFIG_NFSD_V3
1092static int
1093nfsd_filemap_write_and_wait_range(struct nfsd_file *nf, loff_t offset,
1094 loff_t end)
1095{
1096 struct address_space *mapping = nf->nf_file->f_mapping;
1097 int ret = filemap_fdatawrite_range(mapping, offset, end);
1098
1099 if (ret)
1100 return ret;
1101 filemap_fdatawait_range_keep_errors(mapping, offset, end);
1102 return 0;
1103}
1104
1105/*1113/*
1106 * Commit all pending writes to stable storage.1114 * Commit all pending writes to stable storage.
1107 *1115 *
@@ -1115,6 +1123,7 @@ __be32 · 7 unmodified lines
1115nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,1123nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1116 loff_t offset, unsigned long count, __be32 *verf)1124 loff_t offset, unsigned long count, __be32 *verf)
1117{1125{
1126 struct nfsd_net *nn;
1118 struct nfsd_file *nf;1127 struct nfsd_file *nf;
1119 loff_t end = LLONG_MAX;1128 loff_t end = LLONG_MAX;
1120 __be32 err = nfserr_inval;1129 __be32 err = nfserr_inval;
@@ -1131,29 +1140,28 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, · 10 unmodified lines
1131 NFSD_MAY_WRITE|NFSD_MAY_NOT_BREAK_LEASE, &nf);1140 NFSD_MAY_WRITE|NFSD_MAY_NOT_BREAK_LEASE, &nf);
1132 if (err)1141 if (err)
1133 goto out;1142 goto out;
1143 nn = net_generic(nf->nf_net, nfsd_net_id);
1134 if (EX_ISSYNC(fhp->fh_export)) {1144 if (EX_ISSYNC(fhp->fh_export)) {
1135 int err2 = nfsd_filemap_write_and_wait_range(nf, offset, end);1145 errseq_t since = READ_ONCE(nf->nf_file->f_wb_err);
1146 int err2;
1136 1147
1137 down_write(&nf->nf_rwsem);1148 err2 = vfs_fsync_range(nf->nf_file, offset, end, 0);
1138 if (!err2)
1139 err2 = vfs_fsync_range(nf->nf_file, offset, end, 0);
1140 switch (err2) {1149 switch (err2) {
1141 case 0:1150 case 0:
1142 nfsd_copy_boot_verifier(verf, net_generic(nf->nf_net,1151 nfsd_copy_write_verifier(verf, nn);
1143 nfsd_net_id));1152 err2 = filemap_check_wb_err(nf->nf_file->f_mapping,
1153 since);
1144 break;1154 break;
1145 case -EINVAL:1155 case -EINVAL:
1146 err = nfserr_notsupp;1156 err = nfserr_notsupp;
1147 break;1157 break;
1148 default:1158 default:
1149 err = nfserrno(err2);1159 nfsd_reset_write_verifier(nn);
1150 nfsd_reset_boot_verifier(net_generic(nf->nf_net,1160 trace_nfsd_writeverf_reset(nn, rqstp, err2);
1151 nfsd_net_id));
1152 }1161 }
1153 up_write(&nf->nf_rwsem);1162 err = nfserrno(err2);
1154 } else1163 } else
1155 nfsd_copy_boot_verifier(verf, net_generic(nf->nf_net,1164 nfsd_copy_write_verifier(verf, nn);
1156 nfsd_net_id));
1157 1165
1158 nfsd_file_put(nf);1166 nfsd_file_put(nf);
1159out:1167out:
@@ -1747,8 +1755,8 @@ retry: · 587 unmodified lines
1747 * so do it by hand */1755 * so do it by hand */
1748 trap = lock_rename(tdentry, fdentry);1756 trap = lock_rename(tdentry, fdentry);
1749 ffhp->fh_locked = tfhp->fh_locked = true;1757 ffhp->fh_locked = tfhp->fh_locked = true;
1750 fill_pre_wcc(ffhp);1758 fh_fill_pre_attrs(ffhp);
1751 fill_pre_wcc(tfhp);1759 fh_fill_pre_attrs(tfhp);
1752 1760
1753 odentry = lookup_one_len(fname, fdentry, flen);1761 odentry = lookup_one_len(fname, fdentry, flen);
1754 host_err = PTR_ERR(odentry);1762 host_err = PTR_ERR(odentry);
@@ -1808,8 +1816,8 @@ retry: · 53 unmodified lines
1808 * were the same, so again we do it by hand.1816 * were the same, so again we do it by hand.
1809 */1817 */
1810 if (!close_cached) {1818 if (!close_cached) {
1811 fill_post_wcc(ffhp);1819 fh_fill_post_attrs(ffhp);
1812 fill_post_wcc(tfhp);1820 fh_fill_post_attrs(tfhp);
1813 }1821 }
1814 unlock_rename(tdentry, fdentry);1822 unlock_rename(tdentry, fdentry);
1815 ffhp->fh_locked = tfhp->fh_locked = false;1823 ffhp->fh_locked = tfhp->fh_locked = false;
fs/nfsd/vfs.h+2−1
@@ -57,7 +57,8 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, · 56 unmodified lines
57 struct xdr_netobj *);57 struct xdr_netobj *);
58__be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,58__be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
59 struct file *, loff_t, loff_t, int);59 struct file *, loff_t, loff_t, int);
60__be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,60__be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,
61 struct nfsd_file *nf_src, u64 src_pos,
61 struct nfsd_file *nf_dst, u64 dst_pos,62 struct nfsd_file *nf_dst, u64 dst_pos,
62 u64 count, bool sync);63 u64 count, bool sync);
63#endif /* CONFIG_NFSD_V4 */64#endif /* CONFIG_NFSD_V4 */
include/linux/exportfs.h+0−2
@@ -221,8 +221,6 @@ struct export_operations { · 220 unmodified lines
221#define EXPORT_OP_NOATOMIC_ATTR (0x10) /* Filesystem cannot supply221#define EXPORT_OP_NOATOMIC_ATTR (0x10) /* Filesystem cannot supply
222 atomic attribute updates222 atomic attribute updates
223 */223 */
224#define EXPORT_OP_SYNC_LOCKS (0x20) /* Filesystem can't do
225 asychronous blocking locks */
226 unsigned long flags;224 unsigned long flags;
227};225};
228 226
include/linux/fs.h+2−2
@@ -1221,13 +1221,13 @@ static inline int fcntl_setlk(unsigned int fd, struct file *file, · 1220 unmodified lines
1221 1221
1222#if BITS_PER_LONG == 321222#if BITS_PER_LONG == 32
1223static inline int fcntl_getlk64(struct file *file, unsigned int cmd,1223static inline int fcntl_getlk64(struct file *file, unsigned int cmd,
1224 struct flock64 __user *user)1224 struct flock64 *user)
1225{1225{
1226 return -EINVAL;1226 return -EINVAL;
1227}1227}
1228 1228
1229static inline int fcntl_setlk64(unsigned int fd, struct file *file,1229static inline int fcntl_setlk64(unsigned int fd, struct file *file,
1230 unsigned int cmd, struct flock64 __user *user)1230 unsigned int cmd, struct flock64 *user)
1231{1231{
1232 return -EACCES;1232 return -EACCES;
1233}1233}
include/linux/lockd/lockd.h+7−2
@@ -303,10 +303,15 @@ void nlmsvc_invalidate_all(void); · 302 unmodified lines
303int nlmsvc_unlock_all_by_sb(struct super_block *sb);303int nlmsvc_unlock_all_by_sb(struct super_block *sb);
304int nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr);304int nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr);
305 305
306static inline struct file *nlmsvc_file_file(struct nlm_file *file)
307{
308 return file->f_file[O_RDONLY] ?
309 file->f_file[O_RDONLY] : file->f_file[O_WRONLY];
310}
311
306static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)312static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
307{313{
308 return locks_inode(file->f_file[O_RDONLY] ?314 return locks_inode(nlmsvc_file_file(file));
309 file->f_file[O_RDONLY] : file->f_file[O_WRONLY]);
310}315}
311 316
312static inline int __nlm_privileged_request4(const struct sockaddr *sap)317static inline int __nlm_privileged_request4(const struct sockaddr *sap)
include/linux/sunrpc/svc.h+39−40
@@ -64,10 +64,9 @@ struct svc_serv_ops { · 63 unmodified lines
64 /* queue up a transport for servicing */64 /* queue up a transport for servicing */
65 void (*svo_enqueue_xprt)(struct svc_xprt *);65 void (*svo_enqueue_xprt)(struct svc_xprt *);
66 66
67 /* set up thread (or whatever) execution context */67 /* optional module to count when adding threads.
68 int (*svo_setup)(struct svc_serv *, struct svc_pool *, int);68 * Thread function must call module_put_and_exit() to exit.
69 69 */
70 /* optional module to count when adding threads (pooled svcs only) */
71 struct module *svo_module;70 struct module *svo_module;
72};71};
73 72
@@ -85,6 +84,7 @@ struct svc_serv { · 11 unmodified lines
85 struct svc_program * sv_program; /* RPC program */84 struct svc_program * sv_program; /* RPC program */
86 struct svc_stat * sv_stats; /* RPC statistics */85 struct svc_stat * sv_stats; /* RPC statistics */
87 spinlock_t sv_lock;86 spinlock_t sv_lock;
87 struct kref sv_refcnt;
88 unsigned int sv_nrthreads; /* # of server threads */88 unsigned int sv_nrthreads; /* # of server threads */
89 unsigned int sv_maxconn; /* max connections allowed or89 unsigned int sv_maxconn; /* max connections allowed or
90 * '0' causing max to be based90 * '0' causing max to be based
@@ -114,15 +114,43 @@ struct svc_serv { · 23 unmodified lines
114#endif /* CONFIG_SUNRPC_BACKCHANNEL */114#endif /* CONFIG_SUNRPC_BACKCHANNEL */
115};115};
116 116
117/*117/**
118 * We use sv_nrthreads as a reference count. svc_destroy() drops118 * svc_get() - increment reference count on a SUNRPC serv
119 * this refcount, so we need to bump it up around operations that119 * @serv: the svc_serv to have count incremented
120 * change the number of threads. Horrible, but there it is.120 *
121 * Should be called with the "service mutex" held.121 * Returns: the svc_serv that was passed in.
122 */
123static inline struct svc_serv *svc_get(struct svc_serv *serv)
124{
125 kref_get(&serv->sv_refcnt);
126 return serv;
127}
128
129void svc_destroy(struct kref *);
130
131/**
132 * svc_put - decrement reference count on a SUNRPC serv
133 * @serv: the svc_serv to have count decremented
134 *
135 * When the reference count reaches zero, svc_destroy()
136 * is called to clean up and free the serv.
137 */
138static inline void svc_put(struct svc_serv *serv)
139{
140 kref_put(&serv->sv_refcnt, svc_destroy);
141}
142
143/**
144 * svc_put_not_last - decrement non-final reference count on SUNRPC serv
145 * @serv: the svc_serv to have count decremented
146 *
147 * Returns: %true is refcount was decremented.
148 *
149 * If the refcount is 1, it is not decremented and instead failure is reported.
122 */150 */
123static inline void svc_get(struct svc_serv *serv)151static inline bool svc_put_not_last(struct svc_serv *serv)
124{152{
125 serv->sv_nrthreads++;153 return refcount_dec_not_one(&serv->sv_refcnt.refcount);
126}154}
127 155
128/*156/*
@@ -468,29 +496,6 @@ struct svc_procedure { · 339 unmodified lines
468 const char * pc_name; /* for display */496 const char * pc_name; /* for display */
469};497};
470 498
471/*
472 * Mode for mapping cpus to pools.
473 */
474enum {
475 SVC_POOL_AUTO = -1, /* choose one of the others */
476 SVC_POOL_GLOBAL, /* no mapping, just a single global pool
477 * (legacy & UP mode) */
478 SVC_POOL_PERCPU, /* one pool per cpu */
479 SVC_POOL_PERNODE /* one pool per numa node */
480};
481
482struct svc_pool_map {
483 int count; /* How many svc_servs use us */
484 int mode; /* Note: int not enum to avoid
485 * warnings about "enumeration value
486 * not handled in switch" */
487 unsigned int npools;
488 unsigned int *pool_to; /* maps pool id to cpu or node */
489 unsigned int *to_pool; /* maps cpu or node to pool id */
490};
491
492extern struct svc_pool_map svc_pool_map;
493
494/*499/*
495 * Function prototypes.500 * Function prototypes.
496 */501 */
@@ -501,20 +506,14 @@ struct svc_serv *svc_create(struct svc_program *, unsigned int, · 4 unmodified lines
501 const struct svc_serv_ops *);506 const struct svc_serv_ops *);
502struct svc_rqst *svc_rqst_alloc(struct svc_serv *serv,507struct svc_rqst *svc_rqst_alloc(struct svc_serv *serv,
503 struct svc_pool *pool, int node);508 struct svc_pool *pool, int node);
504struct svc_rqst *svc_prepare_thread(struct svc_serv *serv,
505 struct svc_pool *pool, int node);
506void svc_rqst_replace_page(struct svc_rqst *rqstp,509void svc_rqst_replace_page(struct svc_rqst *rqstp,
507 struct page *page);510 struct page *page);
508void svc_rqst_free(struct svc_rqst *);511void svc_rqst_free(struct svc_rqst *);
509void svc_exit_thread(struct svc_rqst *);512void svc_exit_thread(struct svc_rqst *);
510unsigned int svc_pool_map_get(void);
511void svc_pool_map_put(void);
512struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int,513struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int,
513 const struct svc_serv_ops *);514 const struct svc_serv_ops *);
514int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);515int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
515int svc_set_num_threads_sync(struct svc_serv *, struct svc_pool *, int);
516int svc_pool_stats_open(struct svc_serv *serv, struct file *file);516int svc_pool_stats_open(struct svc_serv *serv, struct file *file);
517void svc_destroy(struct svc_serv *);
518void svc_shutdown_net(struct svc_serv *, struct net *);517void svc_shutdown_net(struct svc_serv *, struct net *);
519int svc_process(struct svc_rqst *);518int svc_process(struct svc_rqst *);
520int bc_svc_process(struct svc_serv *, struct rpc_rqst *,519int bc_svc_process(struct svc_serv *, struct rpc_rqst *,
include/trace/events/sunrpc.h+8−29
@@ -1744,10 +1744,11 @@ TRACE_EVENT(svc_xprt_create_err, · 1743 unmodified lines
1744 const char *program,1744 const char *program,
1745 const char *protocol,1745 const char *protocol,
1746 struct sockaddr *sap,1746 struct sockaddr *sap,
1747 size_t salen,
1747 const struct svc_xprt *xprt1748 const struct svc_xprt *xprt
1748 ),1749 ),
1749 1750
1750 TP_ARGS(program, protocol, sap, xprt),1751 TP_ARGS(program, protocol, sap, salen, xprt),
1751 1752
1752 TP_STRUCT__entry(1753 TP_STRUCT__entry(
1753 __field(long, error)1754 __field(long, error)
@@ -1760,7 +1761,7 @@ TRACE_EVENT(svc_xprt_create_err, · 6 unmodified lines
1760 __entry->error = PTR_ERR(xprt);1761 __entry->error = PTR_ERR(xprt);
1761 __assign_str(program, program);1762 __assign_str(program, program);
1762 __assign_str(protocol, protocol);1763 __assign_str(protocol, protocol);
1763 memcpy(__entry->addr, sap, sizeof(__entry->addr));1764 memcpy(__entry->addr, sap, min(salen, sizeof(__entry->addr)));
1764 ),1765 ),
1765 1766
1766 TP_printk("addr=%pISpc program=%s protocol=%s error=%ld",1767 TP_printk("addr=%pISpc program=%s protocol=%s error=%ld",
@@ -1768,7 +1769,7 @@ TRACE_EVENT(svc_xprt_create_err, · 1 unmodified line
1768 __entry->error)1769 __entry->error)
1769);1770);
1770 1771
1771TRACE_EVENT(svc_xprt_do_enqueue,1772TRACE_EVENT(svc_xprt_enqueue,
1772 TP_PROTO(struct svc_xprt *xprt, struct svc_rqst *rqst),1773 TP_PROTO(struct svc_xprt *xprt, struct svc_rqst *rqst),
1773 1774
1774 TP_ARGS(xprt, rqst),1775 TP_ARGS(xprt, rqst),
@@ -1815,7 +1816,6 @@ DECLARE_EVENT_CLASS(svc_xprt_event, · 40 unmodified lines
1815 ), \1816 ), \
1816 TP_ARGS(xprt))1817 TP_ARGS(xprt))
1817 1818
1818DEFINE_SVC_XPRT_EVENT(received);
1819DEFINE_SVC_XPRT_EVENT(no_write_space);1819DEFINE_SVC_XPRT_EVENT(no_write_space);
1820DEFINE_SVC_XPRT_EVENT(close);1820DEFINE_SVC_XPRT_EVENT(close);
1821DEFINE_SVC_XPRT_EVENT(detach);1821DEFINE_SVC_XPRT_EVENT(detach);
@@ -1902,27 +1902,6 @@ TRACE_EVENT(svc_alloc_arg_err, · 80 unmodified lines
1902 TP_printk("pages=%u", __entry->pages)1902 TP_printk("pages=%u", __entry->pages)
1903);1903);
1904 1904
1905TRACE_EVENT(svc_handle_xprt,
1906 TP_PROTO(struct svc_xprt *xprt, int len),
1907
1908 TP_ARGS(xprt, len),
1909
1910 TP_STRUCT__entry(
1911 __field(int, len)
1912 __field(unsigned long, flags)
1913 __string(addr, xprt->xpt_remotebuf)
1914 ),
1915
1916 TP_fast_assign(
1917 __entry->len = len;
1918 __entry->flags = xprt->xpt_flags;
1919 __assign_str(addr, xprt->xpt_remotebuf);
1920 ),
1921
1922 TP_printk("addr=%s len=%d flags=%s", __get_str(addr),
1923 __entry->len, show_svc_xprt_flags(__entry->flags))
1924);
1925
1926TRACE_EVENT(svc_stats_latency,1905TRACE_EVENT(svc_stats_latency,
1927 TP_PROTO(const struct svc_rqst *rqst),1906 TP_PROTO(const struct svc_rqst *rqst),
1928 1907
@@ -2146,17 +2125,17 @@ DECLARE_EVENT_CLASS(svcsock_accept_class, · 217 unmodified lines
2146 TP_STRUCT__entry(2125 TP_STRUCT__entry(
2147 __field(long, status)2126 __field(long, status)
2148 __string(service, service)2127 __string(service, service)
2149 __array(unsigned char, addr, sizeof(struct sockaddr_in6))2128 __field(unsigned int, netns_ino)
2150 ),2129 ),
2151 2130
2152 TP_fast_assign(2131 TP_fast_assign(
2153 __entry->status = status;2132 __entry->status = status;
2154 __assign_str(service, service);2133 __assign_str(service, service);
2155 memcpy(__entry->addr, &xprt->xpt_local, sizeof(__entry->addr));2134 __entry->netns_ino = xprt->xpt_net->ns.inum;
2156 ),2135 ),
2157 2136
2158 TP_printk("listener=%pISpc service=%s status=%ld",2137 TP_printk("addr=listener service=%s status=%ld",
2159 __entry->addr, __get_str(service), __entry->status2138 __get_str(service), __entry->status
2160 )2139 )
2161);2140);
2162 2141
net/sunrpc/svc.c+74−101
@@ -37,18 +37,37 @@ · 36 unmodified lines
37 37
38static void svc_unregister(const struct svc_serv *serv, struct net *net);38static void svc_unregister(const struct svc_serv *serv, struct net *net);
39 39
40#define svc_serv_is_pooled(serv) ((serv)->sv_ops->svo_function)
41
42#define SVC_POOL_DEFAULT SVC_POOL_GLOBAL40#define SVC_POOL_DEFAULT SVC_POOL_GLOBAL
43 41
42/*
43 * Mode for mapping cpus to pools.
44 */
45enum {
46 SVC_POOL_AUTO = -1, /* choose one of the others */
47 SVC_POOL_GLOBAL, /* no mapping, just a single global pool
48 * (legacy & UP mode) */
49 SVC_POOL_PERCPU, /* one pool per cpu */
50 SVC_POOL_PERNODE /* one pool per numa node */
51};
52
44/*53/*
45 * Structure for mapping cpus to pools and vice versa.54 * Structure for mapping cpus to pools and vice versa.
46 * Setup once during sunrpc initialisation.55 * Setup once during sunrpc initialisation.
47 */56 */
48struct svc_pool_map svc_pool_map = {57
58struct svc_pool_map {
59 int count; /* How many svc_servs use us */
60 int mode; /* Note: int not enum to avoid
61 * warnings about "enumeration value
62 * not handled in switch" */
63 unsigned int npools;
64 unsigned int *pool_to; /* maps pool id to cpu or node */
65 unsigned int *to_pool; /* maps cpu or node to pool id */
66};
67
68static struct svc_pool_map svc_pool_map = {
49 .mode = SVC_POOL_DEFAULT69 .mode = SVC_POOL_DEFAULT
50};70};
51EXPORT_SYMBOL_GPL(svc_pool_map);
52 71
53static DEFINE_MUTEX(svc_pool_map_mutex);/* protects svc_pool_map.count only */72static DEFINE_MUTEX(svc_pool_map_mutex);/* protects svc_pool_map.count only */
54 73
@@ -219,10 +238,12 @@ svc_pool_map_init_pernode(struct svc_pool_map *m) · 164 unmodified lines
219 238
220/*239/*
221 * Add a reference to the global map of cpus to pools (and240 * Add a reference to the global map of cpus to pools (and
222 * vice versa). Initialise the map if we're the first user.241 * vice versa) if pools are in use.
223 * Returns the number of pools.242 * Initialise the map if we're the first user.
243 * Returns the number of pools. If this is '1', no reference
244 * was taken.
224 */245 */
225unsigned int246static unsigned int
226svc_pool_map_get(void)247svc_pool_map_get(void)
227{248{
228 struct svc_pool_map *m = &svc_pool_map;249 struct svc_pool_map *m = &svc_pool_map;
@@ -232,6 +253,7 @@ svc_pool_map_get(void) · 3 unmodified lines
232 253
233 if (m->count++) {254 if (m->count++) {
234 mutex_unlock(&svc_pool_map_mutex);255 mutex_unlock(&svc_pool_map_mutex);
256 WARN_ON_ONCE(m->npools <= 1);
235 return m->npools;257 return m->npools;
236 }258 }
237 259
@@ -247,30 +269,36 @@ svc_pool_map_get(void) · 9 unmodified lines
247 break;269 break;
248 }270 }
249 271
250 if (npools < 0) {272 if (npools <= 0) {
251 /* default, or memory allocation failure */273 /* default, or memory allocation failure */
252 npools = 1;274 npools = 1;
253 m->mode = SVC_POOL_GLOBAL;275 m->mode = SVC_POOL_GLOBAL;
254 }276 }
255 m->npools = npools;277 m->npools = npools;
256 278
279 if (npools == 1)
280 /* service is unpooled, so doesn't hold a reference */
281 m->count--;
282
257 mutex_unlock(&svc_pool_map_mutex);283 mutex_unlock(&svc_pool_map_mutex);
258 return m->npools;284 return npools;
259}285}
260EXPORT_SYMBOL_GPL(svc_pool_map_get);
261 286
262/*287/*
263 * Drop a reference to the global map of cpus to pools.288 * Drop a reference to the global map of cpus to pools, if
289 * pools were in use, i.e. if npools > 1.
264 * When the last reference is dropped, the map data is290 * When the last reference is dropped, the map data is
265 * freed; this allows the sysadmin to change the pool291 * freed; this allows the sysadmin to change the pool
266 * mode using the pool_mode module option without292 * mode using the pool_mode module option without
267 * rebooting or re-loading sunrpc.ko.293 * rebooting or re-loading sunrpc.ko.
268 */294 */
269void295static void
270svc_pool_map_put(void)296svc_pool_map_put(int npools)
271{297{
272 struct svc_pool_map *m = &svc_pool_map;298 struct svc_pool_map *m = &svc_pool_map;
273 299
300 if (npools <= 1)
301 return;
274 mutex_lock(&svc_pool_map_mutex);302 mutex_lock(&svc_pool_map_mutex);
275 303
276 if (!--m->count) {304 if (!--m->count) {
@@ -283,7 +311,6 @@ svc_pool_map_put(void) · 6 unmodified lines
283 311
284 mutex_unlock(&svc_pool_map_mutex);312 mutex_unlock(&svc_pool_map_mutex);
285}313}
286EXPORT_SYMBOL_GPL(svc_pool_map_put);
287 314
288static int svc_pool_map_get_node(unsigned int pidx)315static int svc_pool_map_get_node(unsigned int pidx)
289{316{
@@ -340,21 +367,18 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu) · 50 unmodified lines
340 struct svc_pool_map *m = &svc_pool_map;367 struct svc_pool_map *m = &svc_pool_map;
341 unsigned int pidx = 0;368 unsigned int pidx = 0;
342 369
343 /*370 if (serv->sv_nrpools <= 1)
344 * An uninitialised map happens in a pure client when371 return serv->sv_pools;
345 * lockd is brought up, so silently treat it the372
346 * same as SVC_POOL_GLOBAL.373 switch (m->mode) {
347 */374 case SVC_POOL_PERCPU:
348 if (svc_serv_is_pooled(serv)) {375 pidx = m->to_pool[cpu];
349 switch (m->mode) {376 break;
350 case SVC_POOL_PERCPU:377 case SVC_POOL_PERNODE:
351 pidx = m->to_pool[cpu];378 pidx = m->to_pool[cpu_to_node(cpu)];
352 break;379 break;
353 case SVC_POOL_PERNODE:
354 pidx = m->to_pool[cpu_to_node(cpu)];
355 break;
356 }
357 }380 }
381
358 return &serv->sv_pools[pidx % serv->sv_nrpools];382 return &serv->sv_pools[pidx % serv->sv_nrpools];
359}383}
360 384
@@ -435,7 +459,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, · 74 unmodified lines
435 return NULL;459 return NULL;
436 serv->sv_name = prog->pg_name;460 serv->sv_name = prog->pg_name;
437 serv->sv_program = prog;461 serv->sv_program = prog;
438 serv->sv_nrthreads = 1;462 kref_init(&serv->sv_refcnt);
439 serv->sv_stats = prog->pg_stats;463 serv->sv_stats = prog->pg_stats;
440 if (bufsize > RPCSVC_MAXPAYLOAD)464 if (bufsize > RPCSVC_MAXPAYLOAD)
441 bufsize = RPCSVC_MAXPAYLOAD;465 bufsize = RPCSVC_MAXPAYLOAD;
@@ -507,7 +531,7 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize, · 65 unmodified lines
507 goto out_err;531 goto out_err;
508 return serv;532 return serv;
509out_err:533out_err:
510 svc_pool_map_put();534 svc_pool_map_put(npools);
511 return NULL;535 return NULL;
512}536}
513EXPORT_SYMBOL_GPL(svc_create_pooled);537EXPORT_SYMBOL_GPL(svc_create_pooled);
@@ -523,23 +547,14 @@ EXPORT_SYMBOL_GPL(svc_shutdown_net); · 9 unmodified lines
523 547
524/*548/*
525 * Destroy an RPC service. Should be called with appropriate locking to549 * Destroy an RPC service. Should be called with appropriate locking to
526 * protect the sv_nrthreads, sv_permsocks and sv_tempsocks.550 * protect sv_permsocks and sv_tempsocks.
527 */551 */
528void552void
529svc_destroy(struct svc_serv *serv)553svc_destroy(struct kref *ref)
530{554{
531 dprintk("svc: svc_destroy(%s, %d)\n",555 struct svc_serv *serv = container_of(ref, struct svc_serv, sv_refcnt);
532 serv->sv_program->pg_name,
533 serv->sv_nrthreads);
534
535 if (serv->sv_nrthreads) {
536 if (--(serv->sv_nrthreads) != 0) {
537 svc_sock_update_bufs(serv);
538 return;
539 }
540 } else
541 printk("svc_destroy: no threads for serv=%p!\n", serv);
542 556
557 dprintk("svc: svc_destroy(%s)\n", serv->sv_program->pg_name);
543 del_timer_sync(&serv->sv_temptimer);558 del_timer_sync(&serv->sv_temptimer);
544 559
545 /*560 /*
@@ -551,8 +566,7 @@ svc_destroy(struct svc_serv *serv) · 5 unmodified lines
551 566
552 cache_clean_deferred(serv);567 cache_clean_deferred(serv);
553 568
554 if (svc_serv_is_pooled(serv))569 svc_pool_map_put(serv->sv_nrpools);
555 svc_pool_map_put();
556 570
557 kfree(serv->sv_pools);571 kfree(serv->sv_pools);
558 kfree(serv);572 kfree(serv);
@@ -638,7 +652,7 @@ out_enomem: · 79 unmodified lines
638}652}
639EXPORT_SYMBOL_GPL(svc_rqst_alloc);653EXPORT_SYMBOL_GPL(svc_rqst_alloc);
640 654
641struct svc_rqst *655static struct svc_rqst *
642svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node)656svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node)
643{657{
644 struct svc_rqst *rqstp;658 struct svc_rqst *rqstp;
@@ -647,14 +661,17 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node) · 2 unmodified lines
647 if (!rqstp)661 if (!rqstp)
648 return ERR_PTR(-ENOMEM);662 return ERR_PTR(-ENOMEM);
649 663
650 serv->sv_nrthreads++;664 svc_get(serv);
665 spin_lock_bh(&serv->sv_lock);
666 serv->sv_nrthreads += 1;
667 spin_unlock_bh(&serv->sv_lock);
668
651 spin_lock_bh(&pool->sp_lock);669 spin_lock_bh(&pool->sp_lock);
652 pool->sp_nrthreads++;670 pool->sp_nrthreads++;
653 list_add_rcu(&rqstp->rq_all, &pool->sp_all_threads);671 list_add_rcu(&rqstp->rq_all, &pool->sp_all_threads);
654 spin_unlock_bh(&pool->sp_lock);672 spin_unlock_bh(&pool->sp_lock);
655 return rqstp;673 return rqstp;
656}674}
657EXPORT_SYMBOL_GPL(svc_prepare_thread);
658 675
659/*676/*
660 * Choose a pool in which to create a new thread, for svc_set_num_threads677 * Choose a pool in which to create a new thread, for svc_set_num_threads
@@ -748,59 +765,13 @@ svc_start_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) · 87 unmodified lines
748 return 0;765 return 0;
749}766}
750 767
751
752/* destroy old threads */
753static int
754svc_signal_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
755{
756 struct task_struct *task;
757 unsigned int state = serv->sv_nrthreads-1;
758
759 /* destroy old threads */
760 do {
761 task = choose_victim(serv, pool, &state);
762 if (task == NULL)
763 break;
764 send_sig(SIGINT, task, 1);
765 nrservs++;
766 } while (nrservs < 0);
767
768 return 0;
769}
770
771/*768/*
772 * Create or destroy enough new threads to make the number769 * Create or destroy enough new threads to make the number
773 * of threads the given number. If `pool' is non-NULL, applies770 * of threads the given number. If `pool' is non-NULL, applies
774 * only to threads in that pool, otherwise round-robins between771 * only to threads in that pool, otherwise round-robins between
775 * all pools. Caller must ensure that mutual exclusion between this and772 * all pools. Caller must ensure that mutual exclusion between this and
776 * server startup or shutdown.773 * server startup or shutdown.
777 *
778 * Destroying threads relies on the service threads filling in
779 * rqstp->rq_task, which only the nfs ones do. Assumes the serv
780 * has been created using svc_create_pooled().
781 *
782 * Based on code that used to be in nfsd_svc() but tweaked
783 * to be pool-aware.
784 */774 */
785int
786svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
787{
788 if (pool == NULL) {
789 /* The -1 assumes caller has done a svc_get() */
790 nrservs -= (serv->sv_nrthreads-1);
791 } else {
792 spin_lock_bh(&pool->sp_lock);
793 nrservs -= pool->sp_nrthreads;
794 spin_unlock_bh(&pool->sp_lock);
795 }
796
797 if (nrservs > 0)
798 return svc_start_kthreads(serv, pool, nrservs);
799 if (nrservs < 0)
800 return svc_signal_kthreads(serv, pool, nrservs);
801 return 0;
802}
803EXPORT_SYMBOL_GPL(svc_set_num_threads);
804 775
805/* destroy old threads */776/* destroy old threads */
806static int777static int
@@ -821,11 +792,10 @@ svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) · 14 unmodified lines
821}792}
822 793
823int794int
824svc_set_num_threads_sync(struct svc_serv *serv, struct svc_pool *pool, int nrservs)795svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
825{796{
826 if (pool == NULL) {797 if (pool == NULL) {
827 /* The -1 assumes caller has done a svc_get() */798 nrservs -= serv->sv_nrthreads;
828 nrservs -= (serv->sv_nrthreads-1);
829 } else {799 } else {
830 spin_lock_bh(&pool->sp_lock);800 spin_lock_bh(&pool->sp_lock);
831 nrservs -= pool->sp_nrthreads;801 nrservs -= pool->sp_nrthreads;
@@ -838,7 +808,7 @@ svc_set_num_threads_sync(struct svc_serv *serv, struct svc_pool *pool, int nrser · 6 unmodified lines
838 return svc_stop_kthreads(serv, pool, nrservs);808 return svc_stop_kthreads(serv, pool, nrservs);
839 return 0;809 return 0;
840}810}
841EXPORT_SYMBOL_GPL(svc_set_num_threads_sync);811EXPORT_SYMBOL_GPL(svc_set_num_threads);
842 812
843/**813/**
844 * svc_rqst_replace_page - Replace one page in rq_pages[]814 * svc_rqst_replace_page - Replace one page in rq_pages[]
@@ -890,11 +860,14 @@ svc_exit_thread(struct svc_rqst *rqstp) · 45 unmodified lines
890 list_del_rcu(&rqstp->rq_all);860 list_del_rcu(&rqstp->rq_all);
891 spin_unlock_bh(&pool->sp_lock);861 spin_unlock_bh(&pool->sp_lock);
892 862
863 spin_lock_bh(&serv->sv_lock);
864 serv->sv_nrthreads -= 1;
865 spin_unlock_bh(&serv->sv_lock);
866 svc_sock_update_bufs(serv);
867
893 svc_rqst_free(rqstp);868 svc_rqst_free(rqstp);
894 869
895 /* Release the server */870 svc_put(serv);
896 if (serv)
897 svc_destroy(serv);
898}871}
899EXPORT_SYMBOL_GPL(svc_exit_thread);872EXPORT_SYMBOL_GPL(svc_exit_thread);
900 873
net/sunrpc/svc_xprt.c+3−5
@@ -244,7 +244,7 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, · 243 unmodified lines
244 xprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);244 xprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
245 if (IS_ERR(xprt))245 if (IS_ERR(xprt))
246 trace_svc_xprt_create_err(serv->sv_program->pg_name,246 trace_svc_xprt_create_err(serv->sv_program->pg_name,
247 xcl->xcl_name, sap, xprt);247 xcl->xcl_name, sap, len, xprt);
248 return xprt;248 return xprt;
249}249}
250 250
@@ -265,8 +265,6 @@ void svc_xprt_received(struct svc_xprt *xprt) · 14 unmodified lines
265 return;265 return;
266 }266 }
267 267
268 trace_svc_xprt_received(xprt);
269
270 /* As soon as we clear busy, the xprt could be closed and268 /* As soon as we clear busy, the xprt could be closed and
271 * 'put', so we need a reference to call svc_enqueue_xprt with:269 * 'put', so we need a reference to call svc_enqueue_xprt with:
272 */270 */
@@ -467,7 +465,7 @@ void svc_xprt_do_enqueue(struct svc_xprt *xprt) · 194 unmodified lines
467out_unlock:465out_unlock:
468 rcu_read_unlock();466 rcu_read_unlock();
469 put_cpu();467 put_cpu();
470 trace_svc_xprt_do_enqueue(xprt, rqstp);468 trace_svc_xprt_enqueue(xprt, rqstp);
471}469}
472EXPORT_SYMBOL_GPL(svc_xprt_do_enqueue);470EXPORT_SYMBOL_GPL(svc_xprt_do_enqueue);
473 471
@@ -843,8 +841,8 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt) · 369 unmodified lines
843 atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);841 atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
844 } else842 } else
845 svc_xprt_received(xprt);843 svc_xprt_received(xprt);
844
846out:845out:
847 trace_svc_handle_xprt(xprt, len);
848 return len;846 return len;
849}847}
850 848