Message ID | 1439480749-54600-1-git-send-email-trond.myklebust@primarydata.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Aug 13, 2015 at 11:45 AM, Trond Myklebust <trond.myklebust@primarydata.com> wrote: > > - Switch back to using list_for_each_entry(). To fix an incorrect test > for list NULL termination. > - Do not assume that lists are sorted. > - Finally, consider an existing entry to match if it consists of a subset > of the addresses in the new entry. > > Cc: stable@vger.kernel.org # 4.0+ Note that the bug predates Linux-4.0; it goes all the way back to February 2012. This patch will not apply to older versions though, since it used to live in fs/nfs/filelayout/filelayoutdev.c. Cheers Trond -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, 13 Aug 2015 11:45:49 -0400 Trond Myklebust <trond.myklebust@primarydata.com> wrote: > - Switch back to using list_for_each_entry(). To fix an incorrect test > for list NULL termination. > - Do not assume that lists are sorted. > - Finally, consider an existing entry to match if it consists of a subset > of the addresses in the new entry. > > Cc: stable@vger.kernel.org # 4.0+ > Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> > --- > fs/nfs/pnfs_nfs.c | 33 +++++++++++++++++++-------------- > 1 file changed, 19 insertions(+), 14 deletions(-) > > diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c > index cd3c0403101b..bbd407b6bc1f 100644 > --- a/fs/nfs/pnfs_nfs.c > +++ b/fs/nfs/pnfs_nfs.c > @@ -373,26 +373,31 @@ same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2) > return false; > } > > +/* > + * Checks if 'dsaddrs1' contains a subset of 'dsaddrs2'. If it does, > + * declare a match. > + */ > static bool > _same_data_server_addrs_locked(const struct list_head *dsaddrs1, > const struct list_head *dsaddrs2) > { > struct nfs4_pnfs_ds_addr *da1, *da2; > - > - /* step through both lists, comparing as we go */ > - for (da1 = list_first_entry(dsaddrs1, typeof(*da1), da_node), > - da2 = list_first_entry(dsaddrs2, typeof(*da2), da_node); > - da1 != NULL && da2 != NULL; > - da1 = list_entry(da1->da_node.next, typeof(*da1), da_node), > - da2 = list_entry(da2->da_node.next, typeof(*da2), da_node)) { > - if (!same_sockaddr((struct sockaddr *)&da1->da_addr, > - (struct sockaddr *)&da2->da_addr)) > - return false; > + struct sockaddr *sa1, *sa2; > + bool match = false; > + > + list_for_each_entry(da1, dsaddrs1, da_node) { > + sa1 = (struct sockaddr *)&da1->da_addr; > + match = false; > + list_for_each_entry(da2, dsaddrs2, da_node) { > + sa2 = (struct sockaddr *)&da2->da_addr; > + match = same_sockaddr(sa1, sa2); > + if (match) > + break; Sure would be nice to consolidate some of these "same_sockaddr" functions at some point. We also have nfs_sockaddr_cmp which does the exact same thing, and probably some similar ones in the RPC layer. > + } > + if (!match) > + break; > } > - if (da1 == NULL && da2 == NULL) > - return true; > - > - return false; > + return match; > } > > /* Nice catch: Reviewed-by: Jeff Layton <jeff.layton@primarydata.com> -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index cd3c0403101b..bbd407b6bc1f 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c @@ -373,26 +373,31 @@ same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2) return false; } +/* + * Checks if 'dsaddrs1' contains a subset of 'dsaddrs2'. If it does, + * declare a match. + */ static bool _same_data_server_addrs_locked(const struct list_head *dsaddrs1, const struct list_head *dsaddrs2) { struct nfs4_pnfs_ds_addr *da1, *da2; - - /* step through both lists, comparing as we go */ - for (da1 = list_first_entry(dsaddrs1, typeof(*da1), da_node), - da2 = list_first_entry(dsaddrs2, typeof(*da2), da_node); - da1 != NULL && da2 != NULL; - da1 = list_entry(da1->da_node.next, typeof(*da1), da_node), - da2 = list_entry(da2->da_node.next, typeof(*da2), da_node)) { - if (!same_sockaddr((struct sockaddr *)&da1->da_addr, - (struct sockaddr *)&da2->da_addr)) - return false; + struct sockaddr *sa1, *sa2; + bool match = false; + + list_for_each_entry(da1, dsaddrs1, da_node) { + sa1 = (struct sockaddr *)&da1->da_addr; + match = false; + list_for_each_entry(da2, dsaddrs2, da_node) { + sa2 = (struct sockaddr *)&da2->da_addr; + match = same_sockaddr(sa1, sa2); + if (match) + break; + } + if (!match) + break; } - if (da1 == NULL && da2 == NULL) - return true; - - return false; + return match; } /*
- Switch back to using list_for_each_entry(). To fix an incorrect test for list NULL termination. - Do not assume that lists are sorted. - Finally, consider an existing entry to match if it consists of a subset of the addresses in the new entry. Cc: stable@vger.kernel.org # 4.0+ Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> --- fs/nfs/pnfs_nfs.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-)