diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-19 20:24:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-19 20:24:05 -0400 |
commit | 6a6be470c3071559970c5659354484d4f664050e (patch) | |
tree | d4b335e863e426acad96fe5e4bce2e3e064abc32 /fs/nfs | |
parent | 98c89cdd3a292af3451e47a2a33132f5183861b0 (diff) | |
parent | 126e216a8730532dfb685205309275f87e3d133e (diff) |
Merge branch 'nfs-for-2.6.35' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'nfs-for-2.6.35' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (78 commits)
SUNRPC: Don't spam gssd with upcall requests when the kerberos key expired
SUNRPC: Reorder the struct rpc_task fields
SUNRPC: Remove the 'tk_magic' debugging field
SUNRPC: Move the task->tk_bytes_sent and tk_rtt to struct rpc_rqst
NFS: Don't call iput() in nfs_access_cache_shrinker
NFS: Clean up nfs_access_zap_cache()
NFS: Don't run nfs_access_cache_shrinker() when the mask is GFP_NOFS
SUNRPC: Ensure rpcauth_prune_expired() respects the nr_to_scan parameter
SUNRPC: Ensure memory shrinker doesn't waste time in rpcauth_prune_expired()
SUNRPC: Dont run rpcauth_cache_shrinker() when gfp_mask is GFP_NOFS
NFS: Read requests can use GFP_KERNEL.
NFS: Clean up nfs_create_request()
NFS: Don't use GFP_KERNEL in rpcsec_gss downcalls
NFSv4: Don't use GFP_KERNEL allocations in state recovery
SUNRPC: Fix xs_setup_bc_tcp()
SUNRPC: Replace jiffies-based metrics with ktime-based metrics
ktime: introduce ktime_to_ms()
SUNRPC: RPC metrics and RTT estimator should use same RTT value
NFS: Calldata for nfs4_renew_done()
NFS: Squelch compiler warning in nfs_add_server_stats()
...
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/client.c | 55 | ||||
-rw-r--r-- | fs/nfs/delegation.c | 2 | ||||
-rw-r--r-- | fs/nfs/dir.c | 143 | ||||
-rw-r--r-- | fs/nfs/file.c | 15 | ||||
-rw-r--r-- | fs/nfs/fscache.c | 3 | ||||
-rw-r--r-- | fs/nfs/getroot.c | 191 | ||||
-rw-r--r-- | fs/nfs/inode.c | 58 | ||||
-rw-r--r-- | fs/nfs/internal.h | 4 | ||||
-rw-r--r-- | fs/nfs/iostat.h | 6 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 20 | ||||
-rw-r--r-- | fs/nfs/nfs3acl.c | 23 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 128 | ||||
-rw-r--r-- | fs/nfs/nfs3xdr.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 8 | ||||
-rw-r--r-- | fs/nfs/nfs4namespace.c | 12 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 172 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 36 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 22 | ||||
-rw-r--r-- | fs/nfs/nfsroot.c | 14 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 14 | ||||
-rw-r--r-- | fs/nfs/proc.c | 144 | ||||
-rw-r--r-- | fs/nfs/read.c | 4 | ||||
-rw-r--r-- | fs/nfs/super.c | 147 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 4 |
24 files changed, 732 insertions, 495 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index acc9c4943b84..7ec9b34a59f8 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -934,7 +934,6 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str | |||
934 | } | 934 | } |
935 | 935 | ||
936 | fsinfo.fattr = fattr; | 936 | fsinfo.fattr = fattr; |
937 | nfs_fattr_init(fattr); | ||
938 | error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); | 937 | error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); |
939 | if (error < 0) | 938 | if (error < 0) |
940 | goto out_error; | 939 | goto out_error; |
@@ -1047,13 +1046,18 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, | |||
1047 | struct nfs_fh *mntfh) | 1046 | struct nfs_fh *mntfh) |
1048 | { | 1047 | { |
1049 | struct nfs_server *server; | 1048 | struct nfs_server *server; |
1050 | struct nfs_fattr fattr; | 1049 | struct nfs_fattr *fattr; |
1051 | int error; | 1050 | int error; |
1052 | 1051 | ||
1053 | server = nfs_alloc_server(); | 1052 | server = nfs_alloc_server(); |
1054 | if (!server) | 1053 | if (!server) |
1055 | return ERR_PTR(-ENOMEM); | 1054 | return ERR_PTR(-ENOMEM); |
1056 | 1055 | ||
1056 | error = -ENOMEM; | ||
1057 | fattr = nfs_alloc_fattr(); | ||
1058 | if (fattr == NULL) | ||
1059 | goto error; | ||
1060 | |||
1057 | /* Get a client representation */ | 1061 | /* Get a client representation */ |
1058 | error = nfs_init_server(server, data); | 1062 | error = nfs_init_server(server, data); |
1059 | if (error < 0) | 1063 | if (error < 0) |
@@ -1064,7 +1068,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, | |||
1064 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 1068 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
1065 | 1069 | ||
1066 | /* Probe the root fh to retrieve its FSID */ | 1070 | /* Probe the root fh to retrieve its FSID */ |
1067 | error = nfs_probe_fsinfo(server, mntfh, &fattr); | 1071 | error = nfs_probe_fsinfo(server, mntfh, fattr); |
1068 | if (error < 0) | 1072 | if (error < 0) |
1069 | goto error; | 1073 | goto error; |
1070 | if (server->nfs_client->rpc_ops->version == 3) { | 1074 | if (server->nfs_client->rpc_ops->version == 3) { |
@@ -1077,14 +1081,14 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, | |||
1077 | server->namelen = NFS2_MAXNAMLEN; | 1081 | server->namelen = NFS2_MAXNAMLEN; |
1078 | } | 1082 | } |
1079 | 1083 | ||
1080 | if (!(fattr.valid & NFS_ATTR_FATTR)) { | 1084 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
1081 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); | 1085 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr); |
1082 | if (error < 0) { | 1086 | if (error < 0) { |
1083 | dprintk("nfs_create_server: getattr error = %d\n", -error); | 1087 | dprintk("nfs_create_server: getattr error = %d\n", -error); |
1084 | goto error; | 1088 | goto error; |
1085 | } | 1089 | } |
1086 | } | 1090 | } |
1087 | memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); | 1091 | memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); |
1088 | 1092 | ||
1089 | dprintk("Server FSID: %llx:%llx\n", | 1093 | dprintk("Server FSID: %llx:%llx\n", |
1090 | (unsigned long long) server->fsid.major, | 1094 | (unsigned long long) server->fsid.major, |
@@ -1096,9 +1100,11 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, | |||
1096 | spin_unlock(&nfs_client_lock); | 1100 | spin_unlock(&nfs_client_lock); |
1097 | 1101 | ||
1098 | server->mount_time = jiffies; | 1102 | server->mount_time = jiffies; |
1103 | nfs_free_fattr(fattr); | ||
1099 | return server; | 1104 | return server; |
1100 | 1105 | ||
1101 | error: | 1106 | error: |
1107 | nfs_free_fattr(fattr); | ||
1102 | nfs_free_server(server); | 1108 | nfs_free_server(server); |
1103 | return ERR_PTR(error); | 1109 | return ERR_PTR(error); |
1104 | } | 1110 | } |
@@ -1340,7 +1346,7 @@ error: | |||
1340 | struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | 1346 | struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, |
1341 | struct nfs_fh *mntfh) | 1347 | struct nfs_fh *mntfh) |
1342 | { | 1348 | { |
1343 | struct nfs_fattr fattr; | 1349 | struct nfs_fattr *fattr; |
1344 | struct nfs_server *server; | 1350 | struct nfs_server *server; |
1345 | int error; | 1351 | int error; |
1346 | 1352 | ||
@@ -1350,6 +1356,11 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | |||
1350 | if (!server) | 1356 | if (!server) |
1351 | return ERR_PTR(-ENOMEM); | 1357 | return ERR_PTR(-ENOMEM); |
1352 | 1358 | ||
1359 | error = -ENOMEM; | ||
1360 | fattr = nfs_alloc_fattr(); | ||
1361 | if (fattr == NULL) | ||
1362 | goto error; | ||
1363 | |||
1353 | /* set up the general RPC client */ | 1364 | /* set up the general RPC client */ |
1354 | error = nfs4_init_server(server, data); | 1365 | error = nfs4_init_server(server, data); |
1355 | if (error < 0) | 1366 | if (error < 0) |
@@ -1364,7 +1375,7 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | |||
1364 | goto error; | 1375 | goto error; |
1365 | 1376 | ||
1366 | /* Probe the root fh to retrieve its FSID */ | 1377 | /* Probe the root fh to retrieve its FSID */ |
1367 | error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); | 1378 | error = nfs4_get_rootfh(server, mntfh); |
1368 | if (error < 0) | 1379 | if (error < 0) |
1369 | goto error; | 1380 | goto error; |
1370 | 1381 | ||
@@ -1375,7 +1386,7 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | |||
1375 | 1386 | ||
1376 | nfs4_session_set_rwsize(server); | 1387 | nfs4_session_set_rwsize(server); |
1377 | 1388 | ||
1378 | error = nfs_probe_fsinfo(server, mntfh, &fattr); | 1389 | error = nfs_probe_fsinfo(server, mntfh, fattr); |
1379 | if (error < 0) | 1390 | if (error < 0) |
1380 | goto error; | 1391 | goto error; |
1381 | 1392 | ||
@@ -1389,9 +1400,11 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | |||
1389 | 1400 | ||
1390 | server->mount_time = jiffies; | 1401 | server->mount_time = jiffies; |
1391 | dprintk("<-- nfs4_create_server() = %p\n", server); | 1402 | dprintk("<-- nfs4_create_server() = %p\n", server); |
1403 | nfs_free_fattr(fattr); | ||
1392 | return server; | 1404 | return server; |
1393 | 1405 | ||
1394 | error: | 1406 | error: |
1407 | nfs_free_fattr(fattr); | ||
1395 | nfs_free_server(server); | 1408 | nfs_free_server(server); |
1396 | dprintk("<-- nfs4_create_server() = error %d\n", error); | 1409 | dprintk("<-- nfs4_create_server() = error %d\n", error); |
1397 | return ERR_PTR(error); | 1410 | return ERR_PTR(error); |
@@ -1405,7 +1418,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1405 | { | 1418 | { |
1406 | struct nfs_client *parent_client; | 1419 | struct nfs_client *parent_client; |
1407 | struct nfs_server *server, *parent_server; | 1420 | struct nfs_server *server, *parent_server; |
1408 | struct nfs_fattr fattr; | 1421 | struct nfs_fattr *fattr; |
1409 | int error; | 1422 | int error; |
1410 | 1423 | ||
1411 | dprintk("--> nfs4_create_referral_server()\n"); | 1424 | dprintk("--> nfs4_create_referral_server()\n"); |
@@ -1414,6 +1427,11 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1414 | if (!server) | 1427 | if (!server) |
1415 | return ERR_PTR(-ENOMEM); | 1428 | return ERR_PTR(-ENOMEM); |
1416 | 1429 | ||
1430 | error = -ENOMEM; | ||
1431 | fattr = nfs_alloc_fattr(); | ||
1432 | if (fattr == NULL) | ||
1433 | goto error; | ||
1434 | |||
1417 | parent_server = NFS_SB(data->sb); | 1435 | parent_server = NFS_SB(data->sb); |
1418 | parent_client = parent_server->nfs_client; | 1436 | parent_client = parent_server->nfs_client; |
1419 | 1437 | ||
@@ -1443,12 +1461,12 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1443 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 1461 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
1444 | 1462 | ||
1445 | /* Probe the root fh to retrieve its FSID and filehandle */ | 1463 | /* Probe the root fh to retrieve its FSID and filehandle */ |
1446 | error = nfs4_path_walk(server, mntfh, data->mnt_path); | 1464 | error = nfs4_get_rootfh(server, mntfh); |
1447 | if (error < 0) | 1465 | if (error < 0) |
1448 | goto error; | 1466 | goto error; |
1449 | 1467 | ||
1450 | /* probe the filesystem info for this server filesystem */ | 1468 | /* probe the filesystem info for this server filesystem */ |
1451 | error = nfs_probe_fsinfo(server, mntfh, &fattr); | 1469 | error = nfs_probe_fsinfo(server, mntfh, fattr); |
1452 | if (error < 0) | 1470 | if (error < 0) |
1453 | goto error; | 1471 | goto error; |
1454 | 1472 | ||
@@ -1466,10 +1484,12 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1466 | 1484 | ||
1467 | server->mount_time = jiffies; | 1485 | server->mount_time = jiffies; |
1468 | 1486 | ||
1487 | nfs_free_fattr(fattr); | ||
1469 | dprintk("<-- nfs_create_referral_server() = %p\n", server); | 1488 | dprintk("<-- nfs_create_referral_server() = %p\n", server); |
1470 | return server; | 1489 | return server; |
1471 | 1490 | ||
1472 | error: | 1491 | error: |
1492 | nfs_free_fattr(fattr); | ||
1473 | nfs_free_server(server); | 1493 | nfs_free_server(server); |
1474 | dprintk("<-- nfs4_create_referral_server() = error %d\n", error); | 1494 | dprintk("<-- nfs4_create_referral_server() = error %d\n", error); |
1475 | return ERR_PTR(error); | 1495 | return ERR_PTR(error); |
@@ -1485,7 +1505,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
1485 | struct nfs_fattr *fattr) | 1505 | struct nfs_fattr *fattr) |
1486 | { | 1506 | { |
1487 | struct nfs_server *server; | 1507 | struct nfs_server *server; |
1488 | struct nfs_fattr fattr_fsinfo; | 1508 | struct nfs_fattr *fattr_fsinfo; |
1489 | int error; | 1509 | int error; |
1490 | 1510 | ||
1491 | dprintk("--> nfs_clone_server(,%llx:%llx,)\n", | 1511 | dprintk("--> nfs_clone_server(,%llx:%llx,)\n", |
@@ -1496,6 +1516,11 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
1496 | if (!server) | 1516 | if (!server) |
1497 | return ERR_PTR(-ENOMEM); | 1517 | return ERR_PTR(-ENOMEM); |
1498 | 1518 | ||
1519 | error = -ENOMEM; | ||
1520 | fattr_fsinfo = nfs_alloc_fattr(); | ||
1521 | if (fattr_fsinfo == NULL) | ||
1522 | goto out_free_server; | ||
1523 | |||
1499 | /* Copy data from the source */ | 1524 | /* Copy data from the source */ |
1500 | server->nfs_client = source->nfs_client; | 1525 | server->nfs_client = source->nfs_client; |
1501 | atomic_inc(&server->nfs_client->cl_count); | 1526 | atomic_inc(&server->nfs_client->cl_count); |
@@ -1512,7 +1537,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
1512 | nfs_init_server_aclclient(server); | 1537 | nfs_init_server_aclclient(server); |
1513 | 1538 | ||
1514 | /* probe the filesystem info for this server filesystem */ | 1539 | /* probe the filesystem info for this server filesystem */ |
1515 | error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo); | 1540 | error = nfs_probe_fsinfo(server, fh, fattr_fsinfo); |
1516 | if (error < 0) | 1541 | if (error < 0) |
1517 | goto out_free_server; | 1542 | goto out_free_server; |
1518 | 1543 | ||
@@ -1534,10 +1559,12 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
1534 | 1559 | ||
1535 | server->mount_time = jiffies; | 1560 | server->mount_time = jiffies; |
1536 | 1561 | ||
1562 | nfs_free_fattr(fattr_fsinfo); | ||
1537 | dprintk("<-- nfs_clone_server() = %p\n", server); | 1563 | dprintk("<-- nfs_clone_server() = %p\n", server); |
1538 | return server; | 1564 | return server; |
1539 | 1565 | ||
1540 | out_free_server: | 1566 | out_free_server: |
1567 | nfs_free_fattr(fattr_fsinfo); | ||
1541 | nfs_free_server(server); | 1568 | nfs_free_server(server); |
1542 | dprintk("<-- nfs_clone_server() = error %d\n", error); | 1569 | dprintk("<-- nfs_clone_server() = error %d\n", error); |
1543 | return ERR_PTR(error); | 1570 | return ERR_PTR(error); |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index ea61d26e7871..301634543974 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -213,7 +213,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
213 | struct nfs_delegation *freeme = NULL; | 213 | struct nfs_delegation *freeme = NULL; |
214 | int status = 0; | 214 | int status = 0; |
215 | 215 | ||
216 | delegation = kmalloc(sizeof(*delegation), GFP_KERNEL); | 216 | delegation = kmalloc(sizeof(*delegation), GFP_NOFS); |
217 | if (delegation == NULL) | 217 | if (delegation == NULL) |
218 | return -ENOMEM; | 218 | return -ENOMEM; |
219 | memcpy(delegation->stateid.data, res->delegation.data, | 219 | memcpy(delegation->stateid.data, res->delegation.data, |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a7bb5c694aa3..ee9a179ebdf3 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -530,9 +530,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
530 | nfs_readdir_descriptor_t my_desc, | 530 | nfs_readdir_descriptor_t my_desc, |
531 | *desc = &my_desc; | 531 | *desc = &my_desc; |
532 | struct nfs_entry my_entry; | 532 | struct nfs_entry my_entry; |
533 | struct nfs_fh fh; | 533 | int res = -ENOMEM; |
534 | struct nfs_fattr fattr; | ||
535 | long res; | ||
536 | 534 | ||
537 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", | 535 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", |
538 | dentry->d_parent->d_name.name, dentry->d_name.name, | 536 | dentry->d_parent->d_name.name, dentry->d_name.name, |
@@ -554,9 +552,11 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
554 | 552 | ||
555 | my_entry.cookie = my_entry.prev_cookie = 0; | 553 | my_entry.cookie = my_entry.prev_cookie = 0; |
556 | my_entry.eof = 0; | 554 | my_entry.eof = 0; |
557 | my_entry.fh = &fh; | 555 | my_entry.fh = nfs_alloc_fhandle(); |
558 | my_entry.fattr = &fattr; | 556 | my_entry.fattr = nfs_alloc_fattr(); |
559 | nfs_fattr_init(&fattr); | 557 | if (my_entry.fh == NULL || my_entry.fattr == NULL) |
558 | goto out_alloc_failed; | ||
559 | |||
560 | desc->entry = &my_entry; | 560 | desc->entry = &my_entry; |
561 | 561 | ||
562 | nfs_block_sillyrename(dentry); | 562 | nfs_block_sillyrename(dentry); |
@@ -598,7 +598,10 @@ out: | |||
598 | nfs_unblock_sillyrename(dentry); | 598 | nfs_unblock_sillyrename(dentry); |
599 | if (res > 0) | 599 | if (res > 0) |
600 | res = 0; | 600 | res = 0; |
601 | dfprintk(FILE, "NFS: readdir(%s/%s) returns %ld\n", | 601 | out_alloc_failed: |
602 | nfs_free_fattr(my_entry.fattr); | ||
603 | nfs_free_fhandle(my_entry.fh); | ||
604 | dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n", | ||
602 | dentry->d_parent->d_name.name, dentry->d_name.name, | 605 | dentry->d_parent->d_name.name, dentry->d_name.name, |
603 | res); | 606 | res); |
604 | return res; | 607 | return res; |
@@ -776,9 +779,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
776 | struct inode *dir; | 779 | struct inode *dir; |
777 | struct inode *inode; | 780 | struct inode *inode; |
778 | struct dentry *parent; | 781 | struct dentry *parent; |
782 | struct nfs_fh *fhandle = NULL; | ||
783 | struct nfs_fattr *fattr = NULL; | ||
779 | int error; | 784 | int error; |
780 | struct nfs_fh fhandle; | ||
781 | struct nfs_fattr fattr; | ||
782 | 785 | ||
783 | parent = dget_parent(dentry); | 786 | parent = dget_parent(dentry); |
784 | dir = parent->d_inode; | 787 | dir = parent->d_inode; |
@@ -811,14 +814,22 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
811 | if (NFS_STALE(inode)) | 814 | if (NFS_STALE(inode)) |
812 | goto out_bad; | 815 | goto out_bad; |
813 | 816 | ||
814 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); | 817 | error = -ENOMEM; |
818 | fhandle = nfs_alloc_fhandle(); | ||
819 | fattr = nfs_alloc_fattr(); | ||
820 | if (fhandle == NULL || fattr == NULL) | ||
821 | goto out_error; | ||
822 | |||
823 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | ||
815 | if (error) | 824 | if (error) |
816 | goto out_bad; | 825 | goto out_bad; |
817 | if (nfs_compare_fh(NFS_FH(inode), &fhandle)) | 826 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) |
818 | goto out_bad; | 827 | goto out_bad; |
819 | if ((error = nfs_refresh_inode(inode, &fattr)) != 0) | 828 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) |
820 | goto out_bad; | 829 | goto out_bad; |
821 | 830 | ||
831 | nfs_free_fattr(fattr); | ||
832 | nfs_free_fhandle(fhandle); | ||
822 | out_set_verifier: | 833 | out_set_verifier: |
823 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 834 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
824 | out_valid: | 835 | out_valid: |
@@ -842,11 +853,21 @@ out_zap_parent: | |||
842 | shrink_dcache_parent(dentry); | 853 | shrink_dcache_parent(dentry); |
843 | } | 854 | } |
844 | d_drop(dentry); | 855 | d_drop(dentry); |
856 | nfs_free_fattr(fattr); | ||
857 | nfs_free_fhandle(fhandle); | ||
845 | dput(parent); | 858 | dput(parent); |
846 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", | 859 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", |
847 | __func__, dentry->d_parent->d_name.name, | 860 | __func__, dentry->d_parent->d_name.name, |
848 | dentry->d_name.name); | 861 | dentry->d_name.name); |
849 | return 0; | 862 | return 0; |
863 | out_error: | ||
864 | nfs_free_fattr(fattr); | ||
865 | nfs_free_fhandle(fhandle); | ||
866 | dput(parent); | ||
867 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", | ||
868 | __func__, dentry->d_parent->d_name.name, | ||
869 | dentry->d_name.name, error); | ||
870 | return error; | ||
850 | } | 871 | } |
851 | 872 | ||
852 | /* | 873 | /* |
@@ -911,9 +932,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
911 | struct dentry *res; | 932 | struct dentry *res; |
912 | struct dentry *parent; | 933 | struct dentry *parent; |
913 | struct inode *inode = NULL; | 934 | struct inode *inode = NULL; |
935 | struct nfs_fh *fhandle = NULL; | ||
936 | struct nfs_fattr *fattr = NULL; | ||
914 | int error; | 937 | int error; |
915 | struct nfs_fh fhandle; | ||
916 | struct nfs_fattr fattr; | ||
917 | 938 | ||
918 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", | 939 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", |
919 | dentry->d_parent->d_name.name, dentry->d_name.name); | 940 | dentry->d_parent->d_name.name, dentry->d_name.name); |
@@ -923,7 +944,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
923 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) | 944 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) |
924 | goto out; | 945 | goto out; |
925 | 946 | ||
926 | res = ERR_PTR(-ENOMEM); | ||
927 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 947 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; |
928 | 948 | ||
929 | /* | 949 | /* |
@@ -936,17 +956,23 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
936 | goto out; | 956 | goto out; |
937 | } | 957 | } |
938 | 958 | ||
959 | res = ERR_PTR(-ENOMEM); | ||
960 | fhandle = nfs_alloc_fhandle(); | ||
961 | fattr = nfs_alloc_fattr(); | ||
962 | if (fhandle == NULL || fattr == NULL) | ||
963 | goto out; | ||
964 | |||
939 | parent = dentry->d_parent; | 965 | parent = dentry->d_parent; |
940 | /* Protect against concurrent sillydeletes */ | 966 | /* Protect against concurrent sillydeletes */ |
941 | nfs_block_sillyrename(parent); | 967 | nfs_block_sillyrename(parent); |
942 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); | 968 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); |
943 | if (error == -ENOENT) | 969 | if (error == -ENOENT) |
944 | goto no_entry; | 970 | goto no_entry; |
945 | if (error < 0) { | 971 | if (error < 0) { |
946 | res = ERR_PTR(error); | 972 | res = ERR_PTR(error); |
947 | goto out_unblock_sillyrename; | 973 | goto out_unblock_sillyrename; |
948 | } | 974 | } |
949 | inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); | 975 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); |
950 | res = (struct dentry *)inode; | 976 | res = (struct dentry *)inode; |
951 | if (IS_ERR(res)) | 977 | if (IS_ERR(res)) |
952 | goto out_unblock_sillyrename; | 978 | goto out_unblock_sillyrename; |
@@ -962,6 +988,8 @@ no_entry: | |||
962 | out_unblock_sillyrename: | 988 | out_unblock_sillyrename: |
963 | nfs_unblock_sillyrename(parent); | 989 | nfs_unblock_sillyrename(parent); |
964 | out: | 990 | out: |
991 | nfs_free_fattr(fattr); | ||
992 | nfs_free_fhandle(fhandle); | ||
965 | return res; | 993 | return res; |
966 | } | 994 | } |
967 | 995 | ||
@@ -1669,28 +1697,33 @@ static void nfs_access_free_entry(struct nfs_access_entry *entry) | |||
1669 | smp_mb__after_atomic_dec(); | 1697 | smp_mb__after_atomic_dec(); |
1670 | } | 1698 | } |
1671 | 1699 | ||
1700 | static void nfs_access_free_list(struct list_head *head) | ||
1701 | { | ||
1702 | struct nfs_access_entry *cache; | ||
1703 | |||
1704 | while (!list_empty(head)) { | ||
1705 | cache = list_entry(head->next, struct nfs_access_entry, lru); | ||
1706 | list_del(&cache->lru); | ||
1707 | nfs_access_free_entry(cache); | ||
1708 | } | ||
1709 | } | ||
1710 | |||
1672 | int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) | 1711 | int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) |
1673 | { | 1712 | { |
1674 | LIST_HEAD(head); | 1713 | LIST_HEAD(head); |
1675 | struct nfs_inode *nfsi; | 1714 | struct nfs_inode *nfsi; |
1676 | struct nfs_access_entry *cache; | 1715 | struct nfs_access_entry *cache; |
1677 | 1716 | ||
1678 | restart: | 1717 | if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL) |
1718 | return (nr_to_scan == 0) ? 0 : -1; | ||
1719 | |||
1679 | spin_lock(&nfs_access_lru_lock); | 1720 | spin_lock(&nfs_access_lru_lock); |
1680 | list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) { | 1721 | list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) { |
1681 | struct rw_semaphore *s_umount; | ||
1682 | struct inode *inode; | 1722 | struct inode *inode; |
1683 | 1723 | ||
1684 | if (nr_to_scan-- == 0) | 1724 | if (nr_to_scan-- == 0) |
1685 | break; | 1725 | break; |
1686 | s_umount = &nfsi->vfs_inode.i_sb->s_umount; | 1726 | inode = &nfsi->vfs_inode; |
1687 | if (!down_read_trylock(s_umount)) | ||
1688 | continue; | ||
1689 | inode = igrab(&nfsi->vfs_inode); | ||
1690 | if (inode == NULL) { | ||
1691 | up_read(s_umount); | ||
1692 | continue; | ||
1693 | } | ||
1694 | spin_lock(&inode->i_lock); | 1727 | spin_lock(&inode->i_lock); |
1695 | if (list_empty(&nfsi->access_cache_entry_lru)) | 1728 | if (list_empty(&nfsi->access_cache_entry_lru)) |
1696 | goto remove_lru_entry; | 1729 | goto remove_lru_entry; |
@@ -1704,61 +1737,47 @@ restart: | |||
1704 | else { | 1737 | else { |
1705 | remove_lru_entry: | 1738 | remove_lru_entry: |
1706 | list_del_init(&nfsi->access_cache_inode_lru); | 1739 | list_del_init(&nfsi->access_cache_inode_lru); |
1740 | smp_mb__before_clear_bit(); | ||
1707 | clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags); | 1741 | clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags); |
1742 | smp_mb__after_clear_bit(); | ||
1708 | } | 1743 | } |
1709 | spin_unlock(&inode->i_lock); | ||
1710 | spin_unlock(&nfs_access_lru_lock); | ||
1711 | iput(inode); | ||
1712 | up_read(s_umount); | ||
1713 | goto restart; | ||
1714 | } | 1744 | } |
1715 | spin_unlock(&nfs_access_lru_lock); | 1745 | spin_unlock(&nfs_access_lru_lock); |
1716 | while (!list_empty(&head)) { | 1746 | nfs_access_free_list(&head); |
1717 | cache = list_entry(head.next, struct nfs_access_entry, lru); | ||
1718 | list_del(&cache->lru); | ||
1719 | nfs_access_free_entry(cache); | ||
1720 | } | ||
1721 | return (atomic_long_read(&nfs_access_nr_entries) / 100) * sysctl_vfs_cache_pressure; | 1747 | return (atomic_long_read(&nfs_access_nr_entries) / 100) * sysctl_vfs_cache_pressure; |
1722 | } | 1748 | } |
1723 | 1749 | ||
1724 | static void __nfs_access_zap_cache(struct inode *inode) | 1750 | static void __nfs_access_zap_cache(struct nfs_inode *nfsi, struct list_head *head) |
1725 | { | 1751 | { |
1726 | struct nfs_inode *nfsi = NFS_I(inode); | ||
1727 | struct rb_root *root_node = &nfsi->access_cache; | 1752 | struct rb_root *root_node = &nfsi->access_cache; |
1728 | struct rb_node *n, *dispose = NULL; | 1753 | struct rb_node *n; |
1729 | struct nfs_access_entry *entry; | 1754 | struct nfs_access_entry *entry; |
1730 | 1755 | ||
1731 | /* Unhook entries from the cache */ | 1756 | /* Unhook entries from the cache */ |
1732 | while ((n = rb_first(root_node)) != NULL) { | 1757 | while ((n = rb_first(root_node)) != NULL) { |
1733 | entry = rb_entry(n, struct nfs_access_entry, rb_node); | 1758 | entry = rb_entry(n, struct nfs_access_entry, rb_node); |
1734 | rb_erase(n, root_node); | 1759 | rb_erase(n, root_node); |
1735 | list_del(&entry->lru); | 1760 | list_move(&entry->lru, head); |
1736 | n->rb_left = dispose; | ||
1737 | dispose = n; | ||
1738 | } | 1761 | } |
1739 | nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS; | 1762 | nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS; |
1740 | spin_unlock(&inode->i_lock); | ||
1741 | |||
1742 | /* Now kill them all! */ | ||
1743 | while (dispose != NULL) { | ||
1744 | n = dispose; | ||
1745 | dispose = n->rb_left; | ||
1746 | nfs_access_free_entry(rb_entry(n, struct nfs_access_entry, rb_node)); | ||
1747 | } | ||
1748 | } | 1763 | } |
1749 | 1764 | ||
1750 | void nfs_access_zap_cache(struct inode *inode) | 1765 | void nfs_access_zap_cache(struct inode *inode) |
1751 | { | 1766 | { |
1767 | LIST_HEAD(head); | ||
1768 | |||
1769 | if (test_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags) == 0) | ||
1770 | return; | ||
1752 | /* Remove from global LRU init */ | 1771 | /* Remove from global LRU init */ |
1753 | if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) { | 1772 | spin_lock(&nfs_access_lru_lock); |
1754 | spin_lock(&nfs_access_lru_lock); | 1773 | if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) |
1755 | list_del_init(&NFS_I(inode)->access_cache_inode_lru); | 1774 | list_del_init(&NFS_I(inode)->access_cache_inode_lru); |
1756 | spin_unlock(&nfs_access_lru_lock); | ||
1757 | } | ||
1758 | 1775 | ||
1759 | spin_lock(&inode->i_lock); | 1776 | spin_lock(&inode->i_lock); |
1760 | /* This will release the spinlock */ | 1777 | __nfs_access_zap_cache(NFS_I(inode), &head); |
1761 | __nfs_access_zap_cache(inode); | 1778 | spin_unlock(&inode->i_lock); |
1779 | spin_unlock(&nfs_access_lru_lock); | ||
1780 | nfs_access_free_list(&head); | ||
1762 | } | 1781 | } |
1763 | 1782 | ||
1764 | static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, struct rpc_cred *cred) | 1783 | static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, struct rpc_cred *cred) |
@@ -1809,8 +1828,8 @@ out_stale: | |||
1809 | nfs_access_free_entry(cache); | 1828 | nfs_access_free_entry(cache); |
1810 | return -ENOENT; | 1829 | return -ENOENT; |
1811 | out_zap: | 1830 | out_zap: |
1812 | /* This will release the spinlock */ | 1831 | spin_unlock(&inode->i_lock); |
1813 | __nfs_access_zap_cache(inode); | 1832 | nfs_access_zap_cache(inode); |
1814 | return -ENOENT; | 1833 | return -ENOENT; |
1815 | } | 1834 | } |
1816 | 1835 | ||
@@ -1865,9 +1884,11 @@ static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *s | |||
1865 | smp_mb__after_atomic_inc(); | 1884 | smp_mb__after_atomic_inc(); |
1866 | 1885 | ||
1867 | /* Add inode to global LRU list */ | 1886 | /* Add inode to global LRU list */ |
1868 | if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) { | 1887 | if (!test_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) { |
1869 | spin_lock(&nfs_access_lru_lock); | 1888 | spin_lock(&nfs_access_lru_lock); |
1870 | list_add_tail(&NFS_I(inode)->access_cache_inode_lru, &nfs_access_lru_list); | 1889 | if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) |
1890 | list_add_tail(&NFS_I(inode)->access_cache_inode_lru, | ||
1891 | &nfs_access_lru_list); | ||
1871 | spin_unlock(&nfs_access_lru_lock); | 1892 | spin_unlock(&nfs_access_lru_lock); |
1872 | } | 1893 | } |
1873 | } | 1894 | } |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 8d965bddb87e..cac96bcc91e4 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -161,14 +161,17 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) | |||
161 | struct nfs_server *server = NFS_SERVER(inode); | 161 | struct nfs_server *server = NFS_SERVER(inode); |
162 | struct nfs_inode *nfsi = NFS_I(inode); | 162 | struct nfs_inode *nfsi = NFS_I(inode); |
163 | 163 | ||
164 | if (server->flags & NFS_MOUNT_NOAC) | 164 | if (nfs_have_delegated_attributes(inode)) |
165 | goto force_reval; | 165 | goto out_noreval; |
166 | |||
166 | if (filp->f_flags & O_DIRECT) | 167 | if (filp->f_flags & O_DIRECT) |
167 | goto force_reval; | 168 | goto force_reval; |
168 | if (nfsi->npages != 0) | 169 | if (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) |
169 | return 0; | 170 | goto force_reval; |
170 | if (!(nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode)) | 171 | if (nfs_attribute_timeout(inode)) |
171 | return 0; | 172 | goto force_reval; |
173 | out_noreval: | ||
174 | return 0; | ||
172 | force_reval: | 175 | force_reval: |
173 | return __nfs_revalidate_inode(server, inode); | 176 | return __nfs_revalidate_inode(server, inode); |
174 | } | 177 | } |
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index a6b16ed93229..ce153a6b3aec 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c | |||
@@ -467,7 +467,8 @@ int __nfs_readpages_from_fscache(struct nfs_open_context *ctx, | |||
467 | struct list_head *pages, | 467 | struct list_head *pages, |
468 | unsigned *nr_pages) | 468 | unsigned *nr_pages) |
469 | { | 469 | { |
470 | int ret, npages = *nr_pages; | 470 | unsigned npages = *nr_pages; |
471 | int ret; | ||
471 | 472 | ||
472 | dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n", | 473 | dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n", |
473 | NFS_I(inode)->fscache, npages, inode); | 474 | NFS_I(inode)->fscache, npages, inode); |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index b35d2a616066..7428f7d6273b 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -78,159 +78,94 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
78 | { | 78 | { |
79 | struct nfs_server *server = NFS_SB(sb); | 79 | struct nfs_server *server = NFS_SB(sb); |
80 | struct nfs_fsinfo fsinfo; | 80 | struct nfs_fsinfo fsinfo; |
81 | struct nfs_fattr fattr; | 81 | struct dentry *ret; |
82 | struct dentry *mntroot; | ||
83 | struct inode *inode; | 82 | struct inode *inode; |
84 | int error; | 83 | int error; |
85 | 84 | ||
86 | /* get the actual root for this mount */ | 85 | /* get the actual root for this mount */ |
87 | fsinfo.fattr = &fattr; | 86 | fsinfo.fattr = nfs_alloc_fattr(); |
87 | if (fsinfo.fattr == NULL) | ||
88 | return ERR_PTR(-ENOMEM); | ||
88 | 89 | ||
89 | error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); | 90 | error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); |
90 | if (error < 0) { | 91 | if (error < 0) { |
91 | dprintk("nfs_get_root: getattr error = %d\n", -error); | 92 | dprintk("nfs_get_root: getattr error = %d\n", -error); |
92 | return ERR_PTR(error); | 93 | ret = ERR_PTR(error); |
94 | goto out; | ||
93 | } | 95 | } |
94 | 96 | ||
95 | inode = nfs_fhget(sb, mntfh, fsinfo.fattr); | 97 | inode = nfs_fhget(sb, mntfh, fsinfo.fattr); |
96 | if (IS_ERR(inode)) { | 98 | if (IS_ERR(inode)) { |
97 | dprintk("nfs_get_root: get root inode failed\n"); | 99 | dprintk("nfs_get_root: get root inode failed\n"); |
98 | return ERR_CAST(inode); | 100 | ret = ERR_CAST(inode); |
101 | goto out; | ||
99 | } | 102 | } |
100 | 103 | ||
101 | error = nfs_superblock_set_dummy_root(sb, inode); | 104 | error = nfs_superblock_set_dummy_root(sb, inode); |
102 | if (error != 0) | 105 | if (error != 0) { |
103 | return ERR_PTR(error); | 106 | ret = ERR_PTR(error); |
107 | goto out; | ||
108 | } | ||
104 | 109 | ||
105 | /* root dentries normally start off anonymous and get spliced in later | 110 | /* root dentries normally start off anonymous and get spliced in later |
106 | * if the dentry tree reaches them; however if the dentry already | 111 | * if the dentry tree reaches them; however if the dentry already |
107 | * exists, we'll pick it up at this point and use it as the root | 112 | * exists, we'll pick it up at this point and use it as the root |
108 | */ | 113 | */ |
109 | mntroot = d_obtain_alias(inode); | 114 | ret = d_obtain_alias(inode); |
110 | if (IS_ERR(mntroot)) { | 115 | if (IS_ERR(ret)) { |
111 | dprintk("nfs_get_root: get root dentry failed\n"); | 116 | dprintk("nfs_get_root: get root dentry failed\n"); |
112 | return mntroot; | 117 | goto out; |
113 | } | 118 | } |
114 | 119 | ||
115 | security_d_instantiate(mntroot, inode); | 120 | security_d_instantiate(ret, inode); |
116 | |||
117 | if (!mntroot->d_op) | ||
118 | mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; | ||
119 | 121 | ||
120 | return mntroot; | 122 | if (ret->d_op == NULL) |
123 | ret->d_op = server->nfs_client->rpc_ops->dentry_ops; | ||
124 | out: | ||
125 | nfs_free_fattr(fsinfo.fattr); | ||
126 | return ret; | ||
121 | } | 127 | } |
122 | 128 | ||
123 | #ifdef CONFIG_NFS_V4 | 129 | #ifdef CONFIG_NFS_V4 |
124 | 130 | ||
125 | /* | 131 | int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh) |
126 | * Do a simple pathwalk from the root FH of the server to the nominated target | ||
127 | * of the mountpoint | ||
128 | * - give error on symlinks | ||
129 | * - give error on ".." occurring in the path | ||
130 | * - follow traversals | ||
131 | */ | ||
132 | int nfs4_path_walk(struct nfs_server *server, | ||
133 | struct nfs_fh *mntfh, | ||
134 | const char *path) | ||
135 | { | 132 | { |
136 | struct nfs_fsinfo fsinfo; | 133 | struct nfs_fsinfo fsinfo; |
137 | struct nfs_fattr fattr; | 134 | int ret = -ENOMEM; |
138 | struct nfs_fh lastfh; | ||
139 | struct qstr name; | ||
140 | int ret; | ||
141 | 135 | ||
142 | dprintk("--> nfs4_path_walk(,,%s)\n", path); | 136 | dprintk("--> nfs4_get_rootfh()\n"); |
143 | 137 | ||
144 | fsinfo.fattr = &fattr; | 138 | fsinfo.fattr = nfs_alloc_fattr(); |
145 | nfs_fattr_init(&fattr); | 139 | if (fsinfo.fattr == NULL) |
146 | 140 | goto out; | |
147 | /* Eat leading slashes */ | ||
148 | while (*path == '/') | ||
149 | path++; | ||
150 | 141 | ||
151 | /* Start by getting the root filehandle from the server */ | 142 | /* Start by getting the root filehandle from the server */ |
152 | ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); | 143 | ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); |
153 | if (ret < 0) { | 144 | if (ret < 0) { |
154 | dprintk("nfs4_get_root: getroot error = %d\n", -ret); | 145 | dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret); |
155 | return ret; | 146 | goto out; |
156 | } | 147 | } |
157 | 148 | ||
158 | if (!S_ISDIR(fattr.mode)) { | 149 | if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_MODE) |
159 | printk(KERN_ERR "nfs4_get_root:" | 150 | || !S_ISDIR(fsinfo.fattr->mode)) { |
151 | printk(KERN_ERR "nfs4_get_rootfh:" | ||
160 | " getroot encountered non-directory\n"); | 152 | " getroot encountered non-directory\n"); |
161 | return -ENOTDIR; | 153 | ret = -ENOTDIR; |
154 | goto out; | ||
162 | } | 155 | } |
163 | 156 | ||
164 | /* FIXME: It is quite valid for the server to return a referral here */ | 157 | if (fsinfo.fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) { |
165 | if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { | 158 | printk(KERN_ERR "nfs4_get_rootfh:" |
166 | printk(KERN_ERR "nfs4_get_root:" | ||
167 | " getroot obtained referral\n"); | 159 | " getroot obtained referral\n"); |
168 | return -EREMOTE; | 160 | ret = -EREMOTE; |
169 | } | 161 | goto out; |
170 | |||
171 | next_component: | ||
172 | dprintk("Next: %s\n", path); | ||
173 | |||
174 | /* extract the next bit of the path */ | ||
175 | if (!*path) | ||
176 | goto path_walk_complete; | ||
177 | |||
178 | name.name = path; | ||
179 | while (*path && *path != '/') | ||
180 | path++; | ||
181 | name.len = path - (const char *) name.name; | ||
182 | |||
183 | if (name.len > NFS4_MAXNAMLEN) | ||
184 | return -ENAMETOOLONG; | ||
185 | |||
186 | eat_dot_dir: | ||
187 | while (*path == '/') | ||
188 | path++; | ||
189 | |||
190 | if (path[0] == '.' && (path[1] == '/' || !path[1])) { | ||
191 | path += 2; | ||
192 | goto eat_dot_dir; | ||
193 | } | ||
194 | |||
195 | /* FIXME: Why shouldn't the user be able to use ".." in the path? */ | ||
196 | if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2]) | ||
197 | ) { | ||
198 | printk(KERN_ERR "nfs4_get_root:" | ||
199 | " Mount path contains reference to \"..\"\n"); | ||
200 | return -EINVAL; | ||
201 | } | 162 | } |
202 | 163 | ||
203 | /* lookup the next FH in the sequence */ | 164 | memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid)); |
204 | memcpy(&lastfh, mntfh, sizeof(lastfh)); | 165 | out: |
205 | 166 | nfs_free_fattr(fsinfo.fattr); | |
206 | dprintk("LookupFH: %*.*s [%s]\n", name.len, name.len, name.name, path); | 167 | dprintk("<-- nfs4_get_rootfh() = %d\n", ret); |
207 | 168 | return ret; | |
208 | ret = server->nfs_client->rpc_ops->lookupfh(server, &lastfh, &name, | ||
209 | mntfh, &fattr); | ||
210 | if (ret < 0) { | ||
211 | dprintk("nfs4_get_root: getroot error = %d\n", -ret); | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | if (!S_ISDIR(fattr.mode)) { | ||
216 | printk(KERN_ERR "nfs4_get_root:" | ||
217 | " lookupfh encountered non-directory\n"); | ||
218 | return -ENOTDIR; | ||
219 | } | ||
220 | |||
221 | /* FIXME: Referrals are quite valid here too */ | ||
222 | if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { | ||
223 | printk(KERN_ERR "nfs4_get_root:" | ||
224 | " lookupfh obtained referral\n"); | ||
225 | return -EREMOTE; | ||
226 | } | ||
227 | |||
228 | goto next_component; | ||
229 | |||
230 | path_walk_complete: | ||
231 | memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); | ||
232 | dprintk("<-- nfs4_path_walk() = 0\n"); | ||
233 | return 0; | ||
234 | } | 169 | } |
235 | 170 | ||
236 | /* | 171 | /* |
@@ -239,8 +174,8 @@ path_walk_complete: | |||
239 | struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | 174 | struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) |
240 | { | 175 | { |
241 | struct nfs_server *server = NFS_SB(sb); | 176 | struct nfs_server *server = NFS_SB(sb); |
242 | struct nfs_fattr fattr; | 177 | struct nfs_fattr *fattr = NULL; |
243 | struct dentry *mntroot; | 178 | struct dentry *ret; |
244 | struct inode *inode; | 179 | struct inode *inode; |
245 | int error; | 180 | int error; |
246 | 181 | ||
@@ -254,40 +189,50 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
254 | return ERR_PTR(error); | 189 | return ERR_PTR(error); |
255 | } | 190 | } |
256 | 191 | ||
192 | fattr = nfs_alloc_fattr(); | ||
193 | if (fattr == NULL) | ||
194 | return ERR_PTR(-ENOMEM);; | ||
195 | |||
257 | /* get the actual root for this mount */ | 196 | /* get the actual root for this mount */ |
258 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); | 197 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr); |
259 | if (error < 0) { | 198 | if (error < 0) { |
260 | dprintk("nfs_get_root: getattr error = %d\n", -error); | 199 | dprintk("nfs_get_root: getattr error = %d\n", -error); |
261 | return ERR_PTR(error); | 200 | ret = ERR_PTR(error); |
201 | goto out; | ||
262 | } | 202 | } |
263 | 203 | ||
264 | inode = nfs_fhget(sb, mntfh, &fattr); | 204 | inode = nfs_fhget(sb, mntfh, fattr); |
265 | if (IS_ERR(inode)) { | 205 | if (IS_ERR(inode)) { |
266 | dprintk("nfs_get_root: get root inode failed\n"); | 206 | dprintk("nfs_get_root: get root inode failed\n"); |
267 | return ERR_CAST(inode); | 207 | ret = ERR_CAST(inode); |
208 | goto out; | ||
268 | } | 209 | } |
269 | 210 | ||
270 | error = nfs_superblock_set_dummy_root(sb, inode); | 211 | error = nfs_superblock_set_dummy_root(sb, inode); |
271 | if (error != 0) | 212 | if (error != 0) { |
272 | return ERR_PTR(error); | 213 | ret = ERR_PTR(error); |
214 | goto out; | ||
215 | } | ||
273 | 216 | ||
274 | /* root dentries normally start off anonymous and get spliced in later | 217 | /* root dentries normally start off anonymous and get spliced in later |
275 | * if the dentry tree reaches them; however if the dentry already | 218 | * if the dentry tree reaches them; however if the dentry already |
276 | * exists, we'll pick it up at this point and use it as the root | 219 | * exists, we'll pick it up at this point and use it as the root |
277 | */ | 220 | */ |
278 | mntroot = d_obtain_alias(inode); | 221 | ret = d_obtain_alias(inode); |
279 | if (IS_ERR(mntroot)) { | 222 | if (IS_ERR(ret)) { |
280 | dprintk("nfs_get_root: get root dentry failed\n"); | 223 | dprintk("nfs_get_root: get root dentry failed\n"); |
281 | return mntroot; | 224 | goto out; |
282 | } | 225 | } |
283 | 226 | ||
284 | security_d_instantiate(mntroot, inode); | 227 | security_d_instantiate(ret, inode); |
285 | 228 | ||
286 | if (!mntroot->d_op) | 229 | if (ret->d_op == NULL) |
287 | mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; | 230 | ret->d_op = server->nfs_client->rpc_ops->dentry_ops; |
288 | 231 | ||
232 | out: | ||
233 | nfs_free_fattr(fattr); | ||
289 | dprintk("<-- nfs4_get_root()\n"); | 234 | dprintk("<-- nfs4_get_root()\n"); |
290 | return mntroot; | 235 | return ret; |
291 | } | 236 | } |
292 | 237 | ||
293 | #endif /* CONFIG_NFS_V4 */ | 238 | #endif /* CONFIG_NFS_V4 */ |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 50a56edca0b5..099b3518feea 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -393,8 +393,8 @@ int | |||
393 | nfs_setattr(struct dentry *dentry, struct iattr *attr) | 393 | nfs_setattr(struct dentry *dentry, struct iattr *attr) |
394 | { | 394 | { |
395 | struct inode *inode = dentry->d_inode; | 395 | struct inode *inode = dentry->d_inode; |
396 | struct nfs_fattr fattr; | 396 | struct nfs_fattr *fattr; |
397 | int error; | 397 | int error = -ENOMEM; |
398 | 398 | ||
399 | nfs_inc_stats(inode, NFSIOS_VFSSETATTR); | 399 | nfs_inc_stats(inode, NFSIOS_VFSSETATTR); |
400 | 400 | ||
@@ -417,14 +417,20 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
417 | filemap_write_and_wait(inode->i_mapping); | 417 | filemap_write_and_wait(inode->i_mapping); |
418 | nfs_wb_all(inode); | 418 | nfs_wb_all(inode); |
419 | } | 419 | } |
420 | |||
421 | fattr = nfs_alloc_fattr(); | ||
422 | if (fattr == NULL) | ||
423 | goto out; | ||
420 | /* | 424 | /* |
421 | * Return any delegations if we're going to change ACLs | 425 | * Return any delegations if we're going to change ACLs |
422 | */ | 426 | */ |
423 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) | 427 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) |
424 | nfs_inode_return_delegation(inode); | 428 | nfs_inode_return_delegation(inode); |
425 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); | 429 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); |
426 | if (error == 0) | 430 | if (error == 0) |
427 | nfs_refresh_inode(inode, &fattr); | 431 | nfs_refresh_inode(inode, fattr); |
432 | nfs_free_fattr(fattr); | ||
433 | out: | ||
428 | return error; | 434 | return error; |
429 | } | 435 | } |
430 | 436 | ||
@@ -682,7 +688,7 @@ int | |||
682 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 688 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
683 | { | 689 | { |
684 | int status = -ESTALE; | 690 | int status = -ESTALE; |
685 | struct nfs_fattr fattr; | 691 | struct nfs_fattr *fattr = NULL; |
686 | struct nfs_inode *nfsi = NFS_I(inode); | 692 | struct nfs_inode *nfsi = NFS_I(inode); |
687 | 693 | ||
688 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 694 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
@@ -693,8 +699,13 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
693 | if (NFS_STALE(inode)) | 699 | if (NFS_STALE(inode)) |
694 | goto out; | 700 | goto out; |
695 | 701 | ||
702 | status = -ENOMEM; | ||
703 | fattr = nfs_alloc_fattr(); | ||
704 | if (fattr == NULL) | ||
705 | goto out; | ||
706 | |||
696 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | 707 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); |
697 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 708 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr); |
698 | if (status != 0) { | 709 | if (status != 0) { |
699 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 710 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", |
700 | inode->i_sb->s_id, | 711 | inode->i_sb->s_id, |
@@ -707,7 +718,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
707 | goto out; | 718 | goto out; |
708 | } | 719 | } |
709 | 720 | ||
710 | status = nfs_refresh_inode(inode, &fattr); | 721 | status = nfs_refresh_inode(inode, fattr); |
711 | if (status) { | 722 | if (status) { |
712 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 723 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
713 | inode->i_sb->s_id, | 724 | inode->i_sb->s_id, |
@@ -723,6 +734,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
723 | (long long)NFS_FILEID(inode)); | 734 | (long long)NFS_FILEID(inode)); |
724 | 735 | ||
725 | out: | 736 | out: |
737 | nfs_free_fattr(fattr); | ||
726 | return status; | 738 | return status; |
727 | } | 739 | } |
728 | 740 | ||
@@ -730,9 +742,14 @@ int nfs_attribute_timeout(struct inode *inode) | |||
730 | { | 742 | { |
731 | struct nfs_inode *nfsi = NFS_I(inode); | 743 | struct nfs_inode *nfsi = NFS_I(inode); |
732 | 744 | ||
745 | return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); | ||
746 | } | ||
747 | |||
748 | static int nfs_attribute_cache_expired(struct inode *inode) | ||
749 | { | ||
733 | if (nfs_have_delegated_attributes(inode)) | 750 | if (nfs_have_delegated_attributes(inode)) |
734 | return 0; | 751 | return 0; |
735 | return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); | 752 | return nfs_attribute_timeout(inode); |
736 | } | 753 | } |
737 | 754 | ||
738 | /** | 755 | /** |
@@ -745,7 +762,7 @@ int nfs_attribute_timeout(struct inode *inode) | |||
745 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 762 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
746 | { | 763 | { |
747 | if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR) | 764 | if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR) |
748 | && !nfs_attribute_timeout(inode)) | 765 | && !nfs_attribute_cache_expired(inode)) |
749 | return NFS_STALE(inode) ? -ESTALE : 0; | 766 | return NFS_STALE(inode) ? -ESTALE : 0; |
750 | return __nfs_revalidate_inode(server, inode); | 767 | return __nfs_revalidate_inode(server, inode); |
751 | } | 768 | } |
@@ -782,7 +799,8 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
782 | int ret = 0; | 799 | int ret = 0; |
783 | 800 | ||
784 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) | 801 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) |
785 | || nfs_attribute_timeout(inode) || NFS_STALE(inode)) { | 802 | || nfs_attribute_cache_expired(inode) |
803 | || NFS_STALE(inode)) { | ||
786 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 804 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
787 | if (ret < 0) | 805 | if (ret < 0) |
788 | goto out; | 806 | goto out; |
@@ -916,6 +934,26 @@ void nfs_fattr_init(struct nfs_fattr *fattr) | |||
916 | fattr->gencount = nfs_inc_attr_generation_counter(); | 934 | fattr->gencount = nfs_inc_attr_generation_counter(); |
917 | } | 935 | } |
918 | 936 | ||
937 | struct nfs_fattr *nfs_alloc_fattr(void) | ||
938 | { | ||
939 | struct nfs_fattr *fattr; | ||
940 | |||
941 | fattr = kmalloc(sizeof(*fattr), GFP_NOFS); | ||
942 | if (fattr != NULL) | ||
943 | nfs_fattr_init(fattr); | ||
944 | return fattr; | ||
945 | } | ||
946 | |||
947 | struct nfs_fh *nfs_alloc_fhandle(void) | ||
948 | { | ||
949 | struct nfs_fh *fh; | ||
950 | |||
951 | fh = kmalloc(sizeof(struct nfs_fh), GFP_NOFS); | ||
952 | if (fh != NULL) | ||
953 | fh->size = 0; | ||
954 | return fh; | ||
955 | } | ||
956 | |||
919 | /** | 957 | /** |
920 | * nfs_inode_attrs_need_update - check if the inode attributes need updating | 958 | * nfs_inode_attrs_need_update - check if the inode attributes need updating |
921 | * @inode - pointer to inode | 959 | * @inode - pointer to inode |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 11f82f03c5de..d8bd619e386c 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -244,9 +244,7 @@ extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *); | |||
244 | #ifdef CONFIG_NFS_V4 | 244 | #ifdef CONFIG_NFS_V4 |
245 | extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); | 245 | extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); |
246 | 246 | ||
247 | extern int nfs4_path_walk(struct nfs_server *server, | 247 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); |
248 | struct nfs_fh *mntfh, | ||
249 | const char *path); | ||
250 | #endif | 248 | #endif |
251 | 249 | ||
252 | /* read.c */ | 250 | /* read.c */ |
diff --git a/fs/nfs/iostat.h b/fs/nfs/iostat.h index 1d8d5c813b01..c5832487c456 100644 --- a/fs/nfs/iostat.h +++ b/fs/nfs/iostat.h | |||
@@ -36,14 +36,14 @@ static inline void nfs_inc_stats(const struct inode *inode, | |||
36 | 36 | ||
37 | static inline void nfs_add_server_stats(const struct nfs_server *server, | 37 | static inline void nfs_add_server_stats(const struct nfs_server *server, |
38 | enum nfs_stat_bytecounters stat, | 38 | enum nfs_stat_bytecounters stat, |
39 | unsigned long addend) | 39 | long addend) |
40 | { | 40 | { |
41 | this_cpu_add(server->io_stats->bytes[stat], addend); | 41 | this_cpu_add(server->io_stats->bytes[stat], addend); |
42 | } | 42 | } |
43 | 43 | ||
44 | static inline void nfs_add_stats(const struct inode *inode, | 44 | static inline void nfs_add_stats(const struct inode *inode, |
45 | enum nfs_stat_bytecounters stat, | 45 | enum nfs_stat_bytecounters stat, |
46 | unsigned long addend) | 46 | long addend) |
47 | { | 47 | { |
48 | nfs_add_server_stats(NFS_SERVER(inode), stat, addend); | 48 | nfs_add_server_stats(NFS_SERVER(inode), stat, addend); |
49 | } | 49 | } |
@@ -51,7 +51,7 @@ static inline void nfs_add_stats(const struct inode *inode, | |||
51 | #ifdef CONFIG_NFS_FSCACHE | 51 | #ifdef CONFIG_NFS_FSCACHE |
52 | static inline void nfs_add_fscache_stats(struct inode *inode, | 52 | static inline void nfs_add_fscache_stats(struct inode *inode, |
53 | enum nfs_stat_fscachecounters stat, | 53 | enum nfs_stat_fscachecounters stat, |
54 | unsigned long addend) | 54 | long addend) |
55 | { | 55 | { |
56 | this_cpu_add(NFS_SERVER(inode)->io_stats->fscache[stat], addend); | 56 | this_cpu_add(NFS_SERVER(inode)->io_stats->fscache[stat], addend); |
57 | } | 57 | } |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 7888cf36022d..db6aa3673cf3 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -105,8 +105,8 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
105 | struct vfsmount *mnt; | 105 | struct vfsmount *mnt; |
106 | struct nfs_server *server = NFS_SERVER(dentry->d_inode); | 106 | struct nfs_server *server = NFS_SERVER(dentry->d_inode); |
107 | struct dentry *parent; | 107 | struct dentry *parent; |
108 | struct nfs_fh fh; | 108 | struct nfs_fh *fh = NULL; |
109 | struct nfs_fattr fattr; | 109 | struct nfs_fattr *fattr = NULL; |
110 | int err; | 110 | int err; |
111 | 111 | ||
112 | dprintk("--> nfs_follow_mountpoint()\n"); | 112 | dprintk("--> nfs_follow_mountpoint()\n"); |
@@ -115,6 +115,12 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
115 | if (IS_ROOT(dentry)) | 115 | if (IS_ROOT(dentry)) |
116 | goto out_err; | 116 | goto out_err; |
117 | 117 | ||
118 | err = -ENOMEM; | ||
119 | fh = nfs_alloc_fhandle(); | ||
120 | fattr = nfs_alloc_fattr(); | ||
121 | if (fh == NULL || fattr == NULL) | ||
122 | goto out_err; | ||
123 | |||
118 | dprintk("%s: enter\n", __func__); | 124 | dprintk("%s: enter\n", __func__); |
119 | dput(nd->path.dentry); | 125 | dput(nd->path.dentry); |
120 | nd->path.dentry = dget(dentry); | 126 | nd->path.dentry = dget(dentry); |
@@ -123,16 +129,16 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
123 | parent = dget_parent(nd->path.dentry); | 129 | parent = dget_parent(nd->path.dentry); |
124 | err = server->nfs_client->rpc_ops->lookup(parent->d_inode, | 130 | err = server->nfs_client->rpc_ops->lookup(parent->d_inode, |
125 | &nd->path.dentry->d_name, | 131 | &nd->path.dentry->d_name, |
126 | &fh, &fattr); | 132 | fh, fattr); |
127 | dput(parent); | 133 | dput(parent); |
128 | if (err != 0) | 134 | if (err != 0) |
129 | goto out_err; | 135 | goto out_err; |
130 | 136 | ||
131 | if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) | 137 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
132 | mnt = nfs_do_refmount(nd->path.mnt, nd->path.dentry); | 138 | mnt = nfs_do_refmount(nd->path.mnt, nd->path.dentry); |
133 | else | 139 | else |
134 | mnt = nfs_do_submount(nd->path.mnt, nd->path.dentry, &fh, | 140 | mnt = nfs_do_submount(nd->path.mnt, nd->path.dentry, fh, |
135 | &fattr); | 141 | fattr); |
136 | err = PTR_ERR(mnt); | 142 | err = PTR_ERR(mnt); |
137 | if (IS_ERR(mnt)) | 143 | if (IS_ERR(mnt)) |
138 | goto out_err; | 144 | goto out_err; |
@@ -151,6 +157,8 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
151 | nd->path.dentry = dget(mnt->mnt_root); | 157 | nd->path.dentry = dget(mnt->mnt_root); |
152 | schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout); | 158 | schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout); |
153 | out: | 159 | out: |
160 | nfs_free_fattr(fattr); | ||
161 | nfs_free_fhandle(fh); | ||
154 | dprintk("%s: done, returned %d\n", __func__, err); | 162 | dprintk("%s: done, returned %d\n", __func__, err); |
155 | 163 | ||
156 | dprintk("<-- nfs_follow_mountpoint() = %d\n", err); | 164 | dprintk("<-- nfs_follow_mountpoint() = %d\n", err); |
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index d150ae0c5ecd..9f88c5f4c7e2 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -185,7 +185,6 @@ static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl, | |||
185 | struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | 185 | struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) |
186 | { | 186 | { |
187 | struct nfs_server *server = NFS_SERVER(inode); | 187 | struct nfs_server *server = NFS_SERVER(inode); |
188 | struct nfs_fattr fattr; | ||
189 | struct page *pages[NFSACL_MAXPAGES] = { }; | 188 | struct page *pages[NFSACL_MAXPAGES] = { }; |
190 | struct nfs3_getaclargs args = { | 189 | struct nfs3_getaclargs args = { |
191 | .fh = NFS_FH(inode), | 190 | .fh = NFS_FH(inode), |
@@ -193,7 +192,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | |||
193 | .pages = pages, | 192 | .pages = pages, |
194 | }; | 193 | }; |
195 | struct nfs3_getaclres res = { | 194 | struct nfs3_getaclres res = { |
196 | .fattr = &fattr, | 195 | 0 |
197 | }; | 196 | }; |
198 | struct rpc_message msg = { | 197 | struct rpc_message msg = { |
199 | .rpc_argp = &args, | 198 | .rpc_argp = &args, |
@@ -228,7 +227,10 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | |||
228 | 227 | ||
229 | dprintk("NFS call getacl\n"); | 228 | dprintk("NFS call getacl\n"); |
230 | msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL]; | 229 | msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL]; |
231 | nfs_fattr_init(&fattr); | 230 | res.fattr = nfs_alloc_fattr(); |
231 | if (res.fattr == NULL) | ||
232 | return ERR_PTR(-ENOMEM); | ||
233 | |||
232 | status = rpc_call_sync(server->client_acl, &msg, 0); | 234 | status = rpc_call_sync(server->client_acl, &msg, 0); |
233 | dprintk("NFS reply getacl: %d\n", status); | 235 | dprintk("NFS reply getacl: %d\n", status); |
234 | 236 | ||
@@ -238,7 +240,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | |||
238 | 240 | ||
239 | switch (status) { | 241 | switch (status) { |
240 | case 0: | 242 | case 0: |
241 | status = nfs_refresh_inode(inode, &fattr); | 243 | status = nfs_refresh_inode(inode, res.fattr); |
242 | break; | 244 | break; |
243 | case -EPFNOSUPPORT: | 245 | case -EPFNOSUPPORT: |
244 | case -EPROTONOSUPPORT: | 246 | case -EPROTONOSUPPORT: |
@@ -278,6 +280,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | |||
278 | getout: | 280 | getout: |
279 | posix_acl_release(res.acl_access); | 281 | posix_acl_release(res.acl_access); |
280 | posix_acl_release(res.acl_default); | 282 | posix_acl_release(res.acl_default); |
283 | nfs_free_fattr(res.fattr); | ||
281 | 284 | ||
282 | if (status != 0) { | 285 | if (status != 0) { |
283 | posix_acl_release(acl); | 286 | posix_acl_release(acl); |
@@ -290,7 +293,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | |||
290 | struct posix_acl *dfacl) | 293 | struct posix_acl *dfacl) |
291 | { | 294 | { |
292 | struct nfs_server *server = NFS_SERVER(inode); | 295 | struct nfs_server *server = NFS_SERVER(inode); |
293 | struct nfs_fattr fattr; | 296 | struct nfs_fattr *fattr; |
294 | struct page *pages[NFSACL_MAXPAGES]; | 297 | struct page *pages[NFSACL_MAXPAGES]; |
295 | struct nfs3_setaclargs args = { | 298 | struct nfs3_setaclargs args = { |
296 | .inode = inode, | 299 | .inode = inode, |
@@ -335,8 +338,13 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | |||
335 | } | 338 | } |
336 | 339 | ||
337 | dprintk("NFS call setacl\n"); | 340 | dprintk("NFS call setacl\n"); |
341 | status = -ENOMEM; | ||
342 | fattr = nfs_alloc_fattr(); | ||
343 | if (fattr == NULL) | ||
344 | goto out_freepages; | ||
345 | |||
338 | msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL]; | 346 | msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL]; |
339 | nfs_fattr_init(&fattr); | 347 | msg.rpc_resp = fattr; |
340 | status = rpc_call_sync(server->client_acl, &msg, 0); | 348 | status = rpc_call_sync(server->client_acl, &msg, 0); |
341 | nfs_access_zap_cache(inode); | 349 | nfs_access_zap_cache(inode); |
342 | nfs_zap_acl_cache(inode); | 350 | nfs_zap_acl_cache(inode); |
@@ -344,7 +352,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | |||
344 | 352 | ||
345 | switch (status) { | 353 | switch (status) { |
346 | case 0: | 354 | case 0: |
347 | status = nfs_refresh_inode(inode, &fattr); | 355 | status = nfs_refresh_inode(inode, fattr); |
348 | nfs3_cache_acls(inode, acl, dfacl); | 356 | nfs3_cache_acls(inode, acl, dfacl); |
349 | break; | 357 | break; |
350 | case -EPFNOSUPPORT: | 358 | case -EPFNOSUPPORT: |
@@ -355,6 +363,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | |||
355 | case -ENOTSUPP: | 363 | case -ENOTSUPP: |
356 | status = -EOPNOTSUPP; | 364 | status = -EOPNOTSUPP; |
357 | } | 365 | } |
366 | nfs_free_fattr(fattr); | ||
358 | out_freepages: | 367 | out_freepages: |
359 | while (args.npages != 0) { | 368 | while (args.npages != 0) { |
360 | args.npages--; | 369 | args.npages--; |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index e701002694e5..fabb4f2849a1 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -144,14 +144,12 @@ static int | |||
144 | nfs3_proc_lookup(struct inode *dir, struct qstr *name, | 144 | nfs3_proc_lookup(struct inode *dir, struct qstr *name, |
145 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 145 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
146 | { | 146 | { |
147 | struct nfs_fattr dir_attr; | ||
148 | struct nfs3_diropargs arg = { | 147 | struct nfs3_diropargs arg = { |
149 | .fh = NFS_FH(dir), | 148 | .fh = NFS_FH(dir), |
150 | .name = name->name, | 149 | .name = name->name, |
151 | .len = name->len | 150 | .len = name->len |
152 | }; | 151 | }; |
153 | struct nfs3_diropres res = { | 152 | struct nfs3_diropres res = { |
154 | .dir_attr = &dir_attr, | ||
155 | .fh = fhandle, | 153 | .fh = fhandle, |
156 | .fattr = fattr | 154 | .fattr = fattr |
157 | }; | 155 | }; |
@@ -163,29 +161,30 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name, | |||
163 | int status; | 161 | int status; |
164 | 162 | ||
165 | dprintk("NFS call lookup %s\n", name->name); | 163 | dprintk("NFS call lookup %s\n", name->name); |
166 | nfs_fattr_init(&dir_attr); | 164 | res.dir_attr = nfs_alloc_fattr(); |
165 | if (res.dir_attr == NULL) | ||
166 | return -ENOMEM; | ||
167 | |||
167 | nfs_fattr_init(fattr); | 168 | nfs_fattr_init(fattr); |
168 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 169 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
169 | nfs_refresh_inode(dir, &dir_attr); | 170 | nfs_refresh_inode(dir, res.dir_attr); |
170 | if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) { | 171 | if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) { |
171 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; | 172 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; |
172 | msg.rpc_argp = fhandle; | 173 | msg.rpc_argp = fhandle; |
173 | msg.rpc_resp = fattr; | 174 | msg.rpc_resp = fattr; |
174 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 175 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
175 | } | 176 | } |
177 | nfs_free_fattr(res.dir_attr); | ||
176 | dprintk("NFS reply lookup: %d\n", status); | 178 | dprintk("NFS reply lookup: %d\n", status); |
177 | return status; | 179 | return status; |
178 | } | 180 | } |
179 | 181 | ||
180 | static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) | 182 | static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
181 | { | 183 | { |
182 | struct nfs_fattr fattr; | ||
183 | struct nfs3_accessargs arg = { | 184 | struct nfs3_accessargs arg = { |
184 | .fh = NFS_FH(inode), | 185 | .fh = NFS_FH(inode), |
185 | }; | 186 | }; |
186 | struct nfs3_accessres res = { | 187 | struct nfs3_accessres res; |
187 | .fattr = &fattr, | ||
188 | }; | ||
189 | struct rpc_message msg = { | 188 | struct rpc_message msg = { |
190 | .rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS], | 189 | .rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS], |
191 | .rpc_argp = &arg, | 190 | .rpc_argp = &arg, |
@@ -193,7 +192,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
193 | .rpc_cred = entry->cred, | 192 | .rpc_cred = entry->cred, |
194 | }; | 193 | }; |
195 | int mode = entry->mask; | 194 | int mode = entry->mask; |
196 | int status; | 195 | int status = -ENOMEM; |
197 | 196 | ||
198 | dprintk("NFS call access\n"); | 197 | dprintk("NFS call access\n"); |
199 | 198 | ||
@@ -210,9 +209,13 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
210 | if (mode & MAY_EXEC) | 209 | if (mode & MAY_EXEC) |
211 | arg.access |= NFS3_ACCESS_EXECUTE; | 210 | arg.access |= NFS3_ACCESS_EXECUTE; |
212 | } | 211 | } |
213 | nfs_fattr_init(&fattr); | 212 | |
213 | res.fattr = nfs_alloc_fattr(); | ||
214 | if (res.fattr == NULL) | ||
215 | goto out; | ||
216 | |||
214 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 217 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
215 | nfs_refresh_inode(inode, &fattr); | 218 | nfs_refresh_inode(inode, res.fattr); |
216 | if (status == 0) { | 219 | if (status == 0) { |
217 | entry->mask = 0; | 220 | entry->mask = 0; |
218 | if (res.access & NFS3_ACCESS_READ) | 221 | if (res.access & NFS3_ACCESS_READ) |
@@ -222,6 +225,8 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
222 | if (res.access & (NFS3_ACCESS_LOOKUP|NFS3_ACCESS_EXECUTE)) | 225 | if (res.access & (NFS3_ACCESS_LOOKUP|NFS3_ACCESS_EXECUTE)) |
223 | entry->mask |= MAY_EXEC; | 226 | entry->mask |= MAY_EXEC; |
224 | } | 227 | } |
228 | nfs_free_fattr(res.fattr); | ||
229 | out: | ||
225 | dprintk("NFS reply access: %d\n", status); | 230 | dprintk("NFS reply access: %d\n", status); |
226 | return status; | 231 | return status; |
227 | } | 232 | } |
@@ -229,7 +234,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
229 | static int nfs3_proc_readlink(struct inode *inode, struct page *page, | 234 | static int nfs3_proc_readlink(struct inode *inode, struct page *page, |
230 | unsigned int pgbase, unsigned int pglen) | 235 | unsigned int pgbase, unsigned int pglen) |
231 | { | 236 | { |
232 | struct nfs_fattr fattr; | 237 | struct nfs_fattr *fattr; |
233 | struct nfs3_readlinkargs args = { | 238 | struct nfs3_readlinkargs args = { |
234 | .fh = NFS_FH(inode), | 239 | .fh = NFS_FH(inode), |
235 | .pgbase = pgbase, | 240 | .pgbase = pgbase, |
@@ -239,14 +244,19 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page, | |||
239 | struct rpc_message msg = { | 244 | struct rpc_message msg = { |
240 | .rpc_proc = &nfs3_procedures[NFS3PROC_READLINK], | 245 | .rpc_proc = &nfs3_procedures[NFS3PROC_READLINK], |
241 | .rpc_argp = &args, | 246 | .rpc_argp = &args, |
242 | .rpc_resp = &fattr, | ||
243 | }; | 247 | }; |
244 | int status; | 248 | int status = -ENOMEM; |
245 | 249 | ||
246 | dprintk("NFS call readlink\n"); | 250 | dprintk("NFS call readlink\n"); |
247 | nfs_fattr_init(&fattr); | 251 | fattr = nfs_alloc_fattr(); |
252 | if (fattr == NULL) | ||
253 | goto out; | ||
254 | msg.rpc_resp = fattr; | ||
255 | |||
248 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 256 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
249 | nfs_refresh_inode(inode, &fattr); | 257 | nfs_refresh_inode(inode, fattr); |
258 | nfs_free_fattr(fattr); | ||
259 | out: | ||
250 | dprintk("NFS reply readlink: %d\n", status); | 260 | dprintk("NFS reply readlink: %d\n", status); |
251 | return status; | 261 | return status; |
252 | } | 262 | } |
@@ -396,12 +406,17 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name) | |||
396 | .rpc_argp = &arg, | 406 | .rpc_argp = &arg, |
397 | .rpc_resp = &res, | 407 | .rpc_resp = &res, |
398 | }; | 408 | }; |
399 | int status; | 409 | int status = -ENOMEM; |
400 | 410 | ||
401 | dprintk("NFS call remove %s\n", name->name); | 411 | dprintk("NFS call remove %s\n", name->name); |
402 | nfs_fattr_init(&res.dir_attr); | 412 | res.dir_attr = nfs_alloc_fattr(); |
413 | if (res.dir_attr == NULL) | ||
414 | goto out; | ||
415 | |||
403 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 416 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
404 | nfs_post_op_update_inode(dir, &res.dir_attr); | 417 | nfs_post_op_update_inode(dir, res.dir_attr); |
418 | nfs_free_fattr(res.dir_attr); | ||
419 | out: | ||
405 | dprintk("NFS reply remove: %d\n", status); | 420 | dprintk("NFS reply remove: %d\n", status); |
406 | return status; | 421 | return status; |
407 | } | 422 | } |
@@ -419,7 +434,7 @@ nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir) | |||
419 | if (nfs3_async_handle_jukebox(task, dir)) | 434 | if (nfs3_async_handle_jukebox(task, dir)) |
420 | return 0; | 435 | return 0; |
421 | res = task->tk_msg.rpc_resp; | 436 | res = task->tk_msg.rpc_resp; |
422 | nfs_post_op_update_inode(dir, &res->dir_attr); | 437 | nfs_post_op_update_inode(dir, res->dir_attr); |
423 | return 1; | 438 | return 1; |
424 | } | 439 | } |
425 | 440 | ||
@@ -427,7 +442,6 @@ static int | |||
427 | nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name, | 442 | nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name, |
428 | struct inode *new_dir, struct qstr *new_name) | 443 | struct inode *new_dir, struct qstr *new_name) |
429 | { | 444 | { |
430 | struct nfs_fattr old_dir_attr, new_dir_attr; | ||
431 | struct nfs3_renameargs arg = { | 445 | struct nfs3_renameargs arg = { |
432 | .fromfh = NFS_FH(old_dir), | 446 | .fromfh = NFS_FH(old_dir), |
433 | .fromname = old_name->name, | 447 | .fromname = old_name->name, |
@@ -436,23 +450,27 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
436 | .toname = new_name->name, | 450 | .toname = new_name->name, |
437 | .tolen = new_name->len | 451 | .tolen = new_name->len |
438 | }; | 452 | }; |
439 | struct nfs3_renameres res = { | 453 | struct nfs3_renameres res; |
440 | .fromattr = &old_dir_attr, | ||
441 | .toattr = &new_dir_attr | ||
442 | }; | ||
443 | struct rpc_message msg = { | 454 | struct rpc_message msg = { |
444 | .rpc_proc = &nfs3_procedures[NFS3PROC_RENAME], | 455 | .rpc_proc = &nfs3_procedures[NFS3PROC_RENAME], |
445 | .rpc_argp = &arg, | 456 | .rpc_argp = &arg, |
446 | .rpc_resp = &res, | 457 | .rpc_resp = &res, |
447 | }; | 458 | }; |
448 | int status; | 459 | int status = -ENOMEM; |
449 | 460 | ||
450 | dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); | 461 | dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); |
451 | nfs_fattr_init(&old_dir_attr); | 462 | |
452 | nfs_fattr_init(&new_dir_attr); | 463 | res.fromattr = nfs_alloc_fattr(); |
464 | res.toattr = nfs_alloc_fattr(); | ||
465 | if (res.fromattr == NULL || res.toattr == NULL) | ||
466 | goto out; | ||
467 | |||
453 | status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0); | 468 | status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0); |
454 | nfs_post_op_update_inode(old_dir, &old_dir_attr); | 469 | nfs_post_op_update_inode(old_dir, res.fromattr); |
455 | nfs_post_op_update_inode(new_dir, &new_dir_attr); | 470 | nfs_post_op_update_inode(new_dir, res.toattr); |
471 | out: | ||
472 | nfs_free_fattr(res.toattr); | ||
473 | nfs_free_fattr(res.fromattr); | ||
456 | dprintk("NFS reply rename: %d\n", status); | 474 | dprintk("NFS reply rename: %d\n", status); |
457 | return status; | 475 | return status; |
458 | } | 476 | } |
@@ -460,30 +478,32 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
460 | static int | 478 | static int |
461 | nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) | 479 | nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) |
462 | { | 480 | { |
463 | struct nfs_fattr dir_attr, fattr; | ||
464 | struct nfs3_linkargs arg = { | 481 | struct nfs3_linkargs arg = { |
465 | .fromfh = NFS_FH(inode), | 482 | .fromfh = NFS_FH(inode), |
466 | .tofh = NFS_FH(dir), | 483 | .tofh = NFS_FH(dir), |
467 | .toname = name->name, | 484 | .toname = name->name, |
468 | .tolen = name->len | 485 | .tolen = name->len |
469 | }; | 486 | }; |
470 | struct nfs3_linkres res = { | 487 | struct nfs3_linkres res; |
471 | .dir_attr = &dir_attr, | ||
472 | .fattr = &fattr | ||
473 | }; | ||
474 | struct rpc_message msg = { | 488 | struct rpc_message msg = { |
475 | .rpc_proc = &nfs3_procedures[NFS3PROC_LINK], | 489 | .rpc_proc = &nfs3_procedures[NFS3PROC_LINK], |
476 | .rpc_argp = &arg, | 490 | .rpc_argp = &arg, |
477 | .rpc_resp = &res, | 491 | .rpc_resp = &res, |
478 | }; | 492 | }; |
479 | int status; | 493 | int status = -ENOMEM; |
480 | 494 | ||
481 | dprintk("NFS call link %s\n", name->name); | 495 | dprintk("NFS call link %s\n", name->name); |
482 | nfs_fattr_init(&dir_attr); | 496 | res.fattr = nfs_alloc_fattr(); |
483 | nfs_fattr_init(&fattr); | 497 | res.dir_attr = nfs_alloc_fattr(); |
498 | if (res.fattr == NULL || res.dir_attr == NULL) | ||
499 | goto out; | ||
500 | |||
484 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 501 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
485 | nfs_post_op_update_inode(dir, &dir_attr); | 502 | nfs_post_op_update_inode(dir, res.dir_attr); |
486 | nfs_post_op_update_inode(inode, &fattr); | 503 | nfs_post_op_update_inode(inode, res.fattr); |
504 | out: | ||
505 | nfs_free_fattr(res.dir_attr); | ||
506 | nfs_free_fattr(res.fattr); | ||
487 | dprintk("NFS reply link: %d\n", status); | 507 | dprintk("NFS reply link: %d\n", status); |
488 | return status; | 508 | return status; |
489 | } | 509 | } |
@@ -554,7 +574,7 @@ out: | |||
554 | static int | 574 | static int |
555 | nfs3_proc_rmdir(struct inode *dir, struct qstr *name) | 575 | nfs3_proc_rmdir(struct inode *dir, struct qstr *name) |
556 | { | 576 | { |
557 | struct nfs_fattr dir_attr; | 577 | struct nfs_fattr *dir_attr; |
558 | struct nfs3_diropargs arg = { | 578 | struct nfs3_diropargs arg = { |
559 | .fh = NFS_FH(dir), | 579 | .fh = NFS_FH(dir), |
560 | .name = name->name, | 580 | .name = name->name, |
@@ -563,14 +583,19 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name) | |||
563 | struct rpc_message msg = { | 583 | struct rpc_message msg = { |
564 | .rpc_proc = &nfs3_procedures[NFS3PROC_RMDIR], | 584 | .rpc_proc = &nfs3_procedures[NFS3PROC_RMDIR], |
565 | .rpc_argp = &arg, | 585 | .rpc_argp = &arg, |
566 | .rpc_resp = &dir_attr, | ||
567 | }; | 586 | }; |
568 | int status; | 587 | int status = -ENOMEM; |
569 | 588 | ||
570 | dprintk("NFS call rmdir %s\n", name->name); | 589 | dprintk("NFS call rmdir %s\n", name->name); |
571 | nfs_fattr_init(&dir_attr); | 590 | dir_attr = nfs_alloc_fattr(); |
591 | if (dir_attr == NULL) | ||
592 | goto out; | ||
593 | |||
594 | msg.rpc_resp = dir_attr; | ||
572 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 595 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
573 | nfs_post_op_update_inode(dir, &dir_attr); | 596 | nfs_post_op_update_inode(dir, dir_attr); |
597 | nfs_free_fattr(dir_attr); | ||
598 | out: | ||
574 | dprintk("NFS reply rmdir: %d\n", status); | 599 | dprintk("NFS reply rmdir: %d\n", status); |
575 | return status; | 600 | return status; |
576 | } | 601 | } |
@@ -589,7 +614,6 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
589 | u64 cookie, struct page *page, unsigned int count, int plus) | 614 | u64 cookie, struct page *page, unsigned int count, int plus) |
590 | { | 615 | { |
591 | struct inode *dir = dentry->d_inode; | 616 | struct inode *dir = dentry->d_inode; |
592 | struct nfs_fattr dir_attr; | ||
593 | __be32 *verf = NFS_COOKIEVERF(dir); | 617 | __be32 *verf = NFS_COOKIEVERF(dir); |
594 | struct nfs3_readdirargs arg = { | 618 | struct nfs3_readdirargs arg = { |
595 | .fh = NFS_FH(dir), | 619 | .fh = NFS_FH(dir), |
@@ -600,7 +624,6 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
600 | .pages = &page | 624 | .pages = &page |
601 | }; | 625 | }; |
602 | struct nfs3_readdirres res = { | 626 | struct nfs3_readdirres res = { |
603 | .dir_attr = &dir_attr, | ||
604 | .verf = verf, | 627 | .verf = verf, |
605 | .plus = plus | 628 | .plus = plus |
606 | }; | 629 | }; |
@@ -610,7 +633,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
610 | .rpc_resp = &res, | 633 | .rpc_resp = &res, |
611 | .rpc_cred = cred | 634 | .rpc_cred = cred |
612 | }; | 635 | }; |
613 | int status; | 636 | int status = -ENOMEM; |
614 | 637 | ||
615 | if (plus) | 638 | if (plus) |
616 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS]; | 639 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS]; |
@@ -618,12 +641,17 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
618 | dprintk("NFS call readdir%s %d\n", | 641 | dprintk("NFS call readdir%s %d\n", |
619 | plus? "plus" : "", (unsigned int) cookie); | 642 | plus? "plus" : "", (unsigned int) cookie); |
620 | 643 | ||
621 | nfs_fattr_init(&dir_attr); | 644 | res.dir_attr = nfs_alloc_fattr(); |
645 | if (res.dir_attr == NULL) | ||
646 | goto out; | ||
647 | |||
622 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 648 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
623 | 649 | ||
624 | nfs_invalidate_atime(dir); | 650 | nfs_invalidate_atime(dir); |
651 | nfs_refresh_inode(dir, res.dir_attr); | ||
625 | 652 | ||
626 | nfs_refresh_inode(dir, &dir_attr); | 653 | nfs_free_fattr(res.dir_attr); |
654 | out: | ||
627 | dprintk("NFS reply readdir: %d\n", status); | 655 | dprintk("NFS reply readdir: %d\n", status); |
628 | return status; | 656 | return status; |
629 | } | 657 | } |
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 56a86f6ac8b5..75dcfc7da365 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -762,7 +762,7 @@ nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) | |||
762 | static int | 762 | static int |
763 | nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res) | 763 | nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res) |
764 | { | 764 | { |
765 | return nfs3_xdr_wccstat(req, p, &res->dir_attr); | 765 | return nfs3_xdr_wccstat(req, p, res->dir_attr); |
766 | } | 766 | } |
767 | 767 | ||
768 | /* | 768 | /* |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index a187200a7aac..c538c6106e16 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -206,14 +206,14 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t); | |||
206 | 206 | ||
207 | 207 | ||
208 | /* nfs4proc.c */ | 208 | /* nfs4proc.c */ |
209 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *); | 209 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); |
210 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *); | 210 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); |
211 | extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); | 211 | extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); |
212 | extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); | 212 | extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); |
213 | extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); | 213 | extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); |
214 | extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); | 214 | extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); |
215 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); | 215 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); |
216 | extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait); | 216 | extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait); |
217 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); | 217 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); |
218 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); | 218 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); |
219 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); | 219 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); |
@@ -286,7 +286,7 @@ extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | |||
286 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); | 286 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); |
287 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); | 287 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); |
288 | 288 | ||
289 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter); | 289 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask); |
290 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); | 290 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); |
291 | extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid); | 291 | extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid); |
292 | extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid); | 292 | extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid); |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index f071d12c613b..3c2a1724fbd2 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
@@ -115,6 +115,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | |||
115 | char *page, char *page2, | 115 | char *page, char *page2, |
116 | const struct nfs4_fs_location *location) | 116 | const struct nfs4_fs_location *location) |
117 | { | 117 | { |
118 | const size_t addr_bufsize = sizeof(struct sockaddr_storage); | ||
118 | struct vfsmount *mnt = ERR_PTR(-ENOENT); | 119 | struct vfsmount *mnt = ERR_PTR(-ENOENT); |
119 | char *mnt_path; | 120 | char *mnt_path; |
120 | unsigned int maxbuflen; | 121 | unsigned int maxbuflen; |
@@ -126,9 +127,12 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | |||
126 | mountdata->mnt_path = mnt_path; | 127 | mountdata->mnt_path = mnt_path; |
127 | maxbuflen = mnt_path - 1 - page2; | 128 | maxbuflen = mnt_path - 1 - page2; |
128 | 129 | ||
130 | mountdata->addr = kmalloc(addr_bufsize, GFP_KERNEL); | ||
131 | if (mountdata->addr == NULL) | ||
132 | return ERR_PTR(-ENOMEM); | ||
133 | |||
129 | for (s = 0; s < location->nservers; s++) { | 134 | for (s = 0; s < location->nservers; s++) { |
130 | const struct nfs4_string *buf = &location->servers[s]; | 135 | const struct nfs4_string *buf = &location->servers[s]; |
131 | struct sockaddr_storage addr; | ||
132 | 136 | ||
133 | if (buf->len <= 0 || buf->len >= maxbuflen) | 137 | if (buf->len <= 0 || buf->len >= maxbuflen) |
134 | continue; | 138 | continue; |
@@ -137,11 +141,10 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | |||
137 | continue; | 141 | continue; |
138 | 142 | ||
139 | mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len, | 143 | mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len, |
140 | (struct sockaddr *)&addr, sizeof(addr)); | 144 | mountdata->addr, addr_bufsize); |
141 | if (mountdata->addrlen == 0) | 145 | if (mountdata->addrlen == 0) |
142 | continue; | 146 | continue; |
143 | 147 | ||
144 | mountdata->addr = (struct sockaddr *)&addr; | ||
145 | rpc_set_port(mountdata->addr, NFS_PORT); | 148 | rpc_set_port(mountdata->addr, NFS_PORT); |
146 | 149 | ||
147 | memcpy(page2, buf->data, buf->len); | 150 | memcpy(page2, buf->data, buf->len); |
@@ -156,6 +159,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | |||
156 | if (!IS_ERR(mnt)) | 159 | if (!IS_ERR(mnt)) |
157 | break; | 160 | break; |
158 | } | 161 | } |
162 | kfree(mountdata->addr); | ||
159 | return mnt; | 163 | return mnt; |
160 | } | 164 | } |
161 | 165 | ||
@@ -221,8 +225,8 @@ out: | |||
221 | 225 | ||
222 | /* | 226 | /* |
223 | * nfs_do_refmount - handle crossing a referral on server | 227 | * nfs_do_refmount - handle crossing a referral on server |
228 | * @mnt_parent - mountpoint of referral | ||
224 | * @dentry - dentry of referral | 229 | * @dentry - dentry of referral |
225 | * @nd - nameidata info | ||
226 | * | 230 | * |
227 | */ | 231 | */ |
228 | struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) | 232 | struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 071fcedd517c..70015dd60a98 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -70,6 +70,9 @@ static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinf | |||
70 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); | 70 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); |
71 | static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 71 | static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); |
72 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 72 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); |
73 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | ||
74 | struct nfs_fattr *fattr, struct iattr *sattr, | ||
75 | struct nfs4_state *state); | ||
73 | 76 | ||
74 | /* Prevent leaks of NFSv4 errors into userland */ | 77 | /* Prevent leaks of NFSv4 errors into userland */ |
75 | static int nfs4_map_errors(int err) | 78 | static int nfs4_map_errors(int err) |
@@ -714,17 +717,18 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p) | |||
714 | 717 | ||
715 | static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, | 718 | static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, |
716 | struct nfs4_state_owner *sp, fmode_t fmode, int flags, | 719 | struct nfs4_state_owner *sp, fmode_t fmode, int flags, |
717 | const struct iattr *attrs) | 720 | const struct iattr *attrs, |
721 | gfp_t gfp_mask) | ||
718 | { | 722 | { |
719 | struct dentry *parent = dget_parent(path->dentry); | 723 | struct dentry *parent = dget_parent(path->dentry); |
720 | struct inode *dir = parent->d_inode; | 724 | struct inode *dir = parent->d_inode; |
721 | struct nfs_server *server = NFS_SERVER(dir); | 725 | struct nfs_server *server = NFS_SERVER(dir); |
722 | struct nfs4_opendata *p; | 726 | struct nfs4_opendata *p; |
723 | 727 | ||
724 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 728 | p = kzalloc(sizeof(*p), gfp_mask); |
725 | if (p == NULL) | 729 | if (p == NULL) |
726 | goto err; | 730 | goto err; |
727 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | 731 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask); |
728 | if (p->o_arg.seqid == NULL) | 732 | if (p->o_arg.seqid == NULL) |
729 | goto err_free; | 733 | goto err_free; |
730 | path_get(path); | 734 | path_get(path); |
@@ -1060,7 +1064,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context | |||
1060 | { | 1064 | { |
1061 | struct nfs4_opendata *opendata; | 1065 | struct nfs4_opendata *opendata; |
1062 | 1066 | ||
1063 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, 0, NULL); | 1067 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, 0, NULL, GFP_NOFS); |
1064 | if (opendata == NULL) | 1068 | if (opendata == NULL) |
1065 | return ERR_PTR(-ENOMEM); | 1069 | return ERR_PTR(-ENOMEM); |
1066 | opendata->state = state; | 1070 | opendata->state = state; |
@@ -1648,7 +1652,7 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in | |||
1648 | if (path->dentry->d_inode != NULL) | 1652 | if (path->dentry->d_inode != NULL) |
1649 | nfs4_return_incompatible_delegation(path->dentry->d_inode, fmode); | 1653 | nfs4_return_incompatible_delegation(path->dentry->d_inode, fmode); |
1650 | status = -ENOMEM; | 1654 | status = -ENOMEM; |
1651 | opendata = nfs4_opendata_alloc(path, sp, fmode, flags, sattr); | 1655 | opendata = nfs4_opendata_alloc(path, sp, fmode, flags, sattr, GFP_KERNEL); |
1652 | if (opendata == NULL) | 1656 | if (opendata == NULL) |
1653 | goto err_put_state_owner; | 1657 | goto err_put_state_owner; |
1654 | 1658 | ||
@@ -1659,15 +1663,24 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in | |||
1659 | if (status != 0) | 1663 | if (status != 0) |
1660 | goto err_opendata_put; | 1664 | goto err_opendata_put; |
1661 | 1665 | ||
1662 | if (opendata->o_arg.open_flags & O_EXCL) | ||
1663 | nfs4_exclusive_attrset(opendata, sattr); | ||
1664 | |||
1665 | state = nfs4_opendata_to_nfs4_state(opendata); | 1666 | state = nfs4_opendata_to_nfs4_state(opendata); |
1666 | status = PTR_ERR(state); | 1667 | status = PTR_ERR(state); |
1667 | if (IS_ERR(state)) | 1668 | if (IS_ERR(state)) |
1668 | goto err_opendata_put; | 1669 | goto err_opendata_put; |
1669 | if (server->caps & NFS_CAP_POSIX_LOCK) | 1670 | if (server->caps & NFS_CAP_POSIX_LOCK) |
1670 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); | 1671 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); |
1672 | |||
1673 | if (opendata->o_arg.open_flags & O_EXCL) { | ||
1674 | nfs4_exclusive_attrset(opendata, sattr); | ||
1675 | |||
1676 | nfs_fattr_init(opendata->o_res.f_attr); | ||
1677 | status = nfs4_do_setattr(state->inode, cred, | ||
1678 | opendata->o_res.f_attr, sattr, | ||
1679 | state); | ||
1680 | if (status == 0) | ||
1681 | nfs_setattr_update_inode(state->inode, sattr); | ||
1682 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); | ||
1683 | } | ||
1671 | nfs4_opendata_put(opendata); | 1684 | nfs4_opendata_put(opendata); |
1672 | nfs4_put_state_owner(sp); | 1685 | nfs4_put_state_owner(sp); |
1673 | *res = state; | 1686 | *res = state; |
@@ -1914,7 +1927,7 @@ static const struct rpc_call_ops nfs4_close_ops = { | |||
1914 | * | 1927 | * |
1915 | * NOTE: Caller must be holding the sp->so_owner semaphore! | 1928 | * NOTE: Caller must be holding the sp->so_owner semaphore! |
1916 | */ | 1929 | */ |
1917 | int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | 1930 | int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait) |
1918 | { | 1931 | { |
1919 | struct nfs_server *server = NFS_SERVER(state->inode); | 1932 | struct nfs_server *server = NFS_SERVER(state->inode); |
1920 | struct nfs4_closedata *calldata; | 1933 | struct nfs4_closedata *calldata; |
@@ -1933,7 +1946,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1933 | }; | 1946 | }; |
1934 | int status = -ENOMEM; | 1947 | int status = -ENOMEM; |
1935 | 1948 | ||
1936 | calldata = kzalloc(sizeof(*calldata), GFP_KERNEL); | 1949 | calldata = kzalloc(sizeof(*calldata), gfp_mask); |
1937 | if (calldata == NULL) | 1950 | if (calldata == NULL) |
1938 | goto out; | 1951 | goto out; |
1939 | calldata->inode = state->inode; | 1952 | calldata->inode = state->inode; |
@@ -1941,7 +1954,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1941 | calldata->arg.fh = NFS_FH(state->inode); | 1954 | calldata->arg.fh = NFS_FH(state->inode); |
1942 | calldata->arg.stateid = &state->open_stateid; | 1955 | calldata->arg.stateid = &state->open_stateid; |
1943 | /* Serialization for the sequence id */ | 1956 | /* Serialization for the sequence id */ |
1944 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); | 1957 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid, gfp_mask); |
1945 | if (calldata->arg.seqid == NULL) | 1958 | if (calldata->arg.seqid == NULL) |
1946 | goto out_free_calldata; | 1959 | goto out_free_calldata; |
1947 | calldata->arg.fmode = 0; | 1960 | calldata->arg.fmode = 0; |
@@ -2404,14 +2417,12 @@ static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh | |||
2404 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | 2417 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
2405 | { | 2418 | { |
2406 | struct nfs_server *server = NFS_SERVER(inode); | 2419 | struct nfs_server *server = NFS_SERVER(inode); |
2407 | struct nfs_fattr fattr; | ||
2408 | struct nfs4_accessargs args = { | 2420 | struct nfs4_accessargs args = { |
2409 | .fh = NFS_FH(inode), | 2421 | .fh = NFS_FH(inode), |
2410 | .bitmask = server->attr_bitmask, | 2422 | .bitmask = server->attr_bitmask, |
2411 | }; | 2423 | }; |
2412 | struct nfs4_accessres res = { | 2424 | struct nfs4_accessres res = { |
2413 | .server = server, | 2425 | .server = server, |
2414 | .fattr = &fattr, | ||
2415 | }; | 2426 | }; |
2416 | struct rpc_message msg = { | 2427 | struct rpc_message msg = { |
2417 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS], | 2428 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS], |
@@ -2438,7 +2449,11 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
2438 | if (mode & MAY_EXEC) | 2449 | if (mode & MAY_EXEC) |
2439 | args.access |= NFS4_ACCESS_EXECUTE; | 2450 | args.access |= NFS4_ACCESS_EXECUTE; |
2440 | } | 2451 | } |
2441 | nfs_fattr_init(&fattr); | 2452 | |
2453 | res.fattr = nfs_alloc_fattr(); | ||
2454 | if (res.fattr == NULL) | ||
2455 | return -ENOMEM; | ||
2456 | |||
2442 | status = nfs4_call_sync(server, &msg, &args, &res, 0); | 2457 | status = nfs4_call_sync(server, &msg, &args, &res, 0); |
2443 | if (!status) { | 2458 | if (!status) { |
2444 | entry->mask = 0; | 2459 | entry->mask = 0; |
@@ -2448,8 +2463,9 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
2448 | entry->mask |= MAY_WRITE; | 2463 | entry->mask |= MAY_WRITE; |
2449 | if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE)) | 2464 | if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE)) |
2450 | entry->mask |= MAY_EXEC; | 2465 | entry->mask |= MAY_EXEC; |
2451 | nfs_refresh_inode(inode, &fattr); | 2466 | nfs_refresh_inode(inode, res.fattr); |
2452 | } | 2467 | } |
2468 | nfs_free_fattr(res.fattr); | ||
2453 | return status; | 2469 | return status; |
2454 | } | 2470 | } |
2455 | 2471 | ||
@@ -2562,13 +2578,6 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
2562 | } | 2578 | } |
2563 | d_add(dentry, igrab(state->inode)); | 2579 | d_add(dentry, igrab(state->inode)); |
2564 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 2580 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
2565 | if (flags & O_EXCL) { | ||
2566 | struct nfs_fattr fattr; | ||
2567 | status = nfs4_do_setattr(state->inode, cred, &fattr, sattr, state); | ||
2568 | if (status == 0) | ||
2569 | nfs_setattr_update_inode(state->inode, sattr); | ||
2570 | nfs_post_op_update_inode(state->inode, &fattr); | ||
2571 | } | ||
2572 | if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) | 2581 | if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) |
2573 | status = nfs4_intent_set_file(nd, &path, state, fmode); | 2582 | status = nfs4_intent_set_file(nd, &path, state, fmode); |
2574 | else | 2583 | else |
@@ -2596,14 +2605,19 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
2596 | .rpc_argp = &args, | 2605 | .rpc_argp = &args, |
2597 | .rpc_resp = &res, | 2606 | .rpc_resp = &res, |
2598 | }; | 2607 | }; |
2599 | int status; | 2608 | int status = -ENOMEM; |
2609 | |||
2610 | res.dir_attr = nfs_alloc_fattr(); | ||
2611 | if (res.dir_attr == NULL) | ||
2612 | goto out; | ||
2600 | 2613 | ||
2601 | nfs_fattr_init(&res.dir_attr); | ||
2602 | status = nfs4_call_sync(server, &msg, &args, &res, 1); | 2614 | status = nfs4_call_sync(server, &msg, &args, &res, 1); |
2603 | if (status == 0) { | 2615 | if (status == 0) { |
2604 | update_changeattr(dir, &res.cinfo); | 2616 | update_changeattr(dir, &res.cinfo); |
2605 | nfs_post_op_update_inode(dir, &res.dir_attr); | 2617 | nfs_post_op_update_inode(dir, res.dir_attr); |
2606 | } | 2618 | } |
2619 | nfs_free_fattr(res.dir_attr); | ||
2620 | out: | ||
2607 | return status; | 2621 | return status; |
2608 | } | 2622 | } |
2609 | 2623 | ||
@@ -2638,7 +2652,7 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | |||
2638 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) | 2652 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) |
2639 | return 0; | 2653 | return 0; |
2640 | update_changeattr(dir, &res->cinfo); | 2654 | update_changeattr(dir, &res->cinfo); |
2641 | nfs_post_op_update_inode(dir, &res->dir_attr); | 2655 | nfs_post_op_update_inode(dir, res->dir_attr); |
2642 | return 1; | 2656 | return 1; |
2643 | } | 2657 | } |
2644 | 2658 | ||
@@ -2653,29 +2667,31 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
2653 | .new_name = new_name, | 2667 | .new_name = new_name, |
2654 | .bitmask = server->attr_bitmask, | 2668 | .bitmask = server->attr_bitmask, |
2655 | }; | 2669 | }; |
2656 | struct nfs_fattr old_fattr, new_fattr; | ||
2657 | struct nfs4_rename_res res = { | 2670 | struct nfs4_rename_res res = { |
2658 | .server = server, | 2671 | .server = server, |
2659 | .old_fattr = &old_fattr, | ||
2660 | .new_fattr = &new_fattr, | ||
2661 | }; | 2672 | }; |
2662 | struct rpc_message msg = { | 2673 | struct rpc_message msg = { |
2663 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME], | 2674 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME], |
2664 | .rpc_argp = &arg, | 2675 | .rpc_argp = &arg, |
2665 | .rpc_resp = &res, | 2676 | .rpc_resp = &res, |
2666 | }; | 2677 | }; |
2667 | int status; | 2678 | int status = -ENOMEM; |
2668 | 2679 | ||
2669 | nfs_fattr_init(res.old_fattr); | 2680 | res.old_fattr = nfs_alloc_fattr(); |
2670 | nfs_fattr_init(res.new_fattr); | 2681 | res.new_fattr = nfs_alloc_fattr(); |
2671 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); | 2682 | if (res.old_fattr == NULL || res.new_fattr == NULL) |
2683 | goto out; | ||
2672 | 2684 | ||
2685 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); | ||
2673 | if (!status) { | 2686 | if (!status) { |
2674 | update_changeattr(old_dir, &res.old_cinfo); | 2687 | update_changeattr(old_dir, &res.old_cinfo); |
2675 | nfs_post_op_update_inode(old_dir, res.old_fattr); | 2688 | nfs_post_op_update_inode(old_dir, res.old_fattr); |
2676 | update_changeattr(new_dir, &res.new_cinfo); | 2689 | update_changeattr(new_dir, &res.new_cinfo); |
2677 | nfs_post_op_update_inode(new_dir, res.new_fattr); | 2690 | nfs_post_op_update_inode(new_dir, res.new_fattr); |
2678 | } | 2691 | } |
2692 | out: | ||
2693 | nfs_free_fattr(res.new_fattr); | ||
2694 | nfs_free_fattr(res.old_fattr); | ||
2679 | return status; | 2695 | return status; |
2680 | } | 2696 | } |
2681 | 2697 | ||
@@ -2702,28 +2718,30 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
2702 | .name = name, | 2718 | .name = name, |
2703 | .bitmask = server->attr_bitmask, | 2719 | .bitmask = server->attr_bitmask, |
2704 | }; | 2720 | }; |
2705 | struct nfs_fattr fattr, dir_attr; | ||
2706 | struct nfs4_link_res res = { | 2721 | struct nfs4_link_res res = { |
2707 | .server = server, | 2722 | .server = server, |
2708 | .fattr = &fattr, | ||
2709 | .dir_attr = &dir_attr, | ||
2710 | }; | 2723 | }; |
2711 | struct rpc_message msg = { | 2724 | struct rpc_message msg = { |
2712 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], | 2725 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], |
2713 | .rpc_argp = &arg, | 2726 | .rpc_argp = &arg, |
2714 | .rpc_resp = &res, | 2727 | .rpc_resp = &res, |
2715 | }; | 2728 | }; |
2716 | int status; | 2729 | int status = -ENOMEM; |
2730 | |||
2731 | res.fattr = nfs_alloc_fattr(); | ||
2732 | res.dir_attr = nfs_alloc_fattr(); | ||
2733 | if (res.fattr == NULL || res.dir_attr == NULL) | ||
2734 | goto out; | ||
2717 | 2735 | ||
2718 | nfs_fattr_init(res.fattr); | ||
2719 | nfs_fattr_init(res.dir_attr); | ||
2720 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); | 2736 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); |
2721 | if (!status) { | 2737 | if (!status) { |
2722 | update_changeattr(dir, &res.cinfo); | 2738 | update_changeattr(dir, &res.cinfo); |
2723 | nfs_post_op_update_inode(dir, res.dir_attr); | 2739 | nfs_post_op_update_inode(dir, res.dir_attr); |
2724 | nfs_post_op_update_inode(inode, res.fattr); | 2740 | nfs_post_op_update_inode(inode, res.fattr); |
2725 | } | 2741 | } |
2726 | 2742 | out: | |
2743 | nfs_free_fattr(res.dir_attr); | ||
2744 | nfs_free_fattr(res.fattr); | ||
2727 | return status; | 2745 | return status; |
2728 | } | 2746 | } |
2729 | 2747 | ||
@@ -3146,23 +3164,31 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa | |||
3146 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; | 3164 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; |
3147 | } | 3165 | } |
3148 | 3166 | ||
3167 | struct nfs4_renewdata { | ||
3168 | struct nfs_client *client; | ||
3169 | unsigned long timestamp; | ||
3170 | }; | ||
3171 | |||
3149 | /* | 3172 | /* |
3150 | * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special | 3173 | * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special |
3151 | * standalone procedure for queueing an asynchronous RENEW. | 3174 | * standalone procedure for queueing an asynchronous RENEW. |
3152 | */ | 3175 | */ |
3153 | static void nfs4_renew_release(void *data) | 3176 | static void nfs4_renew_release(void *calldata) |
3154 | { | 3177 | { |
3155 | struct nfs_client *clp = data; | 3178 | struct nfs4_renewdata *data = calldata; |
3179 | struct nfs_client *clp = data->client; | ||
3156 | 3180 | ||
3157 | if (atomic_read(&clp->cl_count) > 1) | 3181 | if (atomic_read(&clp->cl_count) > 1) |
3158 | nfs4_schedule_state_renewal(clp); | 3182 | nfs4_schedule_state_renewal(clp); |
3159 | nfs_put_client(clp); | 3183 | nfs_put_client(clp); |
3184 | kfree(data); | ||
3160 | } | 3185 | } |
3161 | 3186 | ||
3162 | static void nfs4_renew_done(struct rpc_task *task, void *data) | 3187 | static void nfs4_renew_done(struct rpc_task *task, void *calldata) |
3163 | { | 3188 | { |
3164 | struct nfs_client *clp = data; | 3189 | struct nfs4_renewdata *data = calldata; |
3165 | unsigned long timestamp = task->tk_start; | 3190 | struct nfs_client *clp = data->client; |
3191 | unsigned long timestamp = data->timestamp; | ||
3166 | 3192 | ||
3167 | if (task->tk_status < 0) { | 3193 | if (task->tk_status < 0) { |
3168 | /* Unless we're shutting down, schedule state recovery! */ | 3194 | /* Unless we're shutting down, schedule state recovery! */ |
@@ -3188,11 +3214,17 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) | |||
3188 | .rpc_argp = clp, | 3214 | .rpc_argp = clp, |
3189 | .rpc_cred = cred, | 3215 | .rpc_cred = cred, |
3190 | }; | 3216 | }; |
3217 | struct nfs4_renewdata *data; | ||
3191 | 3218 | ||
3192 | if (!atomic_inc_not_zero(&clp->cl_count)) | 3219 | if (!atomic_inc_not_zero(&clp->cl_count)) |
3193 | return -EIO; | 3220 | return -EIO; |
3221 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
3222 | if (data == NULL) | ||
3223 | return -ENOMEM; | ||
3224 | data->client = clp; | ||
3225 | data->timestamp = jiffies; | ||
3194 | return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, | 3226 | return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, |
3195 | &nfs4_renew_ops, clp); | 3227 | &nfs4_renew_ops, data); |
3196 | } | 3228 | } |
3197 | 3229 | ||
3198 | int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) | 3230 | int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) |
@@ -3494,7 +3526,9 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3494 | return _nfs4_async_handle_error(task, server, server->nfs_client, state); | 3526 | return _nfs4_async_handle_error(task, server, server->nfs_client, state); |
3495 | } | 3527 | } |
3496 | 3528 | ||
3497 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred) | 3529 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, |
3530 | unsigned short port, struct rpc_cred *cred, | ||
3531 | struct nfs4_setclientid_res *res) | ||
3498 | { | 3532 | { |
3499 | nfs4_verifier sc_verifier; | 3533 | nfs4_verifier sc_verifier; |
3500 | struct nfs4_setclientid setclientid = { | 3534 | struct nfs4_setclientid setclientid = { |
@@ -3504,7 +3538,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po | |||
3504 | struct rpc_message msg = { | 3538 | struct rpc_message msg = { |
3505 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID], | 3539 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID], |
3506 | .rpc_argp = &setclientid, | 3540 | .rpc_argp = &setclientid, |
3507 | .rpc_resp = clp, | 3541 | .rpc_resp = res, |
3508 | .rpc_cred = cred, | 3542 | .rpc_cred = cred, |
3509 | }; | 3543 | }; |
3510 | __be32 *p; | 3544 | __be32 *p; |
@@ -3547,12 +3581,14 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po | |||
3547 | return status; | 3581 | return status; |
3548 | } | 3582 | } |
3549 | 3583 | ||
3550 | static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred) | 3584 | static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, |
3585 | struct nfs4_setclientid_res *arg, | ||
3586 | struct rpc_cred *cred) | ||
3551 | { | 3587 | { |
3552 | struct nfs_fsinfo fsinfo; | 3588 | struct nfs_fsinfo fsinfo; |
3553 | struct rpc_message msg = { | 3589 | struct rpc_message msg = { |
3554 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM], | 3590 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM], |
3555 | .rpc_argp = clp, | 3591 | .rpc_argp = arg, |
3556 | .rpc_resp = &fsinfo, | 3592 | .rpc_resp = &fsinfo, |
3557 | .rpc_cred = cred, | 3593 | .rpc_cred = cred, |
3558 | }; | 3594 | }; |
@@ -3570,12 +3606,14 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cre | |||
3570 | return status; | 3606 | return status; |
3571 | } | 3607 | } |
3572 | 3608 | ||
3573 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred) | 3609 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, |
3610 | struct nfs4_setclientid_res *arg, | ||
3611 | struct rpc_cred *cred) | ||
3574 | { | 3612 | { |
3575 | long timeout = 0; | 3613 | long timeout = 0; |
3576 | int err; | 3614 | int err; |
3577 | do { | 3615 | do { |
3578 | err = _nfs4_proc_setclientid_confirm(clp, cred); | 3616 | err = _nfs4_proc_setclientid_confirm(clp, arg, cred); |
3579 | switch (err) { | 3617 | switch (err) { |
3580 | case 0: | 3618 | case 0: |
3581 | return err; | 3619 | return err; |
@@ -3667,7 +3705,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
3667 | }; | 3705 | }; |
3668 | int status = 0; | 3706 | int status = 0; |
3669 | 3707 | ||
3670 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 3708 | data = kzalloc(sizeof(*data), GFP_NOFS); |
3671 | if (data == NULL) | 3709 | if (data == NULL) |
3672 | return -ENOMEM; | 3710 | return -ENOMEM; |
3673 | data->args.fhandle = &data->fh; | 3711 | data->args.fhandle = &data->fh; |
@@ -3823,7 +3861,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, | |||
3823 | struct nfs4_unlockdata *p; | 3861 | struct nfs4_unlockdata *p; |
3824 | struct inode *inode = lsp->ls_state->inode; | 3862 | struct inode *inode = lsp->ls_state->inode; |
3825 | 3863 | ||
3826 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 3864 | p = kzalloc(sizeof(*p), GFP_NOFS); |
3827 | if (p == NULL) | 3865 | if (p == NULL) |
3828 | return NULL; | 3866 | return NULL; |
3829 | p->arg.fh = NFS_FH(inode); | 3867 | p->arg.fh = NFS_FH(inode); |
@@ -3961,7 +3999,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
3961 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) | 3999 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) |
3962 | goto out; | 4000 | goto out; |
3963 | lsp = request->fl_u.nfs4_fl.owner; | 4001 | lsp = request->fl_u.nfs4_fl.owner; |
3964 | seqid = nfs_alloc_seqid(&lsp->ls_seqid); | 4002 | seqid = nfs_alloc_seqid(&lsp->ls_seqid, GFP_KERNEL); |
3965 | status = -ENOMEM; | 4003 | status = -ENOMEM; |
3966 | if (seqid == NULL) | 4004 | if (seqid == NULL) |
3967 | goto out; | 4005 | goto out; |
@@ -3989,22 +4027,23 @@ struct nfs4_lockdata { | |||
3989 | }; | 4027 | }; |
3990 | 4028 | ||
3991 | static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | 4029 | static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, |
3992 | struct nfs_open_context *ctx, struct nfs4_lock_state *lsp) | 4030 | struct nfs_open_context *ctx, struct nfs4_lock_state *lsp, |
4031 | gfp_t gfp_mask) | ||
3993 | { | 4032 | { |
3994 | struct nfs4_lockdata *p; | 4033 | struct nfs4_lockdata *p; |
3995 | struct inode *inode = lsp->ls_state->inode; | 4034 | struct inode *inode = lsp->ls_state->inode; |
3996 | struct nfs_server *server = NFS_SERVER(inode); | 4035 | struct nfs_server *server = NFS_SERVER(inode); |
3997 | 4036 | ||
3998 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 4037 | p = kzalloc(sizeof(*p), gfp_mask); |
3999 | if (p == NULL) | 4038 | if (p == NULL) |
4000 | return NULL; | 4039 | return NULL; |
4001 | 4040 | ||
4002 | p->arg.fh = NFS_FH(inode); | 4041 | p->arg.fh = NFS_FH(inode); |
4003 | p->arg.fl = &p->fl; | 4042 | p->arg.fl = &p->fl; |
4004 | p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid); | 4043 | p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid, gfp_mask); |
4005 | if (p->arg.open_seqid == NULL) | 4044 | if (p->arg.open_seqid == NULL) |
4006 | goto out_free; | 4045 | goto out_free; |
4007 | p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); | 4046 | p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid, gfp_mask); |
4008 | if (p->arg.lock_seqid == NULL) | 4047 | if (p->arg.lock_seqid == NULL) |
4009 | goto out_free_seqid; | 4048 | goto out_free_seqid; |
4010 | p->arg.lock_stateid = &lsp->ls_stateid; | 4049 | p->arg.lock_stateid = &lsp->ls_stateid; |
@@ -4158,7 +4197,8 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
4158 | 4197 | ||
4159 | dprintk("%s: begin!\n", __func__); | 4198 | dprintk("%s: begin!\n", __func__); |
4160 | data = nfs4_alloc_lockdata(fl, nfs_file_open_context(fl->fl_file), | 4199 | data = nfs4_alloc_lockdata(fl, nfs_file_open_context(fl->fl_file), |
4161 | fl->fl_u.nfs4_fl.owner); | 4200 | fl->fl_u.nfs4_fl.owner, |
4201 | recovery_type == NFS_LOCK_NEW ? GFP_KERNEL : GFP_NOFS); | ||
4162 | if (data == NULL) | 4202 | if (data == NULL) |
4163 | return -ENOMEM; | 4203 | return -ENOMEM; |
4164 | if (IS_SETLKW(cmd)) | 4204 | if (IS_SETLKW(cmd)) |
@@ -4647,7 +4687,7 @@ static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs, | |||
4647 | if (max_reqs != tbl->max_slots) { | 4687 | if (max_reqs != tbl->max_slots) { |
4648 | ret = -ENOMEM; | 4688 | ret = -ENOMEM; |
4649 | new = kmalloc(max_reqs * sizeof(struct nfs4_slot), | 4689 | new = kmalloc(max_reqs * sizeof(struct nfs4_slot), |
4650 | GFP_KERNEL); | 4690 | GFP_NOFS); |
4651 | if (!new) | 4691 | if (!new) |
4652 | goto out; | 4692 | goto out; |
4653 | ret = 0; | 4693 | ret = 0; |
@@ -4712,7 +4752,7 @@ static int nfs4_init_slot_table(struct nfs4_slot_table *tbl, | |||
4712 | 4752 | ||
4713 | dprintk("--> %s: max_reqs=%u\n", __func__, max_slots); | 4753 | dprintk("--> %s: max_reqs=%u\n", __func__, max_slots); |
4714 | 4754 | ||
4715 | slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_KERNEL); | 4755 | slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_NOFS); |
4716 | if (!slot) | 4756 | if (!slot) |
4717 | goto out; | 4757 | goto out; |
4718 | ret = 0; | 4758 | ret = 0; |
@@ -4761,7 +4801,7 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
4761 | struct nfs4_session *session; | 4801 | struct nfs4_session *session; |
4762 | struct nfs4_slot_table *tbl; | 4802 | struct nfs4_slot_table *tbl; |
4763 | 4803 | ||
4764 | session = kzalloc(sizeof(struct nfs4_session), GFP_KERNEL); | 4804 | session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); |
4765 | if (!session) | 4805 | if (!session) |
4766 | return NULL; | 4806 | return NULL; |
4767 | 4807 | ||
@@ -5105,8 +5145,8 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, | |||
5105 | 5145 | ||
5106 | if (!atomic_inc_not_zero(&clp->cl_count)) | 5146 | if (!atomic_inc_not_zero(&clp->cl_count)) |
5107 | return -EIO; | 5147 | return -EIO; |
5108 | args = kzalloc(sizeof(*args), GFP_KERNEL); | 5148 | args = kzalloc(sizeof(*args), GFP_NOFS); |
5109 | res = kzalloc(sizeof(*res), GFP_KERNEL); | 5149 | res = kzalloc(sizeof(*res), GFP_NOFS); |
5110 | if (!args || !res) { | 5150 | if (!args || !res) { |
5111 | kfree(args); | 5151 | kfree(args); |
5112 | kfree(res); | 5152 | kfree(res); |
@@ -5207,7 +5247,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | |||
5207 | int status = -ENOMEM; | 5247 | int status = -ENOMEM; |
5208 | 5248 | ||
5209 | dprintk("--> %s\n", __func__); | 5249 | dprintk("--> %s\n", __func__); |
5210 | calldata = kzalloc(sizeof(*calldata), GFP_KERNEL); | 5250 | calldata = kzalloc(sizeof(*calldata), GFP_NOFS); |
5211 | if (calldata == NULL) | 5251 | if (calldata == NULL) |
5212 | goto out; | 5252 | goto out; |
5213 | calldata->clp = clp; | 5253 | calldata->clp = clp; |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 6c5ed51f105e..34acf5926fdc 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -62,6 +62,7 @@ static LIST_HEAD(nfs4_clientid_list); | |||
62 | 62 | ||
63 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | 63 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) |
64 | { | 64 | { |
65 | struct nfs4_setclientid_res clid; | ||
65 | unsigned short port; | 66 | unsigned short port; |
66 | int status; | 67 | int status; |
67 | 68 | ||
@@ -69,11 +70,15 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | |||
69 | if (clp->cl_addr.ss_family == AF_INET6) | 70 | if (clp->cl_addr.ss_family == AF_INET6) |
70 | port = nfs_callback_tcpport6; | 71 | port = nfs_callback_tcpport6; |
71 | 72 | ||
72 | status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred); | 73 | status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); |
73 | if (status == 0) | 74 | if (status != 0) |
74 | status = nfs4_proc_setclientid_confirm(clp, cred); | 75 | goto out; |
75 | if (status == 0) | 76 | status = nfs4_proc_setclientid_confirm(clp, &clid, cred); |
76 | nfs4_schedule_state_renewal(clp); | 77 | if (status != 0) |
78 | goto out; | ||
79 | clp->cl_clientid = clid.clientid; | ||
80 | nfs4_schedule_state_renewal(clp); | ||
81 | out: | ||
77 | return status; | 82 | return status; |
78 | } | 83 | } |
79 | 84 | ||
@@ -361,7 +366,7 @@ nfs4_alloc_state_owner(void) | |||
361 | { | 366 | { |
362 | struct nfs4_state_owner *sp; | 367 | struct nfs4_state_owner *sp; |
363 | 368 | ||
364 | sp = kzalloc(sizeof(*sp),GFP_KERNEL); | 369 | sp = kzalloc(sizeof(*sp),GFP_NOFS); |
365 | if (!sp) | 370 | if (!sp) |
366 | return NULL; | 371 | return NULL; |
367 | spin_lock_init(&sp->so_lock); | 372 | spin_lock_init(&sp->so_lock); |
@@ -435,7 +440,7 @@ nfs4_alloc_open_state(void) | |||
435 | { | 440 | { |
436 | struct nfs4_state *state; | 441 | struct nfs4_state *state; |
437 | 442 | ||
438 | state = kzalloc(sizeof(*state), GFP_KERNEL); | 443 | state = kzalloc(sizeof(*state), GFP_NOFS); |
439 | if (!state) | 444 | if (!state) |
440 | return NULL; | 445 | return NULL; |
441 | atomic_set(&state->count, 1); | 446 | atomic_set(&state->count, 1); |
@@ -537,7 +542,8 @@ void nfs4_put_open_state(struct nfs4_state *state) | |||
537 | /* | 542 | /* |
538 | * Close the current file. | 543 | * Close the current file. |
539 | */ | 544 | */ |
540 | static void __nfs4_close(struct path *path, struct nfs4_state *state, fmode_t fmode, int wait) | 545 | static void __nfs4_close(struct path *path, struct nfs4_state *state, |
546 | fmode_t fmode, gfp_t gfp_mask, int wait) | ||
541 | { | 547 | { |
542 | struct nfs4_state_owner *owner = state->owner; | 548 | struct nfs4_state_owner *owner = state->owner; |
543 | int call_close = 0; | 549 | int call_close = 0; |
@@ -578,17 +584,17 @@ static void __nfs4_close(struct path *path, struct nfs4_state *state, fmode_t fm | |||
578 | nfs4_put_open_state(state); | 584 | nfs4_put_open_state(state); |
579 | nfs4_put_state_owner(owner); | 585 | nfs4_put_state_owner(owner); |
580 | } else | 586 | } else |
581 | nfs4_do_close(path, state, wait); | 587 | nfs4_do_close(path, state, gfp_mask, wait); |
582 | } | 588 | } |
583 | 589 | ||
584 | void nfs4_close_state(struct path *path, struct nfs4_state *state, fmode_t fmode) | 590 | void nfs4_close_state(struct path *path, struct nfs4_state *state, fmode_t fmode) |
585 | { | 591 | { |
586 | __nfs4_close(path, state, fmode, 0); | 592 | __nfs4_close(path, state, fmode, GFP_NOFS, 0); |
587 | } | 593 | } |
588 | 594 | ||
589 | void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode) | 595 | void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode) |
590 | { | 596 | { |
591 | __nfs4_close(path, state, fmode, 1); | 597 | __nfs4_close(path, state, fmode, GFP_KERNEL, 1); |
592 | } | 598 | } |
593 | 599 | ||
594 | /* | 600 | /* |
@@ -618,7 +624,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
618 | struct nfs4_lock_state *lsp; | 624 | struct nfs4_lock_state *lsp; |
619 | struct nfs_client *clp = state->owner->so_client; | 625 | struct nfs_client *clp = state->owner->so_client; |
620 | 626 | ||
621 | lsp = kzalloc(sizeof(*lsp), GFP_KERNEL); | 627 | lsp = kzalloc(sizeof(*lsp), GFP_NOFS); |
622 | if (lsp == NULL) | 628 | if (lsp == NULL) |
623 | return NULL; | 629 | return NULL; |
624 | rpc_init_wait_queue(&lsp->ls_sequence.wait, "lock_seqid_waitqueue"); | 630 | rpc_init_wait_queue(&lsp->ls_sequence.wait, "lock_seqid_waitqueue"); |
@@ -754,11 +760,11 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
754 | nfs4_put_lock_state(lsp); | 760 | nfs4_put_lock_state(lsp); |
755 | } | 761 | } |
756 | 762 | ||
757 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) | 763 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask) |
758 | { | 764 | { |
759 | struct nfs_seqid *new; | 765 | struct nfs_seqid *new; |
760 | 766 | ||
761 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 767 | new = kmalloc(sizeof(*new), gfp_mask); |
762 | if (new != NULL) { | 768 | if (new != NULL) { |
763 | new->sequence = counter; | 769 | new->sequence = counter; |
764 | INIT_LIST_HEAD(&new->list); | 770 | INIT_LIST_HEAD(&new->list); |
@@ -1347,7 +1353,7 @@ static int nfs4_recall_slot(struct nfs_client *clp) | |||
1347 | 1353 | ||
1348 | nfs4_begin_drain_session(clp); | 1354 | nfs4_begin_drain_session(clp); |
1349 | new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), | 1355 | new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), |
1350 | GFP_KERNEL); | 1356 | GFP_NOFS); |
1351 | if (!new) | 1357 | if (!new) |
1352 | return -ENOMEM; | 1358 | return -ENOMEM; |
1353 | 1359 | ||
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 38f3b582e7c2..6bdef28efa33 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -1504,14 +1504,14 @@ static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclie | |||
1504 | hdr->replen += decode_setclientid_maxsz; | 1504 | hdr->replen += decode_setclientid_maxsz; |
1505 | } | 1505 | } |
1506 | 1506 | ||
1507 | static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state, struct compound_hdr *hdr) | 1507 | static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr) |
1508 | { | 1508 | { |
1509 | __be32 *p; | 1509 | __be32 *p; |
1510 | 1510 | ||
1511 | p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE); | 1511 | p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE); |
1512 | *p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM); | 1512 | *p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM); |
1513 | p = xdr_encode_hyper(p, client_state->cl_clientid); | 1513 | p = xdr_encode_hyper(p, arg->clientid); |
1514 | xdr_encode_opaque_fixed(p, client_state->cl_confirm.data, NFS4_VERIFIER_SIZE); | 1514 | xdr_encode_opaque_fixed(p, arg->confirm.data, NFS4_VERIFIER_SIZE); |
1515 | hdr->nops++; | 1515 | hdr->nops++; |
1516 | hdr->replen += decode_setclientid_confirm_maxsz; | 1516 | hdr->replen += decode_setclientid_confirm_maxsz; |
1517 | } | 1517 | } |
@@ -2324,7 +2324,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4 | |||
2324 | /* | 2324 | /* |
2325 | * a SETCLIENTID_CONFIRM request | 2325 | * a SETCLIENTID_CONFIRM request |
2326 | */ | 2326 | */ |
2327 | static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp) | 2327 | static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs4_setclientid_res *arg) |
2328 | { | 2328 | { |
2329 | struct xdr_stream xdr; | 2329 | struct xdr_stream xdr; |
2330 | struct compound_hdr hdr = { | 2330 | struct compound_hdr hdr = { |
@@ -2334,7 +2334,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str | |||
2334 | 2334 | ||
2335 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 2335 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
2336 | encode_compound_hdr(&xdr, req, &hdr); | 2336 | encode_compound_hdr(&xdr, req, &hdr); |
2337 | encode_setclientid_confirm(&xdr, clp, &hdr); | 2337 | encode_setclientid_confirm(&xdr, arg, &hdr); |
2338 | encode_putrootfh(&xdr, &hdr); | 2338 | encode_putrootfh(&xdr, &hdr); |
2339 | encode_fsinfo(&xdr, lease_bitmap, &hdr); | 2339 | encode_fsinfo(&xdr, lease_bitmap, &hdr); |
2340 | encode_nops(&hdr); | 2340 | encode_nops(&hdr); |
@@ -4397,7 +4397,7 @@ out_overflow: | |||
4397 | return -EIO; | 4397 | return -EIO; |
4398 | } | 4398 | } |
4399 | 4399 | ||
4400 | static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp) | 4400 | static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res) |
4401 | { | 4401 | { |
4402 | __be32 *p; | 4402 | __be32 *p; |
4403 | uint32_t opnum; | 4403 | uint32_t opnum; |
@@ -4417,8 +4417,8 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp) | |||
4417 | p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE); | 4417 | p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE); |
4418 | if (unlikely(!p)) | 4418 | if (unlikely(!p)) |
4419 | goto out_overflow; | 4419 | goto out_overflow; |
4420 | p = xdr_decode_hyper(p, &clp->cl_clientid); | 4420 | p = xdr_decode_hyper(p, &res->clientid); |
4421 | memcpy(clp->cl_confirm.data, p, NFS4_VERIFIER_SIZE); | 4421 | memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE); |
4422 | } else if (nfserr == NFSERR_CLID_INUSE) { | 4422 | } else if (nfserr == NFSERR_CLID_INUSE) { |
4423 | uint32_t len; | 4423 | uint32_t len; |
4424 | 4424 | ||
@@ -4815,7 +4815,7 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_rem | |||
4815 | goto out; | 4815 | goto out; |
4816 | if ((status = decode_remove(&xdr, &res->cinfo)) != 0) | 4816 | if ((status = decode_remove(&xdr, &res->cinfo)) != 0) |
4817 | goto out; | 4817 | goto out; |
4818 | decode_getfattr(&xdr, &res->dir_attr, res->server, | 4818 | decode_getfattr(&xdr, res->dir_attr, res->server, |
4819 | !RPC_IS_ASYNC(rqstp->rq_task)); | 4819 | !RPC_IS_ASYNC(rqstp->rq_task)); |
4820 | out: | 4820 | out: |
4821 | return status; | 4821 | return status; |
@@ -5498,7 +5498,7 @@ static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, __be32 *p, void *dummy) | |||
5498 | * Decode SETCLIENTID response | 5498 | * Decode SETCLIENTID response |
5499 | */ | 5499 | */ |
5500 | static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p, | 5500 | static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p, |
5501 | struct nfs_client *clp) | 5501 | struct nfs4_setclientid_res *res) |
5502 | { | 5502 | { |
5503 | struct xdr_stream xdr; | 5503 | struct xdr_stream xdr; |
5504 | struct compound_hdr hdr; | 5504 | struct compound_hdr hdr; |
@@ -5507,7 +5507,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p, | |||
5507 | xdr_init_decode(&xdr, &req->rq_rcv_buf, p); | 5507 | xdr_init_decode(&xdr, &req->rq_rcv_buf, p); |
5508 | status = decode_compound_hdr(&xdr, &hdr); | 5508 | status = decode_compound_hdr(&xdr, &hdr); |
5509 | if (!status) | 5509 | if (!status) |
5510 | status = decode_setclientid(&xdr, clp); | 5510 | status = decode_setclientid(&xdr, res); |
5511 | return status; | 5511 | return status; |
5512 | } | 5512 | } |
5513 | 5513 | ||
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 8c55b27c0de4..6bd19d843af7 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c | |||
@@ -488,7 +488,6 @@ static int __init root_nfs_ports(void) | |||
488 | */ | 488 | */ |
489 | static int __init root_nfs_get_handle(void) | 489 | static int __init root_nfs_get_handle(void) |
490 | { | 490 | { |
491 | struct nfs_fh fh; | ||
492 | struct sockaddr_in sin; | 491 | struct sockaddr_in sin; |
493 | unsigned int auth_flav_len = 0; | 492 | unsigned int auth_flav_len = 0; |
494 | struct nfs_mount_request request = { | 493 | struct nfs_mount_request request = { |
@@ -499,21 +498,24 @@ static int __init root_nfs_get_handle(void) | |||
499 | NFS_MNT3_VERSION : NFS_MNT_VERSION, | 498 | NFS_MNT3_VERSION : NFS_MNT_VERSION, |
500 | .protocol = (nfs_data.flags & NFS_MOUNT_TCP) ? | 499 | .protocol = (nfs_data.flags & NFS_MOUNT_TCP) ? |
501 | XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP, | 500 | XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP, |
502 | .fh = &fh, | ||
503 | .auth_flav_len = &auth_flav_len, | 501 | .auth_flav_len = &auth_flav_len, |
504 | }; | 502 | }; |
505 | int status; | 503 | int status = -ENOMEM; |
506 | 504 | ||
505 | request.fh = nfs_alloc_fhandle(); | ||
506 | if (!request.fh) | ||
507 | goto out; | ||
507 | set_sockaddr(&sin, servaddr, htons(mount_port)); | 508 | set_sockaddr(&sin, servaddr, htons(mount_port)); |
508 | status = nfs_mount(&request); | 509 | status = nfs_mount(&request); |
509 | if (status < 0) | 510 | if (status < 0) |
510 | printk(KERN_ERR "Root-NFS: Server returned error %d " | 511 | printk(KERN_ERR "Root-NFS: Server returned error %d " |
511 | "while mounting %s\n", status, nfs_export_path); | 512 | "while mounting %s\n", status, nfs_export_path); |
512 | else { | 513 | else { |
513 | nfs_data.root.size = fh.size; | 514 | nfs_data.root.size = request.fh->size; |
514 | memcpy(nfs_data.root.data, fh.data, fh.size); | 515 | memcpy(&nfs_data.root.data, request.fh->data, request.fh->size); |
515 | } | 516 | } |
516 | 517 | nfs_free_fhandle(request.fh); | |
518 | out: | ||
517 | return status; | 519 | return status; |
518 | } | 520 | } |
519 | 521 | ||
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 29d9d36cd5f4..a3654e57b589 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -60,16 +60,10 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode, | |||
60 | { | 60 | { |
61 | struct nfs_page *req; | 61 | struct nfs_page *req; |
62 | 62 | ||
63 | for (;;) { | 63 | /* try to allocate the request struct */ |
64 | /* try to allocate the request struct */ | 64 | req = nfs_page_alloc(); |
65 | req = nfs_page_alloc(); | 65 | if (req == NULL) |
66 | if (req != NULL) | 66 | return ERR_PTR(-ENOMEM); |
67 | break; | ||
68 | |||
69 | if (fatal_signal_pending(current)) | ||
70 | return ERR_PTR(-ERESTARTSYS); | ||
71 | yield(); | ||
72 | } | ||
73 | 67 | ||
74 | /* Initialize the request struct. Initially, we assume a | 68 | /* Initialize the request struct. Initially, we assume a |
75 | * long write-back delay. This will be adjusted in | 69 | * long write-back delay. This will be adjusted in |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 0288be80444f..611bec22f552 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -224,35 +224,60 @@ static int nfs_proc_readlink(struct inode *inode, struct page *page, | |||
224 | return status; | 224 | return status; |
225 | } | 225 | } |
226 | 226 | ||
227 | struct nfs_createdata { | ||
228 | struct nfs_createargs arg; | ||
229 | struct nfs_diropok res; | ||
230 | struct nfs_fh fhandle; | ||
231 | struct nfs_fattr fattr; | ||
232 | }; | ||
233 | |||
234 | static struct nfs_createdata *nfs_alloc_createdata(struct inode *dir, | ||
235 | struct dentry *dentry, struct iattr *sattr) | ||
236 | { | ||
237 | struct nfs_createdata *data; | ||
238 | |||
239 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
240 | |||
241 | if (data != NULL) { | ||
242 | data->arg.fh = NFS_FH(dir); | ||
243 | data->arg.name = dentry->d_name.name; | ||
244 | data->arg.len = dentry->d_name.len; | ||
245 | data->arg.sattr = sattr; | ||
246 | nfs_fattr_init(&data->fattr); | ||
247 | data->fhandle.size = 0; | ||
248 | data->res.fh = &data->fhandle; | ||
249 | data->res.fattr = &data->fattr; | ||
250 | } | ||
251 | return data; | ||
252 | }; | ||
253 | |||
254 | static void nfs_free_createdata(const struct nfs_createdata *data) | ||
255 | { | ||
256 | kfree(data); | ||
257 | } | ||
258 | |||
227 | static int | 259 | static int |
228 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 260 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
229 | int flags, struct nameidata *nd) | 261 | int flags, struct nameidata *nd) |
230 | { | 262 | { |
231 | struct nfs_fh fhandle; | 263 | struct nfs_createdata *data; |
232 | struct nfs_fattr fattr; | ||
233 | struct nfs_createargs arg = { | ||
234 | .fh = NFS_FH(dir), | ||
235 | .name = dentry->d_name.name, | ||
236 | .len = dentry->d_name.len, | ||
237 | .sattr = sattr | ||
238 | }; | ||
239 | struct nfs_diropok res = { | ||
240 | .fh = &fhandle, | ||
241 | .fattr = &fattr | ||
242 | }; | ||
243 | struct rpc_message msg = { | 264 | struct rpc_message msg = { |
244 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], | 265 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], |
245 | .rpc_argp = &arg, | ||
246 | .rpc_resp = &res, | ||
247 | }; | 266 | }; |
248 | int status; | 267 | int status = -ENOMEM; |
249 | 268 | ||
250 | nfs_fattr_init(&fattr); | ||
251 | dprintk("NFS call create %s\n", dentry->d_name.name); | 269 | dprintk("NFS call create %s\n", dentry->d_name.name); |
270 | data = nfs_alloc_createdata(dir, dentry, sattr); | ||
271 | if (data == NULL) | ||
272 | goto out; | ||
273 | msg.rpc_argp = &data->arg; | ||
274 | msg.rpc_resp = &data->res; | ||
252 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 275 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
253 | nfs_mark_for_revalidate(dir); | 276 | nfs_mark_for_revalidate(dir); |
254 | if (status == 0) | 277 | if (status == 0) |
255 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 278 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); |
279 | nfs_free_createdata(data); | ||
280 | out: | ||
256 | dprintk("NFS reply create: %d\n", status); | 281 | dprintk("NFS reply create: %d\n", status); |
257 | return status; | 282 | return status; |
258 | } | 283 | } |
@@ -264,24 +289,12 @@ static int | |||
264 | nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 289 | nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
265 | dev_t rdev) | 290 | dev_t rdev) |
266 | { | 291 | { |
267 | struct nfs_fh fhandle; | 292 | struct nfs_createdata *data; |
268 | struct nfs_fattr fattr; | ||
269 | struct nfs_createargs arg = { | ||
270 | .fh = NFS_FH(dir), | ||
271 | .name = dentry->d_name.name, | ||
272 | .len = dentry->d_name.len, | ||
273 | .sattr = sattr | ||
274 | }; | ||
275 | struct nfs_diropok res = { | ||
276 | .fh = &fhandle, | ||
277 | .fattr = &fattr | ||
278 | }; | ||
279 | struct rpc_message msg = { | 293 | struct rpc_message msg = { |
280 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], | 294 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], |
281 | .rpc_argp = &arg, | ||
282 | .rpc_resp = &res, | ||
283 | }; | 295 | }; |
284 | int status, mode; | 296 | umode_t mode; |
297 | int status = -ENOMEM; | ||
285 | 298 | ||
286 | dprintk("NFS call mknod %s\n", dentry->d_name.name); | 299 | dprintk("NFS call mknod %s\n", dentry->d_name.name); |
287 | 300 | ||
@@ -294,17 +307,24 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
294 | sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ | 307 | sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ |
295 | } | 308 | } |
296 | 309 | ||
297 | nfs_fattr_init(&fattr); | 310 | data = nfs_alloc_createdata(dir, dentry, sattr); |
311 | if (data == NULL) | ||
312 | goto out; | ||
313 | msg.rpc_argp = &data->arg; | ||
314 | msg.rpc_resp = &data->res; | ||
315 | |||
298 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 316 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
299 | nfs_mark_for_revalidate(dir); | 317 | nfs_mark_for_revalidate(dir); |
300 | 318 | ||
301 | if (status == -EINVAL && S_ISFIFO(mode)) { | 319 | if (status == -EINVAL && S_ISFIFO(mode)) { |
302 | sattr->ia_mode = mode; | 320 | sattr->ia_mode = mode; |
303 | nfs_fattr_init(&fattr); | 321 | nfs_fattr_init(data->res.fattr); |
304 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 322 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
305 | } | 323 | } |
306 | if (status == 0) | 324 | if (status == 0) |
307 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 325 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); |
326 | nfs_free_createdata(data); | ||
327 | out: | ||
308 | dprintk("NFS reply mknod: %d\n", status); | 328 | dprintk("NFS reply mknod: %d\n", status); |
309 | return status; | 329 | return status; |
310 | } | 330 | } |
@@ -398,8 +418,8 @@ static int | |||
398 | nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | 418 | nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, |
399 | unsigned int len, struct iattr *sattr) | 419 | unsigned int len, struct iattr *sattr) |
400 | { | 420 | { |
401 | struct nfs_fh fhandle; | 421 | struct nfs_fh *fh; |
402 | struct nfs_fattr fattr; | 422 | struct nfs_fattr *fattr; |
403 | struct nfs_symlinkargs arg = { | 423 | struct nfs_symlinkargs arg = { |
404 | .fromfh = NFS_FH(dir), | 424 | .fromfh = NFS_FH(dir), |
405 | .fromname = dentry->d_name.name, | 425 | .fromname = dentry->d_name.name, |
@@ -412,12 +432,18 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |||
412 | .rpc_proc = &nfs_procedures[NFSPROC_SYMLINK], | 432 | .rpc_proc = &nfs_procedures[NFSPROC_SYMLINK], |
413 | .rpc_argp = &arg, | 433 | .rpc_argp = &arg, |
414 | }; | 434 | }; |
415 | int status; | 435 | int status = -ENAMETOOLONG; |
436 | |||
437 | dprintk("NFS call symlink %s\n", dentry->d_name.name); | ||
416 | 438 | ||
417 | if (len > NFS2_MAXPATHLEN) | 439 | if (len > NFS2_MAXPATHLEN) |
418 | return -ENAMETOOLONG; | 440 | goto out; |
419 | 441 | ||
420 | dprintk("NFS call symlink %s\n", dentry->d_name.name); | 442 | fh = nfs_alloc_fhandle(); |
443 | fattr = nfs_alloc_fattr(); | ||
444 | status = -ENOMEM; | ||
445 | if (fh == NULL || fattr == NULL) | ||
446 | goto out; | ||
421 | 447 | ||
422 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 448 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
423 | nfs_mark_for_revalidate(dir); | 449 | nfs_mark_for_revalidate(dir); |
@@ -427,12 +453,12 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |||
427 | * filehandle size to zero indicates to nfs_instantiate that it | 453 | * filehandle size to zero indicates to nfs_instantiate that it |
428 | * should fill in the data with a LOOKUP call on the wire. | 454 | * should fill in the data with a LOOKUP call on the wire. |
429 | */ | 455 | */ |
430 | if (status == 0) { | 456 | if (status == 0) |
431 | nfs_fattr_init(&fattr); | 457 | status = nfs_instantiate(dentry, fh, fattr); |
432 | fhandle.size = 0; | ||
433 | status = nfs_instantiate(dentry, &fhandle, &fattr); | ||
434 | } | ||
435 | 458 | ||
459 | nfs_free_fattr(fattr); | ||
460 | nfs_free_fhandle(fh); | ||
461 | out: | ||
436 | dprintk("NFS reply symlink: %d\n", status); | 462 | dprintk("NFS reply symlink: %d\n", status); |
437 | return status; | 463 | return status; |
438 | } | 464 | } |
@@ -440,31 +466,25 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |||
440 | static int | 466 | static int |
441 | nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | 467 | nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) |
442 | { | 468 | { |
443 | struct nfs_fh fhandle; | 469 | struct nfs_createdata *data; |
444 | struct nfs_fattr fattr; | ||
445 | struct nfs_createargs arg = { | ||
446 | .fh = NFS_FH(dir), | ||
447 | .name = dentry->d_name.name, | ||
448 | .len = dentry->d_name.len, | ||
449 | .sattr = sattr | ||
450 | }; | ||
451 | struct nfs_diropok res = { | ||
452 | .fh = &fhandle, | ||
453 | .fattr = &fattr | ||
454 | }; | ||
455 | struct rpc_message msg = { | 470 | struct rpc_message msg = { |
456 | .rpc_proc = &nfs_procedures[NFSPROC_MKDIR], | 471 | .rpc_proc = &nfs_procedures[NFSPROC_MKDIR], |
457 | .rpc_argp = &arg, | ||
458 | .rpc_resp = &res, | ||
459 | }; | 472 | }; |
460 | int status; | 473 | int status = -ENOMEM; |
461 | 474 | ||
462 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); | 475 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); |
463 | nfs_fattr_init(&fattr); | 476 | data = nfs_alloc_createdata(dir, dentry, sattr); |
477 | if (data == NULL) | ||
478 | goto out; | ||
479 | msg.rpc_argp = &data->arg; | ||
480 | msg.rpc_resp = &data->res; | ||
481 | |||
464 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 482 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
465 | nfs_mark_for_revalidate(dir); | 483 | nfs_mark_for_revalidate(dir); |
466 | if (status == 0) | 484 | if (status == 0) |
467 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 485 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); |
486 | nfs_free_createdata(data); | ||
487 | out: | ||
468 | dprintk("NFS reply mkdir: %d\n", status); | 488 | dprintk("NFS reply mkdir: %d\n", status); |
469 | return status; | 489 | return status; |
470 | } | 490 | } |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index db9b360ae19d..6e2b06e6ca79 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -40,7 +40,7 @@ static mempool_t *nfs_rdata_mempool; | |||
40 | 40 | ||
41 | struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) | 41 | struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) |
42 | { | 42 | { |
43 | struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, GFP_NOFS); | 43 | struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, GFP_KERNEL); |
44 | 44 | ||
45 | if (p) { | 45 | if (p) { |
46 | memset(p, 0, sizeof(*p)); | 46 | memset(p, 0, sizeof(*p)); |
@@ -50,7 +50,7 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) | |||
50 | if (pagecount <= ARRAY_SIZE(p->page_array)) | 50 | if (pagecount <= ARRAY_SIZE(p->page_array)) |
51 | p->pagevec = p->page_array; | 51 | p->pagevec = p->page_array; |
52 | else { | 52 | else { |
53 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS); | 53 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); |
54 | if (!p->pagevec) { | 54 | if (!p->pagevec) { |
55 | mempool_free(p, nfs_rdata_mempool); | 55 | mempool_free(p, nfs_rdata_mempool); |
56 | p = NULL; | 56 | p = NULL; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index b4148fc00f9f..2f8b1157daa2 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -141,7 +141,6 @@ static const match_table_t nfs_mount_option_tokens = { | |||
141 | { Opt_resvport, "resvport" }, | 141 | { Opt_resvport, "resvport" }, |
142 | { Opt_noresvport, "noresvport" }, | 142 | { Opt_noresvport, "noresvport" }, |
143 | { Opt_fscache, "fsc" }, | 143 | { Opt_fscache, "fsc" }, |
144 | { Opt_fscache_uniq, "fsc=%s" }, | ||
145 | { Opt_nofscache, "nofsc" }, | 144 | { Opt_nofscache, "nofsc" }, |
146 | 145 | ||
147 | { Opt_port, "port=%s" }, | 146 | { Opt_port, "port=%s" }, |
@@ -171,6 +170,7 @@ static const match_table_t nfs_mount_option_tokens = { | |||
171 | { Opt_mountaddr, "mountaddr=%s" }, | 170 | { Opt_mountaddr, "mountaddr=%s" }, |
172 | 171 | ||
173 | { Opt_lookupcache, "lookupcache=%s" }, | 172 | { Opt_lookupcache, "lookupcache=%s" }, |
173 | { Opt_fscache_uniq, "fsc=%s" }, | ||
174 | 174 | ||
175 | { Opt_err, NULL } | 175 | { Opt_err, NULL } |
176 | }; | 176 | }; |
@@ -423,15 +423,19 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
423 | unsigned char blockbits; | 423 | unsigned char blockbits; |
424 | unsigned long blockres; | 424 | unsigned long blockres; |
425 | struct nfs_fh *fh = NFS_FH(dentry->d_inode); | 425 | struct nfs_fh *fh = NFS_FH(dentry->d_inode); |
426 | struct nfs_fattr fattr; | 426 | struct nfs_fsstat res; |
427 | struct nfs_fsstat res = { | 427 | int error = -ENOMEM; |
428 | .fattr = &fattr, | 428 | |
429 | }; | 429 | res.fattr = nfs_alloc_fattr(); |
430 | int error; | 430 | if (res.fattr == NULL) |
431 | goto out_err; | ||
431 | 432 | ||
432 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); | 433 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); |
434 | |||
435 | nfs_free_fattr(res.fattr); | ||
433 | if (error < 0) | 436 | if (error < 0) |
434 | goto out_err; | 437 | goto out_err; |
438 | |||
435 | buf->f_type = NFS_SUPER_MAGIC; | 439 | buf->f_type = NFS_SUPER_MAGIC; |
436 | 440 | ||
437 | /* | 441 | /* |
@@ -1046,14 +1050,6 @@ static int nfs_parse_mount_options(char *raw, | |||
1046 | kfree(mnt->fscache_uniq); | 1050 | kfree(mnt->fscache_uniq); |
1047 | mnt->fscache_uniq = NULL; | 1051 | mnt->fscache_uniq = NULL; |
1048 | break; | 1052 | break; |
1049 | case Opt_fscache_uniq: | ||
1050 | string = match_strdup(args); | ||
1051 | if (!string) | ||
1052 | goto out_nomem; | ||
1053 | kfree(mnt->fscache_uniq); | ||
1054 | mnt->fscache_uniq = string; | ||
1055 | mnt->options |= NFS_OPTION_FSCACHE; | ||
1056 | break; | ||
1057 | 1053 | ||
1058 | /* | 1054 | /* |
1059 | * options that take numeric values | 1055 | * options that take numeric values |
@@ -1384,6 +1380,14 @@ static int nfs_parse_mount_options(char *raw, | |||
1384 | return 0; | 1380 | return 0; |
1385 | }; | 1381 | }; |
1386 | break; | 1382 | break; |
1383 | case Opt_fscache_uniq: | ||
1384 | string = match_strdup(args); | ||
1385 | if (string == NULL) | ||
1386 | goto out_nomem; | ||
1387 | kfree(mnt->fscache_uniq); | ||
1388 | mnt->fscache_uniq = string; | ||
1389 | mnt->options |= NFS_OPTION_FSCACHE; | ||
1390 | break; | ||
1387 | 1391 | ||
1388 | /* | 1392 | /* |
1389 | * Special options | 1393 | * Special options |
@@ -2172,7 +2176,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2172 | int error = -ENOMEM; | 2176 | int error = -ENOMEM; |
2173 | 2177 | ||
2174 | data = nfs_alloc_parsed_mount_data(3); | 2178 | data = nfs_alloc_parsed_mount_data(3); |
2175 | mntfh = kzalloc(sizeof(*mntfh), GFP_KERNEL); | 2179 | mntfh = nfs_alloc_fhandle(); |
2176 | if (data == NULL || mntfh == NULL) | 2180 | if (data == NULL || mntfh == NULL) |
2177 | goto out_free_fh; | 2181 | goto out_free_fh; |
2178 | 2182 | ||
@@ -2247,7 +2251,7 @@ out: | |||
2247 | kfree(data->fscache_uniq); | 2251 | kfree(data->fscache_uniq); |
2248 | security_free_mnt_opts(&data->lsm_opts); | 2252 | security_free_mnt_opts(&data->lsm_opts); |
2249 | out_free_fh: | 2253 | out_free_fh: |
2250 | kfree(mntfh); | 2254 | nfs_free_fhandle(mntfh); |
2251 | kfree(data); | 2255 | kfree(data); |
2252 | return error; | 2256 | return error; |
2253 | 2257 | ||
@@ -2556,7 +2560,7 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type, | |||
2556 | }; | 2560 | }; |
2557 | int error = -ENOMEM; | 2561 | int error = -ENOMEM; |
2558 | 2562 | ||
2559 | mntfh = kzalloc(sizeof(*mntfh), GFP_KERNEL); | 2563 | mntfh = nfs_alloc_fhandle(); |
2560 | if (data == NULL || mntfh == NULL) | 2564 | if (data == NULL || mntfh == NULL) |
2561 | goto out_free_fh; | 2565 | goto out_free_fh; |
2562 | 2566 | ||
@@ -2614,7 +2618,7 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type, | |||
2614 | out: | 2618 | out: |
2615 | security_free_mnt_opts(&data->lsm_opts); | 2619 | security_free_mnt_opts(&data->lsm_opts); |
2616 | out_free_fh: | 2620 | out_free_fh: |
2617 | kfree(mntfh); | 2621 | nfs_free_fhandle(mntfh); |
2618 | return error; | 2622 | return error; |
2619 | 2623 | ||
2620 | out_free: | 2624 | out_free: |
@@ -2669,41 +2673,120 @@ out_freepage: | |||
2669 | free_page((unsigned long)page); | 2673 | free_page((unsigned long)page); |
2670 | } | 2674 | } |
2671 | 2675 | ||
2676 | struct nfs_referral_count { | ||
2677 | struct list_head list; | ||
2678 | const struct task_struct *task; | ||
2679 | unsigned int referral_count; | ||
2680 | }; | ||
2681 | |||
2682 | static LIST_HEAD(nfs_referral_count_list); | ||
2683 | static DEFINE_SPINLOCK(nfs_referral_count_list_lock); | ||
2684 | |||
2685 | static struct nfs_referral_count *nfs_find_referral_count(void) | ||
2686 | { | ||
2687 | struct nfs_referral_count *p; | ||
2688 | |||
2689 | list_for_each_entry(p, &nfs_referral_count_list, list) { | ||
2690 | if (p->task == current) | ||
2691 | return p; | ||
2692 | } | ||
2693 | return NULL; | ||
2694 | } | ||
2695 | |||
2696 | #define NFS_MAX_NESTED_REFERRALS 2 | ||
2697 | |||
2698 | static int nfs_referral_loop_protect(void) | ||
2699 | { | ||
2700 | struct nfs_referral_count *p, *new; | ||
2701 | int ret = -ENOMEM; | ||
2702 | |||
2703 | new = kmalloc(sizeof(*new), GFP_KERNEL); | ||
2704 | if (!new) | ||
2705 | goto out; | ||
2706 | new->task = current; | ||
2707 | new->referral_count = 1; | ||
2708 | |||
2709 | ret = 0; | ||
2710 | spin_lock(&nfs_referral_count_list_lock); | ||
2711 | p = nfs_find_referral_count(); | ||
2712 | if (p != NULL) { | ||
2713 | if (p->referral_count >= NFS_MAX_NESTED_REFERRALS) | ||
2714 | ret = -ELOOP; | ||
2715 | else | ||
2716 | p->referral_count++; | ||
2717 | } else { | ||
2718 | list_add(&new->list, &nfs_referral_count_list); | ||
2719 | new = NULL; | ||
2720 | } | ||
2721 | spin_unlock(&nfs_referral_count_list_lock); | ||
2722 | kfree(new); | ||
2723 | out: | ||
2724 | return ret; | ||
2725 | } | ||
2726 | |||
2727 | static void nfs_referral_loop_unprotect(void) | ||
2728 | { | ||
2729 | struct nfs_referral_count *p; | ||
2730 | |||
2731 | spin_lock(&nfs_referral_count_list_lock); | ||
2732 | p = nfs_find_referral_count(); | ||
2733 | p->referral_count--; | ||
2734 | if (p->referral_count == 0) | ||
2735 | list_del(&p->list); | ||
2736 | else | ||
2737 | p = NULL; | ||
2738 | spin_unlock(&nfs_referral_count_list_lock); | ||
2739 | kfree(p); | ||
2740 | } | ||
2741 | |||
2672 | static int nfs_follow_remote_path(struct vfsmount *root_mnt, | 2742 | static int nfs_follow_remote_path(struct vfsmount *root_mnt, |
2673 | const char *export_path, struct vfsmount *mnt_target) | 2743 | const char *export_path, struct vfsmount *mnt_target) |
2674 | { | 2744 | { |
2745 | struct nameidata *nd = NULL; | ||
2675 | struct mnt_namespace *ns_private; | 2746 | struct mnt_namespace *ns_private; |
2676 | struct nameidata nd; | ||
2677 | struct super_block *s; | 2747 | struct super_block *s; |
2678 | int ret; | 2748 | int ret; |
2679 | 2749 | ||
2750 | nd = kmalloc(sizeof(*nd), GFP_KERNEL); | ||
2751 | if (nd == NULL) | ||
2752 | return -ENOMEM; | ||
2753 | |||
2680 | ns_private = create_mnt_ns(root_mnt); | 2754 | ns_private = create_mnt_ns(root_mnt); |
2681 | ret = PTR_ERR(ns_private); | 2755 | ret = PTR_ERR(ns_private); |
2682 | if (IS_ERR(ns_private)) | 2756 | if (IS_ERR(ns_private)) |
2683 | goto out_mntput; | 2757 | goto out_mntput; |
2684 | 2758 | ||
2759 | ret = nfs_referral_loop_protect(); | ||
2760 | if (ret != 0) | ||
2761 | goto out_put_mnt_ns; | ||
2762 | |||
2685 | ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt, | 2763 | ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt, |
2686 | export_path, LOOKUP_FOLLOW, &nd); | 2764 | export_path, LOOKUP_FOLLOW, nd); |
2687 | 2765 | ||
2766 | nfs_referral_loop_unprotect(); | ||
2688 | put_mnt_ns(ns_private); | 2767 | put_mnt_ns(ns_private); |
2689 | 2768 | ||
2690 | if (ret != 0) | 2769 | if (ret != 0) |
2691 | goto out_err; | 2770 | goto out_err; |
2692 | 2771 | ||
2693 | s = nd.path.mnt->mnt_sb; | 2772 | s = nd->path.mnt->mnt_sb; |
2694 | atomic_inc(&s->s_active); | 2773 | atomic_inc(&s->s_active); |
2695 | mnt_target->mnt_sb = s; | 2774 | mnt_target->mnt_sb = s; |
2696 | mnt_target->mnt_root = dget(nd.path.dentry); | 2775 | mnt_target->mnt_root = dget(nd->path.dentry); |
2697 | 2776 | ||
2698 | /* Correct the device pathname */ | 2777 | /* Correct the device pathname */ |
2699 | nfs_fix_devname(&nd.path, mnt_target); | 2778 | nfs_fix_devname(&nd->path, mnt_target); |
2700 | 2779 | ||
2701 | path_put(&nd.path); | 2780 | path_put(&nd->path); |
2781 | kfree(nd); | ||
2702 | down_write(&s->s_umount); | 2782 | down_write(&s->s_umount); |
2703 | return 0; | 2783 | return 0; |
2784 | out_put_mnt_ns: | ||
2785 | put_mnt_ns(ns_private); | ||
2704 | out_mntput: | 2786 | out_mntput: |
2705 | mntput(root_mnt); | 2787 | mntput(root_mnt); |
2706 | out_err: | 2788 | out_err: |
2789 | kfree(nd); | ||
2707 | return ret; | 2790 | return ret; |
2708 | } | 2791 | } |
2709 | 2792 | ||
@@ -2874,17 +2957,21 @@ static int nfs4_remote_referral_get_sb(struct file_system_type *fs_type, | |||
2874 | struct super_block *s; | 2957 | struct super_block *s; |
2875 | struct nfs_server *server; | 2958 | struct nfs_server *server; |
2876 | struct dentry *mntroot; | 2959 | struct dentry *mntroot; |
2877 | struct nfs_fh mntfh; | 2960 | struct nfs_fh *mntfh; |
2878 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; | 2961 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; |
2879 | struct nfs_sb_mountdata sb_mntdata = { | 2962 | struct nfs_sb_mountdata sb_mntdata = { |
2880 | .mntflags = flags, | 2963 | .mntflags = flags, |
2881 | }; | 2964 | }; |
2882 | int error; | 2965 | int error = -ENOMEM; |
2883 | 2966 | ||
2884 | dprintk("--> nfs4_referral_get_sb()\n"); | 2967 | dprintk("--> nfs4_referral_get_sb()\n"); |
2885 | 2968 | ||
2969 | mntfh = nfs_alloc_fhandle(); | ||
2970 | if (mntfh == NULL) | ||
2971 | goto out_err_nofh; | ||
2972 | |||
2886 | /* create a new volume representation */ | 2973 | /* create a new volume representation */ |
2887 | server = nfs4_create_referral_server(data, &mntfh); | 2974 | server = nfs4_create_referral_server(data, mntfh); |
2888 | if (IS_ERR(server)) { | 2975 | if (IS_ERR(server)) { |
2889 | error = PTR_ERR(server); | 2976 | error = PTR_ERR(server); |
2890 | goto out_err_noserver; | 2977 | goto out_err_noserver; |
@@ -2916,7 +3003,7 @@ static int nfs4_remote_referral_get_sb(struct file_system_type *fs_type, | |||
2916 | nfs_fscache_get_super_cookie(s, NULL, data); | 3003 | nfs_fscache_get_super_cookie(s, NULL, data); |
2917 | } | 3004 | } |
2918 | 3005 | ||
2919 | mntroot = nfs4_get_root(s, &mntfh); | 3006 | mntroot = nfs4_get_root(s, mntfh); |
2920 | if (IS_ERR(mntroot)) { | 3007 | if (IS_ERR(mntroot)) { |
2921 | error = PTR_ERR(mntroot); | 3008 | error = PTR_ERR(mntroot); |
2922 | goto error_splat_super; | 3009 | goto error_splat_super; |
@@ -2933,12 +3020,15 @@ static int nfs4_remote_referral_get_sb(struct file_system_type *fs_type, | |||
2933 | 3020 | ||
2934 | security_sb_clone_mnt_opts(data->sb, s); | 3021 | security_sb_clone_mnt_opts(data->sb, s); |
2935 | 3022 | ||
3023 | nfs_free_fhandle(mntfh); | ||
2936 | dprintk("<-- nfs4_referral_get_sb() = 0\n"); | 3024 | dprintk("<-- nfs4_referral_get_sb() = 0\n"); |
2937 | return 0; | 3025 | return 0; |
2938 | 3026 | ||
2939 | out_err_nosb: | 3027 | out_err_nosb: |
2940 | nfs_free_server(server); | 3028 | nfs_free_server(server); |
2941 | out_err_noserver: | 3029 | out_err_noserver: |
3030 | nfs_free_fhandle(mntfh); | ||
3031 | out_err_nofh: | ||
2942 | dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error); | 3032 | dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error); |
2943 | return error; | 3033 | return error; |
2944 | 3034 | ||
@@ -2947,6 +3037,7 @@ error_splat_super: | |||
2947 | bdi_unregister(&server->backing_dev_info); | 3037 | bdi_unregister(&server->backing_dev_info); |
2948 | error_splat_bdi: | 3038 | error_splat_bdi: |
2949 | deactivate_locked_super(s); | 3039 | deactivate_locked_super(s); |
3040 | nfs_free_fhandle(mntfh); | ||
2950 | dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); | 3041 | dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); |
2951 | return error; | 3042 | return error; |
2952 | } | 3043 | } |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 6da3d3ff6edd..a2242af6a17d 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -23,6 +23,7 @@ struct nfs_unlinkdata { | |||
23 | struct nfs_removeres res; | 23 | struct nfs_removeres res; |
24 | struct inode *dir; | 24 | struct inode *dir; |
25 | struct rpc_cred *cred; | 25 | struct rpc_cred *cred; |
26 | struct nfs_fattr dir_attr; | ||
26 | }; | 27 | }; |
27 | 28 | ||
28 | /** | 29 | /** |
@@ -169,7 +170,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n | |||
169 | } | 170 | } |
170 | nfs_sb_active(dir->i_sb); | 171 | nfs_sb_active(dir->i_sb); |
171 | data->args.fh = NFS_FH(dir); | 172 | data->args.fh = NFS_FH(dir); |
172 | nfs_fattr_init(&data->res.dir_attr); | 173 | nfs_fattr_init(data->res.dir_attr); |
173 | 174 | ||
174 | NFS_PROTO(dir)->unlink_setup(&msg, dir); | 175 | NFS_PROTO(dir)->unlink_setup(&msg, dir); |
175 | 176 | ||
@@ -259,6 +260,7 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry) | |||
259 | goto out_free; | 260 | goto out_free; |
260 | } | 261 | } |
261 | data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | 262 | data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; |
263 | data->res.dir_attr = &data->dir_attr; | ||
262 | 264 | ||
263 | status = -EBUSY; | 265 | status = -EBUSY; |
264 | spin_lock(&dentry->d_lock); | 266 | spin_lock(&dentry->d_lock); |