Skip to content

Commit

Permalink
Merge tag 'nfsd-5.17' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/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
  ...
  • Loading branch information
torvalds committed Jan 16, 2022
2 parents 49ad227 + 1672086 commit 175398a
Show file tree
Hide file tree
Showing 33 changed files with 702 additions and 749 deletions.
4 changes: 1 addition & 3 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -7417,7 +7417,6 @@ F: include/uapi/scsi/fc/

FILE LOCKING (flock() and fcntl()/lockf())
M: Jeff Layton <[email protected]>
M: "J. Bruce Fields" <[email protected]>
L: [email protected]
S: Maintained
F: fs/fcntl.c
Expand Down Expand Up @@ -10428,12 +10427,11 @@ S: Odd Fixes
W: http://kernelnewbies.org/KernelJanitors

KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
M: "J. Bruce Fields" <[email protected]>
M: Chuck Lever <[email protected]>
L: [email protected]
S: Supported
W: http://nfs.sourceforge.net/
T: git git://linux-nfs.org/~bfields/linux.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux.git
F: fs/lockd/
F: fs/nfs_common/
F: fs/nfsd/
Expand Down
200 changes: 61 additions & 139 deletions fs/lockd/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,9 @@ EXPORT_SYMBOL_GPL(nlmsvc_ops);

static DEFINE_MUTEX(nlmsvc_mutex);
static unsigned int nlmsvc_users;
static struct task_struct *nlmsvc_task;
static struct svc_rqst *nlmsvc_rqst;
static struct svc_serv *nlmsvc_serv;
unsigned long nlmsvc_timeout;

static atomic_t nlm_ntf_refcnt = ATOMIC_INIT(0);
static DECLARE_WAIT_QUEUE_HEAD(nlm_ntf_wq);

unsigned int lockd_net_id;

/*
Expand Down Expand Up @@ -184,7 +180,12 @@ lockd(void *vrqstp)
nlm_shutdown_hosts();
cancel_delayed_work_sync(&ln->grace_period_end);
locks_end_grace(&ln->lockd_manager);
return 0;

dprintk("lockd_down: service stopped\n");

svc_exit_thread(rqstp);

module_put_and_exit(0);
}

static int create_lockd_listener(struct svc_serv *serv, const char *name,
Expand Down Expand Up @@ -290,8 +291,8 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net)
__func__, net->ns.inum);
}
} else {
pr_err("%s: no users! task=%p, net=%x\n",
__func__, nlmsvc_task, net->ns.inum);
pr_err("%s: no users! net=%x\n",
__func__, net->ns.inum);
BUG();
}
}
Expand All @@ -302,20 +303,16 @@ static int lockd_inetaddr_event(struct notifier_block *this,
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
struct sockaddr_in sin;

if ((event != NETDEV_DOWN) ||
!atomic_inc_not_zero(&nlm_ntf_refcnt))
if (event != NETDEV_DOWN)
goto out;

if (nlmsvc_rqst) {
if (nlmsvc_serv) {
dprintk("lockd_inetaddr_event: removed %pI4\n",
&ifa->ifa_local);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ifa->ifa_local;
svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
(struct sockaddr *)&sin);
svc_age_temp_xprts_now(nlmsvc_serv, (struct sockaddr *)&sin);
}
atomic_dec(&nlm_ntf_refcnt);
wake_up(&nlm_ntf_wq);

out:
return NOTIFY_DONE;
Expand All @@ -332,21 +329,17 @@ static int lockd_inet6addr_event(struct notifier_block *this,
struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
struct sockaddr_in6 sin6;

if ((event != NETDEV_DOWN) ||
!atomic_inc_not_zero(&nlm_ntf_refcnt))
if (event != NETDEV_DOWN)
goto out;

if (nlmsvc_rqst) {
if (nlmsvc_serv) {
dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr);
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = ifa->addr;
if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
sin6.sin6_scope_id = ifa->idev->dev->ifindex;
svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
(struct sockaddr *)&sin6);
svc_age_temp_xprts_now(nlmsvc_serv, (struct sockaddr *)&sin6);
}
atomic_dec(&nlm_ntf_refcnt);
wake_up(&nlm_ntf_wq);

out:
return NOTIFY_DONE;
Expand All @@ -357,86 +350,22 @@ static struct notifier_block lockd_inet6addr_notifier = {
};
#endif

static void lockd_unregister_notifiers(void)
{
unregister_inetaddr_notifier(&lockd_inetaddr_notifier);
#if IS_ENABLED(CONFIG_IPV6)
unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
#endif
wait_event(nlm_ntf_wq, atomic_read(&nlm_ntf_refcnt) == 0);
}

static void lockd_svc_exit_thread(void)
{
atomic_dec(&nlm_ntf_refcnt);
lockd_unregister_notifiers();
svc_exit_thread(nlmsvc_rqst);
}

static int lockd_start_svc(struct svc_serv *serv)
{
int error;

if (nlmsvc_rqst)
return 0;

/*
* Create the kernel thread and wait for it to start.
*/
nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
if (IS_ERR(nlmsvc_rqst)) {
error = PTR_ERR(nlmsvc_rqst);
printk(KERN_WARNING
"lockd_up: svc_rqst allocation failed, error=%d\n",
error);
lockd_unregister_notifiers();
goto out_rqst;
}

atomic_inc(&nlm_ntf_refcnt);
svc_sock_update_bufs(serv);
serv->sv_maxconn = nlm_max_connections;

nlmsvc_task = kthread_create(lockd, nlmsvc_rqst, "%s", serv->sv_name);
if (IS_ERR(nlmsvc_task)) {
error = PTR_ERR(nlmsvc_task);
printk(KERN_WARNING
"lockd_up: kthread_run failed, error=%d\n", error);
goto out_task;
}
nlmsvc_rqst->rq_task = nlmsvc_task;
wake_up_process(nlmsvc_task);

dprintk("lockd_up: service started\n");
return 0;

out_task:
lockd_svc_exit_thread();
nlmsvc_task = NULL;
out_rqst:
nlmsvc_rqst = NULL;
return error;
}

static const struct svc_serv_ops lockd_sv_ops = {
.svo_shutdown = svc_rpcb_cleanup,
.svo_function = lockd,
.svo_enqueue_xprt = svc_xprt_do_enqueue,
.svo_module = THIS_MODULE,
};

static struct svc_serv *lockd_create_svc(void)
static int lockd_get(void)
{
struct svc_serv *serv;
int error;

/*
* Check whether we're already up and running.
*/
if (nlmsvc_rqst) {
/*
* Note: increase service usage, because later in case of error
* svc_destroy() will be called.
*/
svc_get(nlmsvc_rqst->rq_server);
return nlmsvc_rqst->rq_server;
if (nlmsvc_serv) {
svc_get(nlmsvc_serv);
nlmsvc_users++;
return 0;
}

/*
Expand All @@ -454,51 +383,63 @@ static struct svc_serv *lockd_create_svc(void)
serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, &lockd_sv_ops);
if (!serv) {
printk(KERN_WARNING "lockd_up: create service failed\n");
return ERR_PTR(-ENOMEM);
return -ENOMEM;
}

serv->sv_maxconn = nlm_max_connections;
error = svc_set_num_threads(serv, NULL, 1);
/* The thread now holds the only reference */
svc_put(serv);
if (error < 0)
return error;

nlmsvc_serv = serv;
register_inetaddr_notifier(&lockd_inetaddr_notifier);
#if IS_ENABLED(CONFIG_IPV6)
register_inet6addr_notifier(&lockd_inet6addr_notifier);
#endif
dprintk("lockd_up: service created\n");
return serv;
nlmsvc_users++;
return 0;
}

static void lockd_put(void)
{
if (WARN(nlmsvc_users <= 0, "lockd_down: no users!\n"))
return;
if (--nlmsvc_users)
return;

unregister_inetaddr_notifier(&lockd_inetaddr_notifier);
#if IS_ENABLED(CONFIG_IPV6)
unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
#endif

svc_set_num_threads(nlmsvc_serv, NULL, 0);
nlmsvc_serv = NULL;
dprintk("lockd_down: service destroyed\n");
}

/*
* Bring up the lockd process if it's not already up.
*/
int lockd_up(struct net *net, const struct cred *cred)
{
struct svc_serv *serv;
int error;

mutex_lock(&nlmsvc_mutex);

serv = lockd_create_svc();
if (IS_ERR(serv)) {
error = PTR_ERR(serv);
goto err_create;
}
error = lockd_get();
if (error)
goto err;

error = lockd_up_net(serv, net, cred);
error = lockd_up_net(nlmsvc_serv, net, cred);
if (error < 0) {
lockd_unregister_notifiers();
goto err_put;
lockd_put();
goto err;
}

error = lockd_start_svc(serv);
if (error < 0) {
lockd_down_net(serv, net);
goto err_put;
}
nlmsvc_users++;
/*
* Note: svc_serv structures have an initial use count of 1,
* so we exit through here on both success and failure.
*/
err_put:
svc_destroy(serv);
err_create:
err:
mutex_unlock(&nlmsvc_mutex);
return error;
}
Expand All @@ -511,27 +452,8 @@ void
lockd_down(struct net *net)
{
mutex_lock(&nlmsvc_mutex);
lockd_down_net(nlmsvc_rqst->rq_server, net);
if (nlmsvc_users) {
if (--nlmsvc_users)
goto out;
} else {
printk(KERN_ERR "lockd_down: no users! task=%p\n",
nlmsvc_task);
BUG();
}

if (!nlmsvc_task) {
printk(KERN_ERR "lockd_down: no lockd running.\n");
BUG();
}
kthread_stop(nlmsvc_task);
dprintk("lockd_down: service stopped\n");
lockd_svc_exit_thread();
dprintk("lockd_down: service destroyed\n");
nlmsvc_task = NULL;
nlmsvc_rqst = NULL;
out:
lockd_down_net(nlmsvc_serv, net);
lockd_put();
mutex_unlock(&nlmsvc_mutex);
}
EXPORT_SYMBOL_GPL(lockd_down);
Expand Down
6 changes: 4 additions & 2 deletions fs/lockd/svclock.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,10 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
struct nlm_host *host, struct nlm_lock *lock, int wait,
struct nlm_cookie *cookie, int reclaim)
{
struct nlm_block *block = NULL;
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
struct inode *inode = nlmsvc_file_inode(file);
#endif
struct nlm_block *block = NULL;
int error;
int mode;
int async_block = 0;
Expand All @@ -484,7 +486,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
(long long)lock->fl.fl_end,
wait);

if (inode->i_sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS) {
if (nlmsvc_file_file(file)->f_op->lock) {
async_block = wait;
wait = 0;
}
Expand Down
Loading

0 comments on commit 175398a

Please sign in to comment.