diff options
author | Weston Andros Adamson <dros@netapp.com> | 2012-02-03 15:45:40 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-02-06 18:48:00 -0500 |
commit | 2d3fe01c36a9b881fae89c5bdf4085a4d7d53ae1 (patch) | |
tree | 96abc37a5977cec03f55c3575db054e4c08283c3 /fs/nfs/nfs4filelayoutdev.c | |
parent | a030889a01d1bea921e1a7501010b7b891d2abd2 (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.c | 71 |
1 files changed, 24 insertions, 47 deletions
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index 80fce8dade2e..41677f0bf792 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 | /* | 111 | bool |
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 | */ | ||
115 | static 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 | */ |
137 | static bool | 136 | static 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); |