Commit 0fdc2678 authored by Jeff Layton's avatar Jeff Layton Committed by J. Bruce Fields

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: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent a92e5eb1
...@@ -1263,41 +1263,35 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp, ...@@ -1263,41 +1263,35 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
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
static bool use_gss_proxy(struct net *net) * 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); struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
int ret;
if (sn->use_gss_proxy != -1) WARN_ON_ONCE(type != 0 && type != 1);
return sn->use_gss_proxy; ret = cmpxchg(&sn->use_gss_proxy, -1, type);
spin_lock(&use_gssp_lock); if (ret != -1 && ret != type)
/* return -EBUSY;
* 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; return 0;
} }
#ifdef CONFIG_PROC_FS static bool use_gss_proxy(struct net *net)
static int set_gss_proxy(struct net *net, int type)
{ {
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
int ret = 0;
WARN_ON_ONCE(type != 0 && type != 1); /* If use_gss_proxy is still undefined, then try to disable it */
spin_lock(&use_gssp_lock); if (sn->use_gss_proxy == -1)
if (sn->use_gss_proxy == -1 || sn->use_gss_proxy == type) set_gss_proxy(net, 0);
sn->use_gss_proxy = type; return sn->use_gss_proxy;
else
ret = -EBUSY;
spin_unlock(&use_gssp_lock);
return ret;
} }
#ifdef CONFIG_PROC_FS
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)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment