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>
This commit is contained in:
		
					parent
					
						
							
								f7e8917a67
							
						
					
				
			
			
				commit
				
					
						fca5238ef3
					
				
			
		
					 2 changed files with 32 additions and 21 deletions
				
			
		|  | @ -1003,6 +1003,27 @@ static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_serve | |||
| 	target->options = source->options; | ||||
| } | ||||
| 
 | ||||
| static void nfs_server_insert_lists(struct nfs_server *server) | ||||
| { | ||||
| 	struct nfs_client *clp = server->nfs_client; | ||||
| 
 | ||||
| 	spin_lock(&nfs_client_lock); | ||||
| 	list_add_tail_rcu(&server->client_link, &clp->cl_superblocks); | ||||
| 	list_add_tail(&server->master_link, &nfs_volume_list); | ||||
| 	spin_unlock(&nfs_client_lock); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| static void nfs_server_remove_lists(struct nfs_server *server) | ||||
| { | ||||
| 	spin_lock(&nfs_client_lock); | ||||
| 	list_del_rcu(&server->client_link); | ||||
| 	list_del(&server->master_link); | ||||
| 	spin_unlock(&nfs_client_lock); | ||||
| 
 | ||||
| 	synchronize_rcu(); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Allocate and initialise a server record | ||||
|  */ | ||||
|  | @ -1046,11 +1067,8 @@ void nfs_free_server(struct nfs_server *server) | |||
| { | ||||
| 	dprintk("--> nfs_free_server()\n"); | ||||
| 
 | ||||
| 	nfs_server_remove_lists(server); | ||||
| 	unset_pnfs_layoutdriver(server); | ||||
| 	spin_lock(&nfs_client_lock); | ||||
| 	list_del(&server->client_link); | ||||
| 	list_del(&server->master_link); | ||||
| 	spin_unlock(&nfs_client_lock); | ||||
| 
 | ||||
| 	if (server->destroy != NULL) | ||||
| 		server->destroy(server); | ||||
|  | @ -1125,11 +1143,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, | |||
| 		(unsigned long long) server->fsid.major, | ||||
| 		(unsigned long long) server->fsid.minor); | ||||
| 
 | ||||
| 	spin_lock(&nfs_client_lock); | ||||
| 	list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); | ||||
| 	list_add_tail(&server->master_link, &nfs_volume_list); | ||||
| 	spin_unlock(&nfs_client_lock); | ||||
| 
 | ||||
| 	nfs_server_insert_lists(server); | ||||
| 	server->mount_time = jiffies; | ||||
| 	nfs_free_fattr(fattr); | ||||
| 	return server; | ||||
|  | @ -1454,11 +1468,7 @@ static int nfs4_server_common_setup(struct nfs_server *server, | |||
| 	if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | ||||
| 		server->namelen = NFS4_MAXNAMLEN; | ||||
| 
 | ||||
| 	spin_lock(&nfs_client_lock); | ||||
| 	list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); | ||||
| 	list_add_tail(&server->master_link, &nfs_volume_list); | ||||
| 	spin_unlock(&nfs_client_lock); | ||||
| 
 | ||||
| 	nfs_server_insert_lists(server); | ||||
| 	server->mount_time = jiffies; | ||||
| out: | ||||
| 	nfs_free_fattr(fattr); | ||||
|  | @ -1663,11 +1673,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
| 	if (error < 0) | ||||
| 		goto out_free_server; | ||||
| 
 | ||||
| 	spin_lock(&nfs_client_lock); | ||||
| 	list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); | ||||
| 	list_add_tail(&server->master_link, &nfs_volume_list); | ||||
| 	spin_unlock(&nfs_client_lock); | ||||
| 
 | ||||
| 	nfs_server_insert_lists(server); | ||||
| 	server->mount_time = jiffies; | ||||
| 
 | ||||
| 	nfs_free_fattr(fattr_fsinfo); | ||||
|  |  | |||
|  | @ -63,9 +63,14 @@ nfs4_renew_state(struct work_struct *work) | |||
| 
 | ||||
| 	ops = clp->cl_mvops->state_renewal_ops; | ||||
| 	dprintk("%s: start\n", __func__); | ||||
| 	/* Are there any active superblocks? */ | ||||
| 	if (list_empty(&clp->cl_superblocks)) | ||||
| 
 | ||||
| 	rcu_read_lock(); | ||||
| 	if (list_empty(&clp->cl_superblocks)) { | ||||
| 		rcu_read_unlock(); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	rcu_read_unlock(); | ||||
| 
 | ||||
| 	spin_lock(&clp->cl_lock); | ||||
| 	lease = clp->cl_lease_time; | ||||
| 	last = clp->cl_last_renewal; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Chuck Lever
				Chuck Lever