diff options
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r-- | fs/nfs/client.c | 158 |
1 files changed, 85 insertions, 73 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index acc9c4943b84..4e7df2adb212 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -150,6 +150,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
150 | clp->cl_boot_time = CURRENT_TIME; | 150 | clp->cl_boot_time = CURRENT_TIME; |
151 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | 151 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; |
152 | clp->cl_minorversion = cl_init->minorversion; | 152 | clp->cl_minorversion = cl_init->minorversion; |
153 | clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; | ||
153 | #endif | 154 | #endif |
154 | cred = rpc_lookup_machine_cred(); | 155 | cred = rpc_lookup_machine_cred(); |
155 | if (!IS_ERR(cred)) | 156 | if (!IS_ERR(cred)) |
@@ -178,7 +179,7 @@ static void nfs4_clear_client_minor_version(struct nfs_client *clp) | |||
178 | clp->cl_session = NULL; | 179 | clp->cl_session = NULL; |
179 | } | 180 | } |
180 | 181 | ||
181 | clp->cl_call_sync = _nfs4_call_sync; | 182 | clp->cl_mvops = nfs_v4_minor_ops[0]; |
182 | #endif /* CONFIG_NFS_V4_1 */ | 183 | #endif /* CONFIG_NFS_V4_1 */ |
183 | } | 184 | } |
184 | 185 | ||
@@ -188,7 +189,7 @@ static void nfs4_clear_client_minor_version(struct nfs_client *clp) | |||
188 | static void nfs4_destroy_callback(struct nfs_client *clp) | 189 | static void nfs4_destroy_callback(struct nfs_client *clp) |
189 | { | 190 | { |
190 | if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) | 191 | if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) |
191 | nfs_callback_down(clp->cl_minorversion); | 192 | nfs_callback_down(clp->cl_mvops->minor_version); |
192 | } | 193 | } |
193 | 194 | ||
194 | static void nfs4_shutdown_client(struct nfs_client *clp) | 195 | static void nfs4_shutdown_client(struct nfs_client *clp) |
@@ -934,7 +935,6 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str | |||
934 | } | 935 | } |
935 | 936 | ||
936 | fsinfo.fattr = fattr; | 937 | fsinfo.fattr = fattr; |
937 | nfs_fattr_init(fattr); | ||
938 | error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); | 938 | error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); |
939 | if (error < 0) | 939 | if (error < 0) |
940 | goto out_error; | 940 | goto out_error; |
@@ -1047,13 +1047,18 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, | |||
1047 | struct nfs_fh *mntfh) | 1047 | struct nfs_fh *mntfh) |
1048 | { | 1048 | { |
1049 | struct nfs_server *server; | 1049 | struct nfs_server *server; |
1050 | struct nfs_fattr fattr; | 1050 | struct nfs_fattr *fattr; |
1051 | int error; | 1051 | int error; |
1052 | 1052 | ||
1053 | server = nfs_alloc_server(); | 1053 | server = nfs_alloc_server(); |
1054 | if (!server) | 1054 | if (!server) |
1055 | return ERR_PTR(-ENOMEM); | 1055 | return ERR_PTR(-ENOMEM); |
1056 | 1056 | ||
1057 | error = -ENOMEM; | ||
1058 | fattr = nfs_alloc_fattr(); | ||
1059 | if (fattr == NULL) | ||
1060 | goto error; | ||
1061 | |||
1057 | /* Get a client representation */ | 1062 | /* Get a client representation */ |
1058 | error = nfs_init_server(server, data); | 1063 | error = nfs_init_server(server, data); |
1059 | if (error < 0) | 1064 | if (error < 0) |
@@ -1064,7 +1069,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); | 1069 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
1065 | 1070 | ||
1066 | /* Probe the root fh to retrieve its FSID */ | 1071 | /* Probe the root fh to retrieve its FSID */ |
1067 | error = nfs_probe_fsinfo(server, mntfh, &fattr); | 1072 | error = nfs_probe_fsinfo(server, mntfh, fattr); |
1068 | if (error < 0) | 1073 | if (error < 0) |
1069 | goto error; | 1074 | goto error; |
1070 | if (server->nfs_client->rpc_ops->version == 3) { | 1075 | if (server->nfs_client->rpc_ops->version == 3) { |
@@ -1077,14 +1082,14 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, | |||
1077 | server->namelen = NFS2_MAXNAMLEN; | 1082 | server->namelen = NFS2_MAXNAMLEN; |
1078 | } | 1083 | } |
1079 | 1084 | ||
1080 | if (!(fattr.valid & NFS_ATTR_FATTR)) { | 1085 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
1081 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); | 1086 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr); |
1082 | if (error < 0) { | 1087 | if (error < 0) { |
1083 | dprintk("nfs_create_server: getattr error = %d\n", -error); | 1088 | dprintk("nfs_create_server: getattr error = %d\n", -error); |
1084 | goto error; | 1089 | goto error; |
1085 | } | 1090 | } |
1086 | } | 1091 | } |
1087 | memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); | 1092 | memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); |
1088 | 1093 | ||
1089 | dprintk("Server FSID: %llx:%llx\n", | 1094 | dprintk("Server FSID: %llx:%llx\n", |
1090 | (unsigned long long) server->fsid.major, | 1095 | (unsigned long long) server->fsid.major, |
@@ -1096,9 +1101,11 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, | |||
1096 | spin_unlock(&nfs_client_lock); | 1101 | spin_unlock(&nfs_client_lock); |
1097 | 1102 | ||
1098 | server->mount_time = jiffies; | 1103 | server->mount_time = jiffies; |
1104 | nfs_free_fattr(fattr); | ||
1099 | return server; | 1105 | return server; |
1100 | 1106 | ||
1101 | error: | 1107 | error: |
1108 | nfs_free_fattr(fattr); | ||
1102 | nfs_free_server(server); | 1109 | nfs_free_server(server); |
1103 | return ERR_PTR(error); | 1110 | return ERR_PTR(error); |
1104 | } | 1111 | } |
@@ -1120,7 +1127,7 @@ static int nfs4_init_callback(struct nfs_client *clp) | |||
1120 | return error; | 1127 | return error; |
1121 | } | 1128 | } |
1122 | 1129 | ||
1123 | error = nfs_callback_up(clp->cl_minorversion, | 1130 | error = nfs_callback_up(clp->cl_mvops->minor_version, |
1124 | clp->cl_rpcclient->cl_xprt); | 1131 | clp->cl_rpcclient->cl_xprt); |
1125 | if (error < 0) { | 1132 | if (error < 0) { |
1126 | dprintk("%s: failed to start callback. Error = %d\n", | 1133 | dprintk("%s: failed to start callback. Error = %d\n", |
@@ -1137,10 +1144,8 @@ static int nfs4_init_callback(struct nfs_client *clp) | |||
1137 | */ | 1144 | */ |
1138 | static int nfs4_init_client_minor_version(struct nfs_client *clp) | 1145 | static int nfs4_init_client_minor_version(struct nfs_client *clp) |
1139 | { | 1146 | { |
1140 | clp->cl_call_sync = _nfs4_call_sync; | ||
1141 | |||
1142 | #if defined(CONFIG_NFS_V4_1) | 1147 | #if defined(CONFIG_NFS_V4_1) |
1143 | if (clp->cl_minorversion) { | 1148 | if (clp->cl_mvops->minor_version) { |
1144 | struct nfs4_session *session = NULL; | 1149 | struct nfs4_session *session = NULL; |
1145 | /* | 1150 | /* |
1146 | * Create the session and mark it expired. | 1151 | * Create the session and mark it expired. |
@@ -1152,7 +1157,13 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp) | |||
1152 | return -ENOMEM; | 1157 | return -ENOMEM; |
1153 | 1158 | ||
1154 | clp->cl_session = session; | 1159 | clp->cl_session = session; |
1155 | clp->cl_call_sync = _nfs4_call_sync_session; | 1160 | /* |
1161 | * The create session reply races with the server back | ||
1162 | * channel probe. Mark the client NFS_CS_SESSION_INITING | ||
1163 | * so that the client back channel can find the | ||
1164 | * nfs_client struct | ||
1165 | */ | ||
1166 | clp->cl_cons_state = NFS_CS_SESSION_INITING; | ||
1156 | } | 1167 | } |
1157 | #endif /* CONFIG_NFS_V4_1 */ | 1168 | #endif /* CONFIG_NFS_V4_1 */ |
1158 | 1169 | ||
@@ -1280,6 +1291,55 @@ static void nfs4_session_set_rwsize(struct nfs_server *server) | |||
1280 | #endif /* CONFIG_NFS_V4_1 */ | 1291 | #endif /* CONFIG_NFS_V4_1 */ |
1281 | } | 1292 | } |
1282 | 1293 | ||
1294 | static int nfs4_server_common_setup(struct nfs_server *server, | ||
1295 | struct nfs_fh *mntfh) | ||
1296 | { | ||
1297 | struct nfs_fattr *fattr; | ||
1298 | int error; | ||
1299 | |||
1300 | BUG_ON(!server->nfs_client); | ||
1301 | BUG_ON(!server->nfs_client->rpc_ops); | ||
1302 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | ||
1303 | |||
1304 | fattr = nfs_alloc_fattr(); | ||
1305 | if (fattr == NULL) | ||
1306 | return -ENOMEM; | ||
1307 | |||
1308 | /* We must ensure the session is initialised first */ | ||
1309 | error = nfs4_init_session(server); | ||
1310 | if (error < 0) | ||
1311 | goto out; | ||
1312 | |||
1313 | /* Probe the root fh to retrieve its FSID and filehandle */ | ||
1314 | error = nfs4_get_rootfh(server, mntfh); | ||
1315 | if (error < 0) | ||
1316 | goto out; | ||
1317 | |||
1318 | dprintk("Server FSID: %llx:%llx\n", | ||
1319 | (unsigned long long) server->fsid.major, | ||
1320 | (unsigned long long) server->fsid.minor); | ||
1321 | dprintk("Mount FH: %d\n", mntfh->size); | ||
1322 | |||
1323 | nfs4_session_set_rwsize(server); | ||
1324 | |||
1325 | error = nfs_probe_fsinfo(server, mntfh, fattr); | ||
1326 | if (error < 0) | ||
1327 | goto out; | ||
1328 | |||
1329 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | ||
1330 | server->namelen = NFS4_MAXNAMLEN; | ||
1331 | |||
1332 | spin_lock(&nfs_client_lock); | ||
1333 | list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); | ||
1334 | list_add_tail(&server->master_link, &nfs_volume_list); | ||
1335 | spin_unlock(&nfs_client_lock); | ||
1336 | |||
1337 | server->mount_time = jiffies; | ||
1338 | out: | ||
1339 | nfs_free_fattr(fattr); | ||
1340 | return error; | ||
1341 | } | ||
1342 | |||
1283 | /* | 1343 | /* |
1284 | * Create a version 4 volume record | 1344 | * Create a version 4 volume record |
1285 | */ | 1345 | */ |
@@ -1340,7 +1400,6 @@ error: | |||
1340 | struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | 1400 | struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, |
1341 | struct nfs_fh *mntfh) | 1401 | struct nfs_fh *mntfh) |
1342 | { | 1402 | { |
1343 | struct nfs_fattr fattr; | ||
1344 | struct nfs_server *server; | 1403 | struct nfs_server *server; |
1345 | int error; | 1404 | int error; |
1346 | 1405 | ||
@@ -1355,39 +1414,10 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | |||
1355 | if (error < 0) | 1414 | if (error < 0) |
1356 | goto error; | 1415 | goto error; |
1357 | 1416 | ||
1358 | BUG_ON(!server->nfs_client); | 1417 | error = nfs4_server_common_setup(server, mntfh); |
1359 | BUG_ON(!server->nfs_client->rpc_ops); | ||
1360 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | ||
1361 | |||
1362 | error = nfs4_init_session(server); | ||
1363 | if (error < 0) | ||
1364 | goto error; | ||
1365 | |||
1366 | /* Probe the root fh to retrieve its FSID */ | ||
1367 | error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); | ||
1368 | if (error < 0) | ||
1369 | goto error; | ||
1370 | |||
1371 | dprintk("Server FSID: %llx:%llx\n", | ||
1372 | (unsigned long long) server->fsid.major, | ||
1373 | (unsigned long long) server->fsid.minor); | ||
1374 | dprintk("Mount FH: %d\n", mntfh->size); | ||
1375 | |||
1376 | nfs4_session_set_rwsize(server); | ||
1377 | |||
1378 | error = nfs_probe_fsinfo(server, mntfh, &fattr); | ||
1379 | if (error < 0) | 1418 | if (error < 0) |
1380 | goto error; | 1419 | goto error; |
1381 | 1420 | ||
1382 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | ||
1383 | server->namelen = NFS4_MAXNAMLEN; | ||
1384 | |||
1385 | spin_lock(&nfs_client_lock); | ||
1386 | list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); | ||
1387 | list_add_tail(&server->master_link, &nfs_volume_list); | ||
1388 | spin_unlock(&nfs_client_lock); | ||
1389 | |||
1390 | server->mount_time = jiffies; | ||
1391 | dprintk("<-- nfs4_create_server() = %p\n", server); | 1421 | dprintk("<-- nfs4_create_server() = %p\n", server); |
1392 | return server; | 1422 | return server; |
1393 | 1423 | ||
@@ -1405,7 +1435,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1405 | { | 1435 | { |
1406 | struct nfs_client *parent_client; | 1436 | struct nfs_client *parent_client; |
1407 | struct nfs_server *server, *parent_server; | 1437 | struct nfs_server *server, *parent_server; |
1408 | struct nfs_fattr fattr; | ||
1409 | int error; | 1438 | int error; |
1410 | 1439 | ||
1411 | dprintk("--> nfs4_create_referral_server()\n"); | 1440 | dprintk("--> nfs4_create_referral_server()\n"); |
@@ -1430,7 +1459,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1430 | data->authflavor, | 1459 | data->authflavor, |
1431 | parent_server->client->cl_xprt->prot, | 1460 | parent_server->client->cl_xprt->prot, |
1432 | parent_server->client->cl_timeout, | 1461 | parent_server->client->cl_timeout, |
1433 | parent_client->cl_minorversion); | 1462 | parent_client->cl_mvops->minor_version); |
1434 | if (error < 0) | 1463 | if (error < 0) |
1435 | goto error; | 1464 | goto error; |
1436 | 1465 | ||
@@ -1438,34 +1467,10 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1438 | if (error < 0) | 1467 | if (error < 0) |
1439 | goto error; | 1468 | goto error; |
1440 | 1469 | ||
1441 | BUG_ON(!server->nfs_client); | 1470 | error = nfs4_server_common_setup(server, mntfh); |
1442 | BUG_ON(!server->nfs_client->rpc_ops); | ||
1443 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | ||
1444 | |||
1445 | /* Probe the root fh to retrieve its FSID and filehandle */ | ||
1446 | error = nfs4_path_walk(server, mntfh, data->mnt_path); | ||
1447 | if (error < 0) | 1471 | if (error < 0) |
1448 | goto error; | 1472 | goto error; |
1449 | 1473 | ||
1450 | /* probe the filesystem info for this server filesystem */ | ||
1451 | error = nfs_probe_fsinfo(server, mntfh, &fattr); | ||
1452 | if (error < 0) | ||
1453 | goto error; | ||
1454 | |||
1455 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | ||
1456 | server->namelen = NFS4_MAXNAMLEN; | ||
1457 | |||
1458 | dprintk("Referral FSID: %llx:%llx\n", | ||
1459 | (unsigned long long) server->fsid.major, | ||
1460 | (unsigned long long) server->fsid.minor); | ||
1461 | |||
1462 | spin_lock(&nfs_client_lock); | ||
1463 | list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); | ||
1464 | list_add_tail(&server->master_link, &nfs_volume_list); | ||
1465 | spin_unlock(&nfs_client_lock); | ||
1466 | |||
1467 | server->mount_time = jiffies; | ||
1468 | |||
1469 | dprintk("<-- nfs_create_referral_server() = %p\n", server); | 1474 | dprintk("<-- nfs_create_referral_server() = %p\n", server); |
1470 | return server; | 1475 | return server; |
1471 | 1476 | ||
@@ -1485,7 +1490,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
1485 | struct nfs_fattr *fattr) | 1490 | struct nfs_fattr *fattr) |
1486 | { | 1491 | { |
1487 | struct nfs_server *server; | 1492 | struct nfs_server *server; |
1488 | struct nfs_fattr fattr_fsinfo; | 1493 | struct nfs_fattr *fattr_fsinfo; |
1489 | int error; | 1494 | int error; |
1490 | 1495 | ||
1491 | dprintk("--> nfs_clone_server(,%llx:%llx,)\n", | 1496 | dprintk("--> nfs_clone_server(,%llx:%llx,)\n", |
@@ -1496,6 +1501,11 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
1496 | if (!server) | 1501 | if (!server) |
1497 | return ERR_PTR(-ENOMEM); | 1502 | return ERR_PTR(-ENOMEM); |
1498 | 1503 | ||
1504 | error = -ENOMEM; | ||
1505 | fattr_fsinfo = nfs_alloc_fattr(); | ||
1506 | if (fattr_fsinfo == NULL) | ||
1507 | goto out_free_server; | ||
1508 | |||
1499 | /* Copy data from the source */ | 1509 | /* Copy data from the source */ |
1500 | server->nfs_client = source->nfs_client; | 1510 | server->nfs_client = source->nfs_client; |
1501 | atomic_inc(&server->nfs_client->cl_count); | 1511 | atomic_inc(&server->nfs_client->cl_count); |
@@ -1512,7 +1522,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
1512 | nfs_init_server_aclclient(server); | 1522 | nfs_init_server_aclclient(server); |
1513 | 1523 | ||
1514 | /* probe the filesystem info for this server filesystem */ | 1524 | /* probe the filesystem info for this server filesystem */ |
1515 | error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo); | 1525 | error = nfs_probe_fsinfo(server, fh, fattr_fsinfo); |
1516 | if (error < 0) | 1526 | if (error < 0) |
1517 | goto out_free_server; | 1527 | goto out_free_server; |
1518 | 1528 | ||
@@ -1534,10 +1544,12 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
1534 | 1544 | ||
1535 | server->mount_time = jiffies; | 1545 | server->mount_time = jiffies; |
1536 | 1546 | ||
1547 | nfs_free_fattr(fattr_fsinfo); | ||
1537 | dprintk("<-- nfs_clone_server() = %p\n", server); | 1548 | dprintk("<-- nfs_clone_server() = %p\n", server); |
1538 | return server; | 1549 | return server; |
1539 | 1550 | ||
1540 | out_free_server: | 1551 | out_free_server: |
1552 | nfs_free_fattr(fattr_fsinfo); | ||
1541 | nfs_free_server(server); | 1553 | nfs_free_server(server); |
1542 | dprintk("<-- nfs_clone_server() = error %d\n", error); | 1554 | dprintk("<-- nfs_clone_server() = error %d\n", error); |
1543 | return ERR_PTR(error); | 1555 | return ERR_PTR(error); |