Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFS: Add nfs_client behavior flags

"noresvport" and "discrtry" can be passed to nfs_create_rpc_client()
by setting flags in the passed-in nfs_client. This change makes it
easy to add new flags.

Note that these settings are now "sticky" over the lifetime of a
struct nfs_client, and may even be copied when an nfs_client is
cloned.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

authored by

Chuck Lever and committed by
Trond Myklebust
4bf590e0 8cab4c39

+26 -27
+20 -22
fs/nfs/client.c
··· 131 131 #endif /* CONFIG_NFS_V3_ACL */ 132 132 133 133 struct nfs_client_initdata { 134 + unsigned long init_flags; 134 135 const char *hostname; 135 136 const struct sockaddr *addr; 136 137 size_t addrlen; ··· 543 542 nfs_get_client(const struct nfs_client_initdata *cl_init, 544 543 const struct rpc_timeout *timeparms, 545 544 const char *ip_addr, 546 - rpc_authflavor_t authflavour, 547 - int noresvport) 545 + rpc_authflavor_t authflavour) 548 546 { 549 547 struct nfs_client *clp, *new = NULL; 550 548 struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id); ··· 565 565 if (new) { 566 566 list_add(&new->cl_share_link, &nn->nfs_client_list); 567 567 spin_unlock(&nn->nfs_client_lock); 568 + new->cl_flags = cl_init->init_flags; 568 569 return cl_init->rpc_ops->init_client(new, 569 570 timeparms, ip_addr, 570 - authflavour, noresvport); 571 + authflavour); 571 572 } 572 573 573 574 spin_unlock(&nn->nfs_client_lock); ··· 652 651 */ 653 652 static int nfs_create_rpc_client(struct nfs_client *clp, 654 653 const struct rpc_timeout *timeparms, 655 - rpc_authflavor_t flavor, 656 - int discrtry, int noresvport) 654 + rpc_authflavor_t flavor) 657 655 { 658 656 struct rpc_clnt *clnt = NULL; 659 657 struct rpc_create_args args = { ··· 667 667 .authflavor = flavor, 668 668 }; 669 669 670 - if (discrtry) 670 + if (test_bit(NFS_CS_DISCRTRY, &clp->cl_flags)) 671 671 args.flags |= RPC_CLNT_CREATE_DISCRTRY; 672 - if (noresvport) 672 + if (test_bit(NFS_CS_NORESVPORT, &clp->cl_flags)) 673 673 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; 674 674 675 675 if (!IS_ERR(clp->cl_rpcclient)) ··· 809 809 * @timeparms: timeout parameters for underlying RPC transport 810 810 * @ip_addr: IP presentation address (not used) 811 811 * @authflavor: authentication flavor for underlying RPC transport 812 - * @noresvport: set if RPC transport can use an ephemeral source port 813 812 * 814 813 * Returns pointer to an NFS client, or an ERR_PTR value. 815 814 */ 816 815 struct nfs_client *nfs_init_client(struct nfs_client *clp, 817 816 const struct rpc_timeout *timeparms, 818 - const char *ip_addr, rpc_authflavor_t authflavour, 819 - int noresvport) 817 + const char *ip_addr, rpc_authflavor_t authflavour) 820 818 { 821 819 int error; 822 820 ··· 828 830 * Create a client RPC handle for doing FSSTAT with UNIX auth only 829 831 * - RFC 2623, sec 2.3.2 830 832 */ 831 - error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, 832 - 0, noresvport); 833 + error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX); 833 834 if (error < 0) 834 835 goto error; 835 836 nfs_mark_client_ready(clp, NFS_CS_READY); ··· 878 881 879 882 nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, 880 883 data->timeo, data->retrans); 884 + if (data->flags & NFS_MOUNT_NORESVPORT) 885 + set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); 881 886 882 887 /* Allocate or find a client reference we can use */ 883 - clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX, 884 - data->flags & NFS_MOUNT_NORESVPORT); 888 + clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX); 885 889 if (IS_ERR(clp)) { 886 890 dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); 887 891 return PTR_ERR(clp); ··· 1362 1364 * @timeparms: timeout parameters for underlying RPC transport 1363 1365 * @ip_addr: callback IP address in presentation format 1364 1366 * @authflavor: authentication flavor for underlying RPC transport 1365 - * @noresvport: set if RPC transport can use an ephemeral source port 1366 1367 * 1367 1368 * Returns pointer to an NFS client, or an ERR_PTR value. 1368 1369 */ 1369 1370 struct nfs_client *nfs4_init_client(struct nfs_client *clp, 1370 1371 const struct rpc_timeout *timeparms, 1371 1372 const char *ip_addr, 1372 - rpc_authflavor_t authflavour, 1373 - int noresvport) 1373 + rpc_authflavor_t authflavour) 1374 1374 { 1375 1375 char buf[INET6_ADDRSTRLEN + 1]; 1376 1376 int error; ··· 1382 1386 /* Check NFS protocol revision and initialize RPC op vector */ 1383 1387 clp->rpc_ops = &nfs_v4_clientops; 1384 1388 1385 - error = nfs_create_rpc_client(clp, timeparms, authflavour, 1386 - 1, noresvport); 1389 + __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags); 1390 + error = nfs_create_rpc_client(clp, timeparms, authflavour); 1387 1391 if (error < 0) 1388 1392 goto error; 1389 1393 ··· 1451 1455 1452 1456 dprintk("--> nfs4_set_client()\n"); 1453 1457 1458 + if (server->flags & NFS_MOUNT_NORESVPORT) 1459 + set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); 1460 + 1454 1461 /* Allocate or find a client reference we can use */ 1455 - clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour, 1456 - server->flags & NFS_MOUNT_NORESVPORT); 1462 + clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour); 1457 1463 if (IS_ERR(clp)) { 1458 1464 error = PTR_ERR(clp); 1459 1465 goto error; ··· 1510 1512 */ 1511 1513 nfs_init_timeout_values(&ds_timeout, ds_proto, ds_timeo, ds_retrans); 1512 1514 clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr, 1513 - mds_clp->cl_rpcclient->cl_auth->au_flavor, 0); 1515 + mds_clp->cl_rpcclient->cl_auth->au_flavor); 1514 1516 1515 1517 dprintk("<-- %s %p\n", __func__, clp); 1516 1518 return clp;
+2 -4
fs/nfs/internal.h
··· 240 240 void nfs_close_context(struct nfs_open_context *ctx, int is_sync); 241 241 extern struct nfs_client *nfs_init_client(struct nfs_client *clp, 242 242 const struct rpc_timeout *timeparms, 243 - const char *ip_addr, rpc_authflavor_t authflavour, 244 - int noresvport); 243 + const char *ip_addr, rpc_authflavor_t authflavour); 245 244 246 245 /* dir.c */ 247 246 extern int nfs_access_cache_shrinker(struct shrinker *shrink, ··· 375 376 extern struct nfs_client *nfs4_init_client(struct nfs_client *clp, 376 377 const struct rpc_timeout *timeparms, 377 378 const char *ip_addr, 378 - rpc_authflavor_t authflavour, 379 - int noresvport); 379 + rpc_authflavor_t authflavour); 380 380 extern int _nfs4_call_sync(struct rpc_clnt *clnt, 381 381 struct nfs_server *server, 382 382 struct rpc_message *msg,
+3
include/linux/nfs_fs_sb.h
··· 35 35 #define NFS_CS_RENEWD 3 /* - renewd started */ 36 36 #define NFS_CS_STOP_RENEW 4 /* no more state to renew */ 37 37 #define NFS_CS_CHECK_LEASE_TIME 5 /* need to check lease time */ 38 + unsigned long cl_flags; /* behavior switches */ 39 + #define NFS_CS_NORESVPORT 0 /* - use ephemeral src port */ 40 + #define NFS_CS_DISCRTRY 1 /* - disconnect on RPC retry */ 38 41 struct sockaddr_storage cl_addr; /* server identifier */ 39 42 size_t cl_addrlen; 40 43 char * cl_hostname; /* hostname of server */
+1 -1
include/linux/nfs_xdr.h
··· 1399 1399 struct iattr *iattr); 1400 1400 struct nfs_client * 1401 1401 (*init_client) (struct nfs_client *, const struct rpc_timeout *, 1402 - const char *, rpc_authflavor_t, int); 1402 + const char *, rpc_authflavor_t); 1403 1403 }; 1404 1404 1405 1405 /*