Page MenuHomeFreeBSD

D31042.diff
No OneTemporary

D31042.diff

Index: lib/libpfctl/libpfctl.h
===================================================================
--- lib/libpfctl/libpfctl.h
+++ lib/libpfctl/libpfctl.h
@@ -238,6 +238,11 @@
uint32_t sync_flags;
};
+struct pfctl_states_stats {
+ uint64_t states;
+ size_t state_size_hint;
+};
+
TAILQ_HEAD(pfctl_statelist, pfctl_state);
struct pfctl_states {
struct pfctl_statelist states;
@@ -254,6 +259,7 @@
const char *anchor, const char *anchor_call, u_int32_t ticket,
u_int32_t pool_ticket);
int pfctl_set_keepcounters(int dev, bool keep);
+int pfctl_get_states_stats(int dev, struct pfctl_states_stats *stats);
int pfctl_get_states(int dev, struct pfctl_states *states);
void pfctl_free_states(struct pfctl_states *states);
int pfctl_clear_states(int dev, const struct pfctl_kill *kill,
Index: lib/libpfctl/libpfctl.c
===================================================================
--- lib/libpfctl/libpfctl.c
+++ lib/libpfctl/libpfctl.c
@@ -705,21 +705,65 @@
s->sync_flags = nvlist_get_number(nvl, "sync_flags");
}
+int
+pfctl_get_states_stats(int dev, struct pfctl_states_stats *stats)
+{
+ struct pfioc_nv nv;
+ nvlist_t *nvl = NULL;
+ int error = 0;
+
+ bzero(stats, sizeof(*stats));
+
+ nv.data = malloc(128);
+ nv.len = nv.size = 128;
+
+ if (ioctl(dev, DIOCGETSTATESSTATSNV, &nv)) {
+ error = errno;
+ goto out;
+ }
+
+ nvl = nvlist_unpack(nv.data, nv.len, 0);
+ if (nvl == NULL) {
+ error = EIO;
+ goto out;
+ }
+
+ stats->states = nvlist_get_number(nvl, "states");
+ stats->state_size_hint = nvlist_get_number(nvl, "state_size_hint");
+
+out:
+ nvlist_destroy(nvl);
+ free(nv.data);
+
+ return (error);
+}
+
int
pfctl_get_states(int dev, struct pfctl_states *states)
{
- struct pfioc_nv nv;
- nvlist_t *nvl = NULL;
- const nvlist_t * const *slist;
- size_t found_count;
- int error = 0;
+ struct pfioc_nv nv;
+ struct pfctl_states_stats stats;
+ nvlist_t *nvl = NULL;
+ const nvlist_t * const *slist;
+ size_t found_count;
+ size_t size_estimate;
+ int error = 0;
+
+ error = pfctl_get_states_stats(dev, &stats);
+ if (error)
+ return (error);
bzero(states, sizeof(*states));
TAILQ_INIT(&states->states);
- /* Just enough to get a number, and we'll grow from there. */
- nv.data = malloc(64);
- nv.len = nv.size = 64;
+ /* 20% extra, in case more states are added between the stats call and
+ * the actual read. */
+ size_estimate = 64 + (stats.states * stats.state_size_hint * 12 / 10);
+ /* Never more than 100MB at a time. */
+ size_estimate = MIN(size_estimate, 100 * 1024 * 1024);
+
+ nv.data = malloc(size_estimate);
+ nv.len = nv.size = size_estimate;
for (;;) {
if (ioctl(dev, DIOCGETSTATESNV, &nv)) {

File Metadata

Mime Type
text/plain
Expires
Sat, Feb 8, 8:32 PM (18 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16531788
Default Alt Text
D31042.diff (2 KB)

Event Timeline