Changeset View
Changeset View
Standalone View
Standalone View
sys/sys/mbuf.h
Context not available. | |||||
#endif | #endif | ||||
#endif | #endif | ||||
#ifdef MBUF_TRACKING | |||||
#include <sys/lock.h> | |||||
#include <sys/mutex.h> | |||||
#include <x86/stack.h> | |||||
LIST_HEAD(mbuflist, mbuf); | |||||
extern struct mbuflist mbufs; | |||||
extern struct mtx mbuf_track_mtx; | |||||
#define M_HANDOFF(m, x, y) \ | |||||
do { \ | |||||
m->m_owner = x; \ | |||||
m->m_ownerdata = y; \ | |||||
} while (0) | |||||
#define M_HANDOFFM(m, x, y) \ | |||||
do { \ | |||||
struct mbuf *_n = m; \ | |||||
while (_n) { \ | |||||
M_HANDOFF(_n, x, y); \ | |||||
_n = _n->m_next; \ | |||||
} \ | |||||
} while (0) | |||||
#define M_TRACK_FREE(m, x) \ | |||||
do { \ | |||||
m->m_lastowner = m->m_owner; \ | |||||
m->m_lastfree = x; \ | |||||
} while (0) | |||||
#define M_TRACK_FREE_EXT(m, x) \ | |||||
do { \ | |||||
m->m_ext.ext_lastowner = m->m_owner; \ | |||||
m->m_ext.ext_lastfree = x; \ | |||||
} while (0) | |||||
#define MBUF_TRACK_INSERT(mb) \ | |||||
do { \ | |||||
if (mb) { \ | |||||
M_HANDOFF(mb, "function", get_caller_ip()); \ | |||||
mtx_lock(&mbuf_track_mtx); \ | |||||
LIST_INSERT_HEAD(&mbufs, mb, m_mlist); \ | |||||
mtx_unlock(&mbuf_track_mtx); \ | |||||
} \ | |||||
} while (0) | |||||
#define MBUF_TRACK_REMOVE(mb) \ | |||||
do { \ | |||||
if (mb) { \ | |||||
mtx_lock(&mbuf_track_mtx); \ | |||||
LIST_REMOVE(mb, m_mlist); \ | |||||
mtx_unlock(&mbuf_track_mtx); \ | |||||
} \ | |||||
} while (0) | |||||
void mbuf_track_init(void); | |||||
#else /* !MBUF_TRACKING */ | |||||
#define M_HANDOFF(m, x, y) do { } while (0) | |||||
#define M_HANDOFFM(m, x, y) do { } while (0) | |||||
#define M_TRACK_FREE(m, x) do { } while (0) | |||||
#define M_TRACK_FREE_EXT(m, x) do { } while (0) | |||||
#define MBUF_TRACK_INSERT(mb) do { } while (0) | |||||
#define MBUF_TRACK_REMOVE(mb) do { } while (0) | |||||
#define get_mbuf_usage(fmt) do { } while (0) | |||||
#define print_mbuf_usage() do { } while (0) | |||||
#endif /* MBUF_TRACKING */ | |||||
/* | /* | ||||
* Mbufs are of a single size, MSIZE (sys/param.h), which includes overhead. | * Mbufs are of a single size, MSIZE (sys/param.h), which includes overhead. | ||||
* An mbuf may add a single "mbuf cluster" of size MCLBYTES (also in | * An mbuf may add a single "mbuf cluster" of size MCLBYTES (also in | ||||
Context not available. | |||||
(struct mbuf *, void *, void *); | (struct mbuf *, void *, void *); | ||||
void *ext_arg1; /* optional argument pointer */ | void *ext_arg1; /* optional argument pointer */ | ||||
void *ext_arg2; /* optional argument pointer */ | void *ext_arg2; /* optional argument pointer */ | ||||
#ifdef MBUF_TRACKING | |||||
const char *ext_lastowner; | |||||
const char *ext_lastfree; | |||||
#endif | |||||
}; | }; | ||||
/* | /* | ||||
Context not available. | |||||
#if !defined(__LP64__) | #if !defined(__LP64__) | ||||
uint32_t m_pad; /* pad for 64bit alignment */ | uint32_t m_pad; /* pad for 64bit alignment */ | ||||
#endif | #endif | ||||
#ifdef MBUF_TRACKING | |||||
const char *m_owner; | |||||
const void *m_ownerdata; | |||||
const char *m_lastowner; | |||||
const char *m_lastfree; | |||||
LIST_ENTRY(mbuf) m_mlist; | |||||
#endif | |||||
/* | /* | ||||
* A set of optional headers (packet header, external storage header) | * A set of optional headers (packet header, external storage header) | ||||
Context not available. | |||||
m_get(int how, short type) | m_get(int how, short type) | ||||
{ | { | ||||
struct mb_args args; | struct mb_args args; | ||||
struct mbuf *mb; | |||||
args.flags = 0; | args.flags = 0; | ||||
args.type = type; | args.type = type; | ||||
return (uma_zalloc_arg(zone_mbuf, &args, how)); | mb = uma_zalloc_arg(zone_mbuf, &args, how); | ||||
MBUF_TRACK_INSERT(mb); | |||||
return (mb); | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
m = uma_zalloc_arg(zone_mbuf, &args, how); | m = uma_zalloc_arg(zone_mbuf, &args, how); | ||||
if (m != NULL) | if (m != NULL) | ||||
bzero(m->m_data, MLEN); | bzero(m->m_data, MLEN); | ||||
MBUF_TRACK_INSERT(m); | |||||
return (m); | return (m); | ||||
} | } | ||||
Context not available. | |||||
m_gethdr(int how, short type) | m_gethdr(int how, short type) | ||||
{ | { | ||||
struct mb_args args; | struct mb_args args; | ||||
struct mbuf *mb; | |||||
args.flags = M_PKTHDR; | args.flags = M_PKTHDR; | ||||
args.type = type; | args.type = type; | ||||
return (uma_zalloc_arg(zone_mbuf, &args, how)); | mb = uma_zalloc_arg(zone_mbuf, &args, how); | ||||
MBUF_TRACK_INSERT(mb); | |||||
return (mb); | |||||
} | } | ||||
static __inline struct mbuf * | static __inline struct mbuf * | ||||
m_getcl(int how, short type, int flags) | m_getcl(int how, short type, int flags) | ||||
{ | { | ||||
struct mb_args args; | struct mb_args args; | ||||
struct mbuf *mb; | |||||
args.flags = flags; | args.flags = flags; | ||||
args.type = type; | args.type = type; | ||||
return (uma_zalloc_arg(zone_pack, &args, how)); | mb = uma_zalloc_arg(zone_pack, &args, how); | ||||
MBUF_TRACK_INSERT(mb); | |||||
return (mb); | |||||
} | } | ||||
static __inline int | static __inline int | ||||
Context not available. | |||||
struct mbuf *m_split(struct mbuf *, int, int); | struct mbuf *m_split(struct mbuf *, int, int); | ||||
struct mbuf *m_uiotombuf(struct uio *, int, int, int, int); | struct mbuf *m_uiotombuf(struct uio *, int, int, int, int); | ||||
struct mbuf *m_unshare(struct mbuf *, int); | struct mbuf *m_unshare(struct mbuf *, int); | ||||
#ifdef INVARIANTS | |||||
void m_check(struct mbuf *); | |||||
void m_checkm(struct mbuf *); | |||||
#endif | |||||
/*- | /*- | ||||
* Network packets may have annotations attached by affixing a list of | * Network packets may have annotations attached by affixing a list of | ||||
Context not available. | |||||
{ | { | ||||
struct mbuf *n = m->m_next; | struct mbuf *n = m->m_next; | ||||
MBUF_TRACK_REMOVE(m); | |||||
M_TRACK_FREE(m, __func__); | |||||
if ((m->m_flags & M_EXT) != 0) | |||||
M_TRACK_FREE_EXT(m, __func__); | |||||
M_HANDOFF(m, __func__, 0); | |||||
if ((m->m_flags & (M_PKTHDR|M_NOFREE)) == (M_PKTHDR|M_NOFREE)) | if ((m->m_flags & (M_PKTHDR|M_NOFREE)) == (M_PKTHDR|M_NOFREE)) | ||||
m_tag_delete_chain(m, NULL); | m_tag_delete_chain(m, NULL); | ||||
if (m->m_flags & M_EXT) | if (m->m_flags & M_EXT) | ||||
mb_free_ext(m); | mb_free_ext(m); | ||||
else if ((m->m_flags & M_NOFREE) == 0) | else if ((m->m_flags & M_NOFREE) == 0) { | ||||
#ifdef INVARIANTS | |||||
m_check(m); | |||||
#endif | |||||
uma_zfree(zone_mbuf, m); | uma_zfree(zone_mbuf, m); | ||||
} | |||||
return (n); | return (n); | ||||
} | } | ||||
Context not available. |