aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r--fs/nfs/client.c113
1 files changed, 68 insertions, 45 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 1d09289c8f0e..1c5ff6d58385 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -110,8 +110,8 @@ struct nfs_subversion *get_nfs_version(unsigned int version)
110 mutex_unlock(&nfs_version_mutex); 110 mutex_unlock(&nfs_version_mutex);
111 } 111 }
112 112
113 if (!IS_ERR(nfs)) 113 if (!IS_ERR(nfs) && !try_module_get(nfs->owner))
114 try_module_get(nfs->owner); 114 return ERR_PTR(-EAGAIN);
115 return nfs; 115 return nfs;
116} 116}
117 117
@@ -158,7 +158,8 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
158 goto error_0; 158 goto error_0;
159 159
160 clp->cl_nfs_mod = cl_init->nfs_mod; 160 clp->cl_nfs_mod = cl_init->nfs_mod;
161 try_module_get(clp->cl_nfs_mod->owner); 161 if (!try_module_get(clp->cl_nfs_mod->owner))
162 goto error_dealloc;
162 163
163 clp->rpc_ops = clp->cl_nfs_mod->rpc_ops; 164 clp->rpc_ops = clp->cl_nfs_mod->rpc_ops;
164 165
@@ -190,6 +191,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
190 191
191error_cleanup: 192error_cleanup:
192 put_nfs_version(clp->cl_nfs_mod); 193 put_nfs_version(clp->cl_nfs_mod);
194error_dealloc:
193 kfree(clp); 195 kfree(clp);
194error_0: 196error_0:
195 return ERR_PTR(err); 197 return ERR_PTR(err);
@@ -252,6 +254,7 @@ void nfs_free_client(struct nfs_client *clp)
252 put_net(clp->cl_net); 254 put_net(clp->cl_net);
253 put_nfs_version(clp->cl_nfs_mod); 255 put_nfs_version(clp->cl_nfs_mod);
254 kfree(clp->cl_hostname); 256 kfree(clp->cl_hostname);
257 kfree(clp->cl_acceptor);
255 kfree(clp); 258 kfree(clp);
256 259
257 dprintk("<-- nfs_free_client()\n"); 260 dprintk("<-- nfs_free_client()\n");
@@ -482,8 +485,13 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
482 struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id); 485 struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id);
483 const struct nfs_rpc_ops *rpc_ops = cl_init->nfs_mod->rpc_ops; 486 const struct nfs_rpc_ops *rpc_ops = cl_init->nfs_mod->rpc_ops;
484 487
488 if (cl_init->hostname == NULL) {
489 WARN_ON(1);
490 return NULL;
491 }
492
485 dprintk("--> nfs_get_client(%s,v%u)\n", 493 dprintk("--> nfs_get_client(%s,v%u)\n",
486 cl_init->hostname ?: "", rpc_ops->version); 494 cl_init->hostname, rpc_ops->version);
487 495
488 /* see if the client already exists */ 496 /* see if the client already exists */
489 do { 497 do {
@@ -510,7 +518,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
510 } while (!IS_ERR(new)); 518 } while (!IS_ERR(new));
511 519
512 dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n", 520 dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n",
513 cl_init->hostname ?: "", PTR_ERR(new)); 521 cl_init->hostname, PTR_ERR(new));
514 return new; 522 return new;
515} 523}
516EXPORT_SYMBOL_GPL(nfs_get_client); 524EXPORT_SYMBOL_GPL(nfs_get_client);
@@ -1205,7 +1213,7 @@ static const struct file_operations nfs_server_list_fops = {
1205 .open = nfs_server_list_open, 1213 .open = nfs_server_list_open,
1206 .read = seq_read, 1214 .read = seq_read,
1207 .llseek = seq_lseek, 1215 .llseek = seq_lseek,
1208 .release = seq_release, 1216 .release = seq_release_net,
1209 .owner = THIS_MODULE, 1217 .owner = THIS_MODULE,
1210}; 1218};
1211 1219
@@ -1226,7 +1234,7 @@ static const struct file_operations nfs_volume_list_fops = {
1226 .open = nfs_volume_list_open, 1234 .open = nfs_volume_list_open,
1227 .read = seq_read, 1235 .read = seq_read,
1228 .llseek = seq_lseek, 1236 .llseek = seq_lseek,
1229 .release = seq_release, 1237 .release = seq_release_net,
1230 .owner = THIS_MODULE, 1238 .owner = THIS_MODULE,
1231}; 1239};
1232 1240
@@ -1236,19 +1244,8 @@ static const struct file_operations nfs_volume_list_fops = {
1236 */ 1244 */
1237static int nfs_server_list_open(struct inode *inode, struct file *file) 1245static int nfs_server_list_open(struct inode *inode, struct file *file)
1238{ 1246{
1239 struct seq_file *m; 1247 return seq_open_net(inode, file, &nfs_server_list_ops,
1240 int ret; 1248 sizeof(struct seq_net_private));
1241 struct pid_namespace *pid_ns = file->f_dentry->d_sb->s_fs_info;
1242 struct net *net = pid_ns->child_reaper->nsproxy->net_ns;
1243
1244 ret = seq_open(file, &nfs_server_list_ops);
1245 if (ret < 0)
1246 return ret;
1247
1248 m = file->private_data;
1249 m->private = net;
1250
1251 return 0;
1252} 1249}
1253 1250
1254/* 1251/*
@@ -1256,7 +1253,7 @@ static int nfs_server_list_open(struct inode *inode, struct file *file)
1256 */ 1253 */
1257static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) 1254static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
1258{ 1255{
1259 struct nfs_net *nn = net_generic(m->private, nfs_net_id); 1256 struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
1260 1257
1261 /* lock the list against modification */ 1258 /* lock the list against modification */
1262 spin_lock(&nn->nfs_client_lock); 1259 spin_lock(&nn->nfs_client_lock);
@@ -1268,7 +1265,7 @@ static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
1268 */ 1265 */
1269static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) 1266static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
1270{ 1267{
1271 struct nfs_net *nn = net_generic(p->private, nfs_net_id); 1268 struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
1272 1269
1273 return seq_list_next(v, &nn->nfs_client_list, pos); 1270 return seq_list_next(v, &nn->nfs_client_list, pos);
1274} 1271}
@@ -1278,7 +1275,7 @@ static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
1278 */ 1275 */
1279static void nfs_server_list_stop(struct seq_file *p, void *v) 1276static void nfs_server_list_stop(struct seq_file *p, void *v)
1280{ 1277{
1281 struct nfs_net *nn = net_generic(p->private, nfs_net_id); 1278 struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
1282 1279
1283 spin_unlock(&nn->nfs_client_lock); 1280 spin_unlock(&nn->nfs_client_lock);
1284} 1281}
@@ -1289,7 +1286,7 @@ static void nfs_server_list_stop(struct seq_file *p, void *v)
1289static int nfs_server_list_show(struct seq_file *m, void *v) 1286static int nfs_server_list_show(struct seq_file *m, void *v)
1290{ 1287{
1291 struct nfs_client *clp; 1288 struct nfs_client *clp;
1292 struct nfs_net *nn = net_generic(m->private, nfs_net_id); 1289 struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
1293 1290
1294 /* display header on line 1 */ 1291 /* display header on line 1 */
1295 if (v == &nn->nfs_client_list) { 1292 if (v == &nn->nfs_client_list) {
@@ -1321,19 +1318,8 @@ static int nfs_server_list_show(struct seq_file *m, void *v)
1321 */ 1318 */
1322static int nfs_volume_list_open(struct inode *inode, struct file *file) 1319static int nfs_volume_list_open(struct inode *inode, struct file *file)
1323{ 1320{
1324 struct seq_file *m; 1321 return seq_open_net(inode, file, &nfs_server_list_ops,
1325 int ret; 1322 sizeof(struct seq_net_private));
1326 struct pid_namespace *pid_ns = file->f_dentry->d_sb->s_fs_info;
1327 struct net *net = pid_ns->child_reaper->nsproxy->net_ns;
1328
1329 ret = seq_open(file, &nfs_volume_list_ops);
1330 if (ret < 0)
1331 return ret;
1332
1333 m = file->private_data;
1334 m->private = net;
1335
1336 return 0;
1337} 1323}
1338 1324
1339/* 1325/*
@@ -1341,7 +1327,7 @@ static int nfs_volume_list_open(struct inode *inode, struct file *file)
1341 */ 1327 */
1342static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) 1328static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
1343{ 1329{
1344 struct nfs_net *nn = net_generic(m->private, nfs_net_id); 1330 struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
1345 1331
1346 /* lock the list against modification */ 1332 /* lock the list against modification */
1347 spin_lock(&nn->nfs_client_lock); 1333 spin_lock(&nn->nfs_client_lock);
@@ -1353,7 +1339,7 @@ static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
1353 */ 1339 */
1354static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) 1340static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
1355{ 1341{
1356 struct nfs_net *nn = net_generic(p->private, nfs_net_id); 1342 struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
1357 1343
1358 return seq_list_next(v, &nn->nfs_volume_list, pos); 1344 return seq_list_next(v, &nn->nfs_volume_list, pos);
1359} 1345}
@@ -1363,7 +1349,7 @@ static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
1363 */ 1349 */
1364static void nfs_volume_list_stop(struct seq_file *p, void *v) 1350static void nfs_volume_list_stop(struct seq_file *p, void *v)
1365{ 1351{
1366 struct nfs_net *nn = net_generic(p->private, nfs_net_id); 1352 struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
1367 1353
1368 spin_unlock(&nn->nfs_client_lock); 1354 spin_unlock(&nn->nfs_client_lock);
1369} 1355}
@@ -1376,7 +1362,7 @@ static int nfs_volume_list_show(struct seq_file *m, void *v)
1376 struct nfs_server *server; 1362 struct nfs_server *server;
1377 struct nfs_client *clp; 1363 struct nfs_client *clp;
1378 char dev[8], fsid[17]; 1364 char dev[8], fsid[17];
1379 struct nfs_net *nn = net_generic(m->private, nfs_net_id); 1365 struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
1380 1366
1381 /* display header on line 1 */ 1367 /* display header on line 1 */
1382 if (v == &nn->nfs_volume_list) { 1368 if (v == &nn->nfs_volume_list) {
@@ -1407,6 +1393,45 @@ static int nfs_volume_list_show(struct seq_file *m, void *v)
1407 return 0; 1393 return 0;
1408} 1394}
1409 1395
1396int nfs_fs_proc_net_init(struct net *net)
1397{
1398 struct nfs_net *nn = net_generic(net, nfs_net_id);
1399 struct proc_dir_entry *p;
1400
1401 nn->proc_nfsfs = proc_net_mkdir(net, "nfsfs", net->proc_net);
1402 if (!nn->proc_nfsfs)
1403 goto error_0;
1404
1405 /* a file of servers with which we're dealing */
1406 p = proc_create("servers", S_IFREG|S_IRUGO,
1407 nn->proc_nfsfs, &nfs_server_list_fops);
1408 if (!p)
1409 goto error_1;
1410
1411 /* a file of volumes that we have mounted */
1412 p = proc_create("volumes", S_IFREG|S_IRUGO,
1413 nn->proc_nfsfs, &nfs_volume_list_fops);
1414 if (!p)
1415 goto error_2;
1416 return 0;
1417
1418error_2:
1419 remove_proc_entry("servers", nn->proc_nfsfs);
1420error_1:
1421 remove_proc_entry("fs/nfsfs", NULL);
1422error_0:
1423 return -ENOMEM;
1424}
1425
1426void nfs_fs_proc_net_exit(struct net *net)
1427{
1428 struct nfs_net *nn = net_generic(net, nfs_net_id);
1429
1430 remove_proc_entry("volumes", nn->proc_nfsfs);
1431 remove_proc_entry("servers", nn->proc_nfsfs);
1432 remove_proc_entry("fs/nfsfs", NULL);
1433}
1434
1410/* 1435/*
1411 * initialise the /proc/fs/nfsfs/ directory 1436 * initialise the /proc/fs/nfsfs/ directory
1412 */ 1437 */
@@ -1419,14 +1444,12 @@ int __init nfs_fs_proc_init(void)
1419 goto error_0; 1444 goto error_0;
1420 1445
1421 /* a file of servers with which we're dealing */ 1446 /* a file of servers with which we're dealing */
1422 p = proc_create("servers", S_IFREG|S_IRUGO, 1447 p = proc_symlink("servers", proc_fs_nfs, "../../net/nfsfs/servers");
1423 proc_fs_nfs, &nfs_server_list_fops);
1424 if (!p) 1448 if (!p)
1425 goto error_1; 1449 goto error_1;
1426 1450
1427 /* a file of volumes that we have mounted */ 1451 /* a file of volumes that we have mounted */
1428 p = proc_create("volumes", S_IFREG|S_IRUGO, 1452 p = proc_symlink("volumes", proc_fs_nfs, "../../net/nfsfs/volumes");
1429 proc_fs_nfs, &nfs_volume_list_fops);
1430 if (!p) 1453 if (!p)
1431 goto error_2; 1454 goto error_2;
1432 return 0; 1455 return 0;