cxgbe(4): Fix bug in the calculation of the number of physically

contiguous regions in an mbuf chain.

If the payload of an mbuf ends at a page boundary count_mbuf_nsegs would
incorrectly consider the next mbuf's payload physically contiguous based
solely on a KVA comparison.

MFC after:	1 week
Sponsored by:	Chelsio Communications
This commit is contained in:
Navdeep Parhar 2016-10-24 19:09:56 +00:00
parent d67ec19c3e
commit 77e9044c47

View File

@ -2110,24 +2110,6 @@ m_advance(struct mbuf **pm, int *poffset, int len)
return ((void *)p);
}
static inline int
same_paddr(char *a, char *b)
{
if (a == b)
return (1);
else if (a != NULL && b != NULL) {
vm_offset_t x = (vm_offset_t)a;
vm_offset_t y = (vm_offset_t)b;
if ((x & PAGE_MASK) == (y & PAGE_MASK) &&
pmap_kextract(x) == pmap_kextract(y))
return (1);
}
return (0);
}
/*
* Can deal with empty mbufs in the chain that have m_len = 0, but the chain
* must have at least one mbuf that's not empty.
@ -2135,24 +2117,25 @@ same_paddr(char *a, char *b)
static inline int
count_mbuf_nsegs(struct mbuf *m)
{
char *prev_end, *start;
vm_paddr_t lastb, next;
vm_offset_t va;
int len, nsegs;
MPASS(m != NULL);
nsegs = 0;
prev_end = NULL;
lastb = 0;
for (; m; m = m->m_next) {
len = m->m_len;
if (__predict_false(len == 0))
continue;
start = mtod(m, char *);
nsegs += sglist_count(start, len);
if (same_paddr(prev_end, start))
va = mtod(m, vm_offset_t);
next = pmap_kextract(va);
nsegs += sglist_count(m->m_data, len);
if (lastb + 1 == next)
nsegs--;
prev_end = start + len;
lastb = pmap_kextract(va + len - 1);
}
MPASS(nsegs > 0);