aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2010-12-23 20:32:32 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-01-06 14:47:56 -0500
commitfca5238ef3232cd0cf4bf0457e751b3bb20912a9 (patch)
tree5b61da0d71e3e89b835d46a49e0f4945b5002cea
parentf7e8917a67980924651a9e244510e63ef05c7755 (diff)
NFS: Allow walking nfs_client.cl_superblocks list outside client.c
We're about to move some fields from struct nfs_client to struct nfs_server. There is a many-to-one relationship between nfs_servers and nfs_clients. After these fields are moved to the nfs_server struct, to visit all of the data in these fields that is owned by one nfs_client, code will need to visit each nfs_server on the cl_superblocks list for that nfs_client. To serialize changes to the cl_superblocks list during these little expeditions, protect the list with RCU. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/client.c44
-rw-r--r--fs/nfs/nfs4renewd.c9
2 files changed, 32 insertions, 21 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 684b67771199..32b5fbfab35e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1003,6 +1003,27 @@ static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_serve
1003 target->options = source->options; 1003 target->options = source->options;
1004} 1004}
1005 1005
1006static void nfs_server_insert_lists(struct nfs_server *server)
1007{
1008 struct nfs_client *clp = server->nfs_client;
1009
1010 spin_lock(&nfs_client_lock);
1011 list_add_tail_rcu(&server->client_link, &clp->cl_superblocks);
1012 list_add_tail(&server->master_link, &nfs_volume_list);
1013 spin_unlock(&nfs_client_lock);
1014
1015}
1016
1017static void nfs_server_remove_lists(struct nfs_server *server)
1018{
1019 spin_lock(&nfs_client_lock);
1020 list_del_rcu(&server->client_link);
1021 list_del(&server->master_link);
1022 spin_unlock(&nfs_client_lock);
1023
1024 synchronize_rcu();
1025}
1026
1006/* 1027/*
1007 * Allocate and initialise a server record 1028 * Allocate and initialise a server record
1008 */ 1029 */
@@ -1046,11 +1067,8 @@ void nfs_free_server(struct nfs_server *server)
1046{ 1067{
1047 dprintk("--> nfs_free_server()\n"); 1068 dprintk("--> nfs_free_server()\n");
1048 1069
1070 nfs_server_remove_lists(server);
1049 unset_pnfs_layoutdriver(server); 1071 unset_pnfs_layoutdriver(server);
1050 spin_lock(&nfs_client_lock);
1051 list_del(&server->client_link);
1052 list_del(&server->master_link);
1053 spin_unlock(&nfs_client_lock);
1054 1072
1055 if (server->destroy != NULL) 1073 if (server->destroy != NULL)
1056 server->destroy(server); 1074 server->destroy(server);
@@ -1125,11 +1143,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
1125 (unsigned long long) server->fsid.major, 1143 (unsigned long long) server->fsid.major,
1126 (unsigned long long) server->fsid.minor); 1144 (unsigned long long) server->fsid.minor);
1127 1145
1128 spin_lock(&nfs_client_lock); 1146 nfs_server_insert_lists(server);
1129 list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
1130 list_add_tail(&server->master_link, &nfs_volume_list);
1131 spin_unlock(&nfs_client_lock);
1132
1133 server->mount_time = jiffies; 1147 server->mount_time = jiffies;
1134 nfs_free_fattr(fattr); 1148 nfs_free_fattr(fattr);
1135 return server; 1149 return server;
@@ -1454,11 +1468,7 @@ static int nfs4_server_common_setup(struct nfs_server *server,
1454 if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) 1468 if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
1455 server->namelen = NFS4_MAXNAMLEN; 1469 server->namelen = NFS4_MAXNAMLEN;
1456 1470
1457 spin_lock(&nfs_client_lock); 1471 nfs_server_insert_lists(server);
1458 list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
1459 list_add_tail(&server->master_link, &nfs_volume_list);
1460 spin_unlock(&nfs_client_lock);
1461
1462 server->mount_time = jiffies; 1472 server->mount_time = jiffies;
1463out: 1473out:
1464 nfs_free_fattr(fattr); 1474 nfs_free_fattr(fattr);
@@ -1663,11 +1673,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
1663 if (error < 0) 1673 if (error < 0)
1664 goto out_free_server; 1674 goto out_free_server;
1665 1675
1666 spin_lock(&nfs_client_lock); 1676 nfs_server_insert_lists(server);
1667 list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
1668 list_add_tail(&server->master_link, &nfs_volume_list);
1669 spin_unlock(&nfs_client_lock);
1670
1671 server->mount_time = jiffies; 1677 server->mount_time = jiffies;
1672 1678
1673 nfs_free_fattr(fattr_fsinfo); 1679 nfs_free_fattr(fattr_fsinfo);
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 72b6c580af13..cde5650ee5a2 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -63,9 +63,14 @@ nfs4_renew_state(struct work_struct *work)
63 63
64 ops = clp->cl_mvops->state_renewal_ops; 64 ops = clp->cl_mvops->state_renewal_ops;
65 dprintk("%s: start\n", __func__); 65 dprintk("%s: start\n", __func__);
66 /* Are there any active superblocks? */ 66
67 if (list_empty(&clp->cl_superblocks)) 67 rcu_read_lock();
68 if (list_empty(&clp->cl_superblocks)) {
69 rcu_read_unlock();
68 goto out; 70 goto out;
71 }
72 rcu_read_unlock();
73
69 spin_lock(&clp->cl_lock); 74 spin_lock(&clp->cl_lock);
70 lease = clp->cl_lease_time; 75 lease = clp->cl_lease_time;
71 last = clp->cl_last_renewal; 76 last = clp->cl_last_renewal;