aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2013-11-14 07:25:17 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-12-06 13:06:30 -0500
commit4b9a445e3eeb8bd9278b1ae51c1b3a651e370cd6 (patch)
tree883070dd3c7eaafc185787649c5591528478eb3b /net/sunrpc
parentc7848f69ec4a8c03732cde5c949bd2aa711a9f4b (diff)
sunrpc: create a new dummy pipe for gssd to hold open
rpc.gssd will naturally hold open any pipe named */clnt*/gssd that shows up under rpc_pipefs. That behavior gives us a reliable mechanism to tell whether it's actually running or not. Create a new toplevel "gssd" directory in rpc_pipefs when it's mounted. Under that directory create another directory called "clntXX", and then within that a pipe called "gssd". We'll never send an upcall along that pipe, and any downcall written to it will just return -EINVAL. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/netns.h1
-rw-r--r--net/sunrpc/rpc_pipe.c93
-rw-r--r--net/sunrpc/sunrpc_syms.c8
3 files changed, 98 insertions, 4 deletions
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index 779742cfc1ff..8a8e841d1547 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -14,6 +14,7 @@ struct sunrpc_net {
14 struct cache_detail *rsi_cache; 14 struct cache_detail *rsi_cache;
15 15
16 struct super_block *pipefs_sb; 16 struct super_block *pipefs_sb;
17 struct rpc_pipe *gssd_dummy;
17 struct mutex pipefs_sb_lock; 18 struct mutex pipefs_sb_lock;
18 19
19 struct list_head all_clients; 20 struct list_head all_clients;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index bf04b30a788a..c23458b464c4 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -38,7 +38,7 @@
38#define NET_NAME(net) ((net == &init_net) ? " (init_net)" : "") 38#define NET_NAME(net) ((net == &init_net) ? " (init_net)" : "")
39 39
40static struct file_system_type rpc_pipe_fs_type; 40static struct file_system_type rpc_pipe_fs_type;
41 41static const struct rpc_pipe_ops gssd_dummy_pipe_ops;
42 42
43static struct kmem_cache *rpc_inode_cachep __read_mostly; 43static struct kmem_cache *rpc_inode_cachep __read_mostly;
44 44
@@ -1159,6 +1159,7 @@ enum {
1159 RPCAUTH_nfsd4_cb, 1159 RPCAUTH_nfsd4_cb,
1160 RPCAUTH_cache, 1160 RPCAUTH_cache,
1161 RPCAUTH_nfsd, 1161 RPCAUTH_nfsd,
1162 RPCAUTH_gssd,
1162 RPCAUTH_RootEOF 1163 RPCAUTH_RootEOF
1163}; 1164};
1164 1165
@@ -1195,6 +1196,10 @@ static const struct rpc_filelist files[] = {
1195 .name = "nfsd", 1196 .name = "nfsd",
1196 .mode = S_IFDIR | S_IRUGO | S_IXUGO, 1197 .mode = S_IFDIR | S_IRUGO | S_IXUGO,
1197 }, 1198 },
1199 [RPCAUTH_gssd] = {
1200 .name = "gssd",
1201 .mode = S_IFDIR | S_IRUGO | S_IXUGO,
1202 },
1198}; 1203};
1199 1204
1200/* 1205/*
@@ -1208,13 +1213,25 @@ struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
1208} 1213}
1209EXPORT_SYMBOL_GPL(rpc_d_lookup_sb); 1214EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
1210 1215
1211void rpc_pipefs_init_net(struct net *net) 1216int rpc_pipefs_init_net(struct net *net)
1212{ 1217{
1213 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1218 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1214 1219
1220 sn->gssd_dummy = rpc_mkpipe_data(&gssd_dummy_pipe_ops, 0);
1221 if (IS_ERR(sn->gssd_dummy))
1222 return PTR_ERR(sn->gssd_dummy);
1223
1215 mutex_init(&sn->pipefs_sb_lock); 1224 mutex_init(&sn->pipefs_sb_lock);
1216 sn->gssd_running = 1; 1225 sn->gssd_running = 1;
1217 sn->pipe_version = -1; 1226 sn->pipe_version = -1;
1227 return 0;
1228}
1229
1230void rpc_pipefs_exit_net(struct net *net)
1231{
1232 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1233
1234 rpc_destroy_pipe_data(sn->gssd_dummy);
1218} 1235}
1219 1236
1220/* 1237/*
@@ -1244,11 +1261,73 @@ void rpc_put_sb_net(const struct net *net)
1244} 1261}
1245EXPORT_SYMBOL_GPL(rpc_put_sb_net); 1262EXPORT_SYMBOL_GPL(rpc_put_sb_net);
1246 1263
1264static const struct rpc_filelist gssd_dummy_clnt_dir[] = {
1265 [0] = {
1266 .name = "clntXX",
1267 .mode = S_IFDIR | S_IRUGO | S_IXUGO,
1268 },
1269};
1270
1271static ssize_t
1272dummy_downcall(struct file *filp, const char __user *src, size_t len)
1273{
1274 return -EINVAL;
1275}
1276
1277static const struct rpc_pipe_ops gssd_dummy_pipe_ops = {
1278 .upcall = rpc_pipe_generic_upcall,
1279 .downcall = dummy_downcall,
1280};
1281
1282/**
1283 * rpc_gssd_dummy_populate - create a dummy gssd pipe
1284 * @root: root of the rpc_pipefs filesystem
1285 * @pipe_data: pipe data created when netns is initialized
1286 *
1287 * Create a dummy set of directories and a pipe that gssd can hold open to
1288 * indicate that it is up and running.
1289 */
1290static struct dentry *
1291rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
1292{
1293 int ret = 0;
1294 struct dentry *gssd_dentry;
1295 struct dentry *clnt_dentry = NULL;
1296 struct dentry *pipe_dentry = NULL;
1297 struct qstr q = QSTR_INIT(files[RPCAUTH_gssd].name,
1298 strlen(files[RPCAUTH_gssd].name));
1299
1300 /* We should never get this far if "gssd" doesn't exist */
1301 gssd_dentry = d_hash_and_lookup(root, &q);
1302 if (!gssd_dentry)
1303 return ERR_PTR(-ENOENT);
1304
1305 ret = rpc_populate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1, NULL);
1306 if (ret) {
1307 pipe_dentry = ERR_PTR(ret);
1308 goto out;
1309 }
1310
1311 q.name = gssd_dummy_clnt_dir[0].name;
1312 q.len = strlen(gssd_dummy_clnt_dir[0].name);
1313 clnt_dentry = d_hash_and_lookup(gssd_dentry, &q);
1314 if (!clnt_dentry) {
1315 pipe_dentry = ERR_PTR(-ENOENT);
1316 goto out;
1317 }
1318
1319 pipe_dentry = rpc_mkpipe_dentry(clnt_dentry, "gssd", NULL, pipe_data);
1320out:
1321 dput(clnt_dentry);
1322 dput(gssd_dentry);
1323 return pipe_dentry;
1324}
1325
1247static int 1326static int
1248rpc_fill_super(struct super_block *sb, void *data, int silent) 1327rpc_fill_super(struct super_block *sb, void *data, int silent)
1249{ 1328{
1250 struct inode *inode; 1329 struct inode *inode;
1251 struct dentry *root; 1330 struct dentry *root, *gssd_dentry;
1252 struct net *net = data; 1331 struct net *net = data;
1253 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1332 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1254 int err; 1333 int err;
@@ -1266,6 +1345,13 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
1266 return -ENOMEM; 1345 return -ENOMEM;
1267 if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) 1346 if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
1268 return -ENOMEM; 1347 return -ENOMEM;
1348
1349 gssd_dentry = rpc_gssd_dummy_populate(root, sn->gssd_dummy);
1350 if (IS_ERR(gssd_dentry)) {
1351 __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
1352 return PTR_ERR(gssd_dentry);
1353 }
1354
1269 dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", 1355 dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n",
1270 net, NET_NAME(net)); 1356 net, NET_NAME(net));
1271 mutex_lock(&sn->pipefs_sb_lock); 1357 mutex_lock(&sn->pipefs_sb_lock);
@@ -1280,6 +1366,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
1280 return 0; 1366 return 0;
1281 1367
1282err_depopulate: 1368err_depopulate:
1369 dput(gssd_dentry);
1283 blocking_notifier_call_chain(&rpc_pipefs_notifier_list, 1370 blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
1284 RPC_PIPEFS_UMOUNT, 1371 RPC_PIPEFS_UMOUNT,
1285 sb); 1372 sb);
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 3d6498af9adc..cd30120de9e4 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -44,12 +44,17 @@ static __net_init int sunrpc_init_net(struct net *net)
44 if (err) 44 if (err)
45 goto err_unixgid; 45 goto err_unixgid;
46 46
47 rpc_pipefs_init_net(net); 47 err = rpc_pipefs_init_net(net);
48 if (err)
49 goto err_pipefs;
50
48 INIT_LIST_HEAD(&sn->all_clients); 51 INIT_LIST_HEAD(&sn->all_clients);
49 spin_lock_init(&sn->rpc_client_lock); 52 spin_lock_init(&sn->rpc_client_lock);
50 spin_lock_init(&sn->rpcb_clnt_lock); 53 spin_lock_init(&sn->rpcb_clnt_lock);
51 return 0; 54 return 0;
52 55
56err_pipefs:
57 unix_gid_cache_destroy(net);
53err_unixgid: 58err_unixgid:
54 ip_map_cache_destroy(net); 59 ip_map_cache_destroy(net);
55err_ipmap: 60err_ipmap:
@@ -60,6 +65,7 @@ err_proc:
60 65
61static __net_exit void sunrpc_exit_net(struct net *net) 66static __net_exit void sunrpc_exit_net(struct net *net)
62{ 67{
68 rpc_pipefs_exit_net(net);
63 unix_gid_cache_destroy(net); 69 unix_gid_cache_destroy(net);
64 ip_map_cache_destroy(net); 70 ip_map_cache_destroy(net);
65 rpc_proc_exit(net); 71 rpc_proc_exit(net);