aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2014-01-04 07:18:05 -0500
committerJ. Bruce Fields <bfields@redhat.com>2014-01-06 15:14:18 -0500
commit0fdc26785d0a5bb33d9adb572307fd2d7a406734 (patch)
tree85474a5723bbf22117c654f357aaa26e9999fdce /net/sunrpc/auth_gss
parenta92e5eb1103341e985a575e48e26f87fbb9b1679 (diff)
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>
Diffstat (limited to 'net/sunrpc/auth_gss')
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c42
1 files changed, 18 insertions, 24 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 60dc3700b2cb..2a935404047f 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1263,41 +1263,35 @@ out:
1263 return ret; 1263 return ret;
1264} 1264}
1265 1265
1266DEFINE_SPINLOCK(use_gssp_lock); 1266/*
1267 1267 * Try to set the sn->use_gss_proxy variable to a new value. We only allow
1268static bool use_gss_proxy(struct net *net) 1268 * it to be changed if it's currently undefined (-1). If it's any other value
1269 * then return -EBUSY unless the type wouldn't have changed anyway.
1270 */
1271static int set_gss_proxy(struct net *net, int type)
1269{ 1272{
1270 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1273 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1274 int ret;
1271 1275
1272 if (sn->use_gss_proxy != -1) 1276 WARN_ON_ONCE(type != 0 && type != 1);
1273 return sn->use_gss_proxy; 1277 ret = cmpxchg(&sn->use_gss_proxy, -1, type);
1274 spin_lock(&use_gssp_lock); 1278 if (ret != -1 && ret != type)
1275 /* 1279 return -EBUSY;
1276 * If you wanted gss-proxy, you should have said so before
1277 * starting to accept requests:
1278 */
1279 sn->use_gss_proxy = 0;
1280 spin_unlock(&use_gssp_lock);
1281 return 0; 1280 return 0;
1282} 1281}
1283 1282
1284#ifdef CONFIG_PROC_FS 1283static bool use_gss_proxy(struct net *net)
1285
1286static int set_gss_proxy(struct net *net, int type)
1287{ 1284{
1288 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1285 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1289 int ret = 0;
1290 1286
1291 WARN_ON_ONCE(type != 0 && type != 1); 1287 /* If use_gss_proxy is still undefined, then try to disable it */
1292 spin_lock(&use_gssp_lock); 1288 if (sn->use_gss_proxy == -1)
1293 if (sn->use_gss_proxy == -1 || sn->use_gss_proxy == type) 1289 set_gss_proxy(net, 0);
1294 sn->use_gss_proxy = type; 1290 return sn->use_gss_proxy;
1295 else
1296 ret = -EBUSY;
1297 spin_unlock(&use_gssp_lock);
1298 return ret;
1299} 1291}
1300 1292
1293#ifdef CONFIG_PROC_FS
1294
1301static ssize_t write_gssp(struct file *file, const char __user *buf, 1295static ssize_t write_gssp(struct file *file, const char __user *buf,
1302 size_t count, loff_t *ppos) 1296 size_t count, loff_t *ppos)
1303{ 1297{