aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4filelayoutdev.c
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@netapp.com>2012-02-03 15:45:40 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-02-06 18:48:00 -0500
commit2d3fe01c36a9b881fae89c5bdf4085a4d7d53ae1 (patch)
tree96abc37a5977cec03f55c3575db054e4c08283c3 /fs/nfs/nfs4filelayoutdev.c
parenta030889a01d1bea921e1a7501010b7b891d2abd2 (diff)
NFS: Fix comparison between DS address lists
data_server_cache entries should only be treated as the same if the address list hasn't changed. A new entry will be made when an MDS changes an address list (as seen by GETDEVINFO). The old entry will be freed once all references are gone. Signed-off-by: Weston Andros Adamson <dros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4filelayoutdev.c')
-rw-r--r--fs/nfs/nfs4filelayoutdev.c71
1 files changed, 24 insertions, 47 deletions
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index 80fce8dade2..41677f0bf79 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -108,58 +108,40 @@ same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2)
108 return false; 108 return false;
109} 109}
110 110
111/* 111bool
112 * Lookup DS by addresses. The first matching address returns true. 112_same_data_server_addrs_locked(const struct list_head *dsaddrs1,
113 * nfs4_ds_cache_lock is held 113 const struct list_head *dsaddrs2)
114 */
115static struct nfs4_pnfs_ds *
116_data_server_lookup_locked(struct list_head *dsaddrs)
117{ 114{
118 struct nfs4_pnfs_ds *ds;
119 struct nfs4_pnfs_ds_addr *da1, *da2; 115 struct nfs4_pnfs_ds_addr *da1, *da2;
120 116
121 list_for_each_entry(da1, dsaddrs, da_node) { 117 /* step through both lists, comparing as we go */
122 list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) { 118 for (da1 = list_first_entry(dsaddrs1, typeof(*da1), da_node),
123 list_for_each_entry(da2, &ds->ds_addrs, da_node) { 119 da2 = list_first_entry(dsaddrs2, typeof(*da2), da_node);
124 if (same_sockaddr( 120 da1 != NULL && da2 != NULL;
125 (struct sockaddr *)&da1->da_addr, 121 da1 = list_entry(da1->da_node.next, typeof(*da1), da_node),
126 (struct sockaddr *)&da2->da_addr)) 122 da2 = list_entry(da2->da_node.next, typeof(*da2), da_node)) {
127 return ds; 123 if (!same_sockaddr((struct sockaddr *)&da1->da_addr,
128 } 124 (struct sockaddr *)&da2->da_addr))
129 } 125 return false;
130 } 126 }
131 return NULL; 127 if (da1 == NULL && da2 == NULL)
128 return true;
129
130 return false;
132} 131}
133 132
134/* 133/*
135 * Compare two lists of addresses. 134 * Lookup DS by addresses. nfs4_ds_cache_lock is held
136 */ 135 */
137static bool 136static struct nfs4_pnfs_ds *
138_data_server_match_all_addrs_locked(struct list_head *dsaddrs1, 137_data_server_lookup_locked(const struct list_head *dsaddrs)
139 struct list_head *dsaddrs2)
140{ 138{
141 struct nfs4_pnfs_ds_addr *da1, *da2; 139 struct nfs4_pnfs_ds *ds;
142 size_t count1 = 0,
143 count2 = 0;
144
145 list_for_each_entry(da1, dsaddrs1, da_node)
146 count1++;
147
148 list_for_each_entry(da2, dsaddrs2, da_node) {
149 bool found = false;
150 count2++;
151 list_for_each_entry(da1, dsaddrs1, da_node) {
152 if (same_sockaddr((struct sockaddr *)&da1->da_addr,
153 (struct sockaddr *)&da2->da_addr)) {
154 found = true;
155 break;
156 }
157 }
158 if (!found)
159 return false;
160 }
161 140
162 return (count1 == count2); 141 list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
142 if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs))
143 return ds;
144 return NULL;
163} 145}
164 146
165/* 147/*
@@ -356,11 +338,6 @@ nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags)
356 dprintk("%s add new data server %s\n", __func__, 338 dprintk("%s add new data server %s\n", __func__,
357 ds->ds_remotestr); 339 ds->ds_remotestr);
358 } else { 340 } else {
359 if (!_data_server_match_all_addrs_locked(&tmp_ds->ds_addrs,
360 dsaddrs)) {
361 dprintk("%s: multipath address mismatch: %s != %s",
362 __func__, tmp_ds->ds_remotestr, remotestr);
363 }
364 kfree(remotestr); 341 kfree(remotestr);
365 kfree(ds); 342 kfree(ds);
366 atomic_inc(&tmp_ds->ds_count); 343 atomic_inc(&tmp_ds->ds_count);