nfsd: re-order client tracking method selection

The new order is first nfsdcld, then the UMH upcall, and finally the
legacy tracking method.  Added some printk's to the tracking
initialization functions so it's clear which tracking method was
ultimately selected.

Signed-off-by: Scott Mayhew <smayhew@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
Scott Mayhew 2019-03-26 18:06:29 -04:00 committed by J. Bruce Fields
parent 362063a595
commit 869216075b
1 changed files with 65 additions and 15 deletions

View File

@ -628,6 +628,7 @@ nfsd4_legacy_tracking_init(struct net *net)
status = nfsd4_load_reboot_recovery_data(net); status = nfsd4_load_reboot_recovery_data(net);
if (status) if (status)
goto err; goto err;
printk("NFSD: Using legacy client tracking operations.\n");
return 0; return 0;
err: err:
@ -937,7 +938,7 @@ nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe)
/* Initialize rpc_pipefs pipe for communication with client tracking daemon */ /* Initialize rpc_pipefs pipe for communication with client tracking daemon */
static int static int
nfsd4_init_cld_pipe(struct net *net) __nfsd4_init_cld_pipe(struct net *net)
{ {
int ret; int ret;
struct dentry *dentry; struct dentry *dentry;
@ -980,6 +981,17 @@ err:
return ret; return ret;
} }
static int
nfsd4_init_cld_pipe(struct net *net)
{
int status;
status = __nfsd4_init_cld_pipe(net);
if (!status)
printk("NFSD: Using old nfsdcld client tracking operations.\n");
return status;
}
static void static void
nfsd4_remove_cld_pipe(struct net *net) nfsd4_remove_cld_pipe(struct net *net)
{ {
@ -1285,27 +1297,55 @@ nfs4_cld_state_shutdown(struct net *net)
kfree(nn->reclaim_str_hashtbl); kfree(nn->reclaim_str_hashtbl);
} }
static bool
cld_running(struct nfsd_net *nn)
{
struct cld_net *cn = nn->cld_net;
struct rpc_pipe *pipe = cn->cn_pipe;
return pipe->nreaders || pipe->nwriters;
}
static int static int
nfsd4_cld_tracking_init(struct net *net) nfsd4_cld_tracking_init(struct net *net)
{ {
int status; int status;
struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct nfsd_net *nn = net_generic(net, nfsd_net_id);
bool running;
int retries = 10;
status = nfs4_cld_state_init(net); status = nfs4_cld_state_init(net);
if (status) if (status)
return status; return status;
status = nfsd4_init_cld_pipe(net); status = __nfsd4_init_cld_pipe(net);
if (status) if (status)
goto err_shutdown; goto err_shutdown;
/*
* rpc pipe upcalls take 30 seconds to time out, so we don't want to
* queue an upcall unless we know that nfsdcld is running (because we
* want this to fail fast so that nfsd4_client_tracking_init() can try
* the next client tracking method). nfsdcld should already be running
* before nfsd is started, so the wait here is for nfsdcld to open the
* pipefs file we just created.
*/
while (!(running = cld_running(nn)) && retries--)
msleep(100);
if (!running) {
status = -ETIMEDOUT;
goto err_remove;
}
status = nfsd4_cld_grace_start(nn); status = nfsd4_cld_grace_start(nn);
if (status) { if (status) {
if (status == -EOPNOTSUPP) if (status == -EOPNOTSUPP)
printk(KERN_WARNING "NFSD: Please upgrade nfsdcld.\n"); printk(KERN_WARNING "NFSD: Please upgrade nfsdcld.\n");
nfs4_release_reclaim(nn); nfs4_release_reclaim(nn);
goto err_remove; goto err_remove;
} } else
printk("NFSD: Using nfsdcld client tracking operations.\n");
return 0; return 0;
err_remove: err_remove:
@ -1552,6 +1592,8 @@ nfsd4_umh_cltrack_init(struct net *net)
ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL); ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL);
kfree(grace_start); kfree(grace_start);
if (!ret)
printk("NFSD: Using UMH upcall client tracking operations.\n");
return ret; return ret;
} }
@ -1701,9 +1743,20 @@ nfsd4_client_tracking_init(struct net *net)
if (nn->client_tracking_ops) if (nn->client_tracking_ops)
goto do_init; goto do_init;
/* First, try to use nfsdcld */
nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
status = nn->client_tracking_ops->init(net);
if (!status)
return status;
if (status != -ETIMEDOUT) {
nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v0;
status = nn->client_tracking_ops->init(net);
if (!status)
return status;
}
/* /*
* First, try a UMH upcall. It should succeed or fail quickly, so * Next, try the UMH upcall.
* there's little harm in trying that first.
*/ */
nn->client_tracking_ops = &nfsd4_umh_tracking_ops; nn->client_tracking_ops = &nfsd4_umh_tracking_ops;
status = nn->client_tracking_ops->init(net); status = nn->client_tracking_ops->init(net);
@ -1711,26 +1764,23 @@ nfsd4_client_tracking_init(struct net *net)
return status; return status;
/* /*
* See if the recoverydir exists and is a directory. If it is, * Finally, See if the recoverydir exists and is a directory.
* then use the legacy ops. * If it is, then use the legacy ops.
*/ */
nn->client_tracking_ops = &nfsd4_legacy_tracking_ops; nn->client_tracking_ops = &nfsd4_legacy_tracking_ops;
status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
if (!status) { if (!status) {
status = d_is_dir(path.dentry); status = d_is_dir(path.dentry);
path_put(&path); path_put(&path);
if (status) if (!status) {
goto do_init; status = -EINVAL;
goto out;
}
} }
/* Finally, try to use nfsdcld */
nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
status = nn->client_tracking_ops->init(net);
if (!status)
return status;
nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v0;
do_init: do_init:
status = nn->client_tracking_ops->init(net); status = nn->client_tracking_ops->init(net);
out:
if (status) { if (status) {
printk(KERN_WARNING "NFSD: Unable to initialize client " printk(KERN_WARNING "NFSD: Unable to initialize client "
"recovery tracking! (%d)\n", status); "recovery tracking! (%d)\n", status);