sunrpc: get rid of use_gssp_lock
We can achieve the same result with a cmpxchg(). This also fixes a potential race in use_gss_proxy(). The value of sn->use_gss_proxy could go from -1 to 1 just after we check it in use_gss_proxy() but before we acquire the spinlock. The procfile write would end up returning success but the value would flip to 0 soon afterward. With this method we not only avoid locking but the first "setter" always wins. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
a92e5eb110
commit
0fdc26785d
|
@ -1263,41 +1263,35 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_SPINLOCK(use_gssp_lock);
|
/*
|
||||||
|
* Try to set the sn->use_gss_proxy variable to a new value. We only allow
|
||||||
|
* it to be changed if it's currently undefined (-1). If it's any other value
|
||||||
|
* then return -EBUSY unless the type wouldn't have changed anyway.
|
||||||
|
*/
|
||||||
|
static int set_gss_proxy(struct net *net, int type)
|
||||||
|
{
|
||||||
|
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
WARN_ON_ONCE(type != 0 && type != 1);
|
||||||
|
ret = cmpxchg(&sn->use_gss_proxy, -1, type);
|
||||||
|
if (ret != -1 && ret != type)
|
||||||
|
return -EBUSY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool use_gss_proxy(struct net *net)
|
static bool use_gss_proxy(struct net *net)
|
||||||
{
|
{
|
||||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||||
|
|
||||||
if (sn->use_gss_proxy != -1)
|
/* If use_gss_proxy is still undefined, then try to disable it */
|
||||||
return sn->use_gss_proxy;
|
if (sn->use_gss_proxy == -1)
|
||||||
spin_lock(&use_gssp_lock);
|
set_gss_proxy(net, 0);
|
||||||
/*
|
return sn->use_gss_proxy;
|
||||||
* If you wanted gss-proxy, you should have said so before
|
|
||||||
* starting to accept requests:
|
|
||||||
*/
|
|
||||||
sn->use_gss_proxy = 0;
|
|
||||||
spin_unlock(&use_gssp_lock);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
|
|
||||||
static int set_gss_proxy(struct net *net, int type)
|
|
||||||
{
|
|
||||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
WARN_ON_ONCE(type != 0 && type != 1);
|
|
||||||
spin_lock(&use_gssp_lock);
|
|
||||||
if (sn->use_gss_proxy == -1 || sn->use_gss_proxy == type)
|
|
||||||
sn->use_gss_proxy = type;
|
|
||||||
else
|
|
||||||
ret = -EBUSY;
|
|
||||||
spin_unlock(&use_gssp_lock);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t write_gssp(struct file *file, const char __user *buf,
|
static ssize_t write_gssp(struct file *file, const char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue