diff options
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r-- | fs/nfs/client.c | 113 |
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 | ||
191 | error_cleanup: | 192 | error_cleanup: |
192 | put_nfs_version(clp->cl_nfs_mod); | 193 | put_nfs_version(clp->cl_nfs_mod); |
194 | error_dealloc: | ||
193 | kfree(clp); | 195 | kfree(clp); |
194 | error_0: | 196 | error_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 | } |
516 | EXPORT_SYMBOL_GPL(nfs_get_client); | 524 | EXPORT_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 | */ |
1237 | static int nfs_server_list_open(struct inode *inode, struct file *file) | 1245 | static 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 | */ |
1257 | static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) | 1254 | static 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 | */ |
1269 | static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) | 1266 | static 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 | */ |
1279 | static void nfs_server_list_stop(struct seq_file *p, void *v) | 1276 | static 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) | |||
1289 | static int nfs_server_list_show(struct seq_file *m, void *v) | 1286 | static 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 | */ |
1322 | static int nfs_volume_list_open(struct inode *inode, struct file *file) | 1319 | static 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 | */ |
1342 | static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) | 1328 | static 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 | */ |
1354 | static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) | 1340 | static 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 | */ |
1364 | static void nfs_volume_list_stop(struct seq_file *p, void *v) | 1350 | static 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 | ||
1396 | int 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 | |||
1418 | error_2: | ||
1419 | remove_proc_entry("servers", nn->proc_nfsfs); | ||
1420 | error_1: | ||
1421 | remove_proc_entry("fs/nfsfs", NULL); | ||
1422 | error_0: | ||
1423 | return -ENOMEM; | ||
1424 | } | ||
1425 | |||
1426 | void 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; |