netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* netfilter: half a patch for the pseudoregression
@ 2009-01-27 22:30 Jan Engelhardt
  2009-02-09 16:20 ` Patrick McHardy
  0 siblings, 1 reply; 5+ messages in thread
From: Jan Engelhardt @ 2009-01-27 22:30 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List



Here is the sample patch that fixes ip_tables_matches, but I still 
challenge the usefulness of /proc/net/ip_tables_* altogether.
Those files should have been removed, or appropriately upgraded when 
revision support was introduced.

http://picpaste.de/usefulornot_1.png

I am not fond of it, at all. Doing the same for targets - code
replication here we come. The LOC for it would have been
better spent at the previously-posted pretty-printer (knowing
that text printing meets the usual resistance).

---8<---
parent d8bf62a172295f26d960cea92aead0ce78ca524c (v2.6.29-rc2-21-gd8bf62a)
commit 3f1d7c73afeeb637ef05eba0ad7ccb55305ab8f2
Author: Jan Engelhardt <jengelh@medozas.de>
Date:   Tue Jan 27 23:21:16 2009 +0100

netfilter: make proc/net/ip_tables_matches print names from foreign NFPROTO

The ugliness this code adds could have been better spent at
a full and much more helpful dump.
---
 net/netfilter/x_tables.c |  115 +++++++++++++++++++++++++++++--------
 1 files changed, 90 insertions(+), 25 deletions(-)

diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index bfbf521..329c01c 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -827,39 +827,96 @@ static const struct file_operations xt_table_ops = {
 	.release = seq_release_net,
 };
 
-static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos)
+struct match_trav {
+	struct list_head *head, *curr;
+	uint8_t class, nfproto;
+};
+
+enum {
+	MATCHTRAV_INIT,
+	MATCHTRAV_NFP_UNSPEC,
+	MATCHTRAV_NFP_SPEC,
+	MATCHTRAV_DONE,
+};
+
+static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *ppos)
 {
-	struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
-	u_int16_t af = (unsigned long)pde->data;
+	static const uint8_t next_class[] = {
+		[MATCHTRAV_NFP_UNSPEC] = MATCHTRAV_NFP_SPEC,
+		[MATCHTRAV_NFP_SPEC]   = MATCHTRAV_DONE,
+	};
+	struct match_trav *trav = seq->private;
+
+	switch (trav->class) {
+	case MATCHTRAV_INIT:
+		trav->class = MATCHTRAV_NFP_UNSPEC;
+		mutex_lock(&xt[NFPROTO_UNSPEC].mutex);
+		trav->head = trav->curr = &xt[NFPROTO_UNSPEC].match;
+		break;
+	case MATCHTRAV_NFP_UNSPEC:
+		trav->curr = trav->curr->next;
+		if (trav->curr != trav->head)
+			break;
+		mutex_unlock(&xt[NFPROTO_UNSPEC].mutex);
+		mutex_lock(&xt[trav->nfproto].mutex);
+		trav->head = trav->curr = &xt[trav->nfproto].match;
+		trav->class = next_class[trav->class];
+		break;
+	case MATCHTRAV_NFP_SPEC:
+		trav->curr = trav->curr->next;
+		if (trav->curr != trav->head)
+			break;
+		/* fallthru, _stop will unlock */
+	default:
+		return NULL;
+	}
 
-	mutex_lock(&xt[af].mutex);
-	return seq_list_start(&xt[af].match, *pos);
+	if (ppos != NULL)
+		++*ppos;
+	return trav;
 }
 
-static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
-	u_int16_t af = (unsigned long)pde->data;
+	struct match_trav *trav = seq->private;
+	unsigned int j;
 
-	return seq_list_next(v, &xt[af].match, pos);
+	trav->class = MATCHTRAV_INIT;
+	for (j = 0; j < *pos; ++j)
+		if (xt_match_seq_next(seq, NULL, NULL) == NULL)
+			return NULL;
+	return trav;
 }
 
 static void xt_match_seq_stop(struct seq_file *seq, void *v)
 {
-	struct proc_dir_entry *pde = seq->private;
-	u_int16_t af = (unsigned long)pde->data;
-
-	mutex_unlock(&xt[af].mutex);
+	struct match_trav *trav = seq->private;
+
+	switch (trav->class) {
+	case MATCHTRAV_NFP_UNSPEC:
+		mutex_unlock(&xt[NFPROTO_UNSPEC].mutex);
+		break;
+	case MATCHTRAV_NFP_SPEC:
+		mutex_unlock(&xt[trav->nfproto].mutex);
+		break;
+	}
 }
 
 static int xt_match_seq_show(struct seq_file *seq, void *v)
 {
-	struct xt_match *match = list_entry(v, struct xt_match, list);
-
-	if (strlen(match->name))
-		return seq_printf(seq, "%s\n", match->name);
-	else
-		return 0;
+	const struct match_trav *trav = seq->private;
+	const struct xt_match *match;
+
+	switch (trav->class) {
+	case MATCHTRAV_NFP_UNSPEC:
+	case MATCHTRAV_NFP_SPEC:
+		if (trav->curr == trav->head)
+			return 0;
+		match = list_entry(trav->curr, struct xt_match, list);
+		return (*match->name == '\0') ? 0 :
+		       seq_printf(seq, "%s\n", match->name);
+	}
+	return 0;
 }
 
 static const struct seq_operations xt_match_seq_ops = {
@@ -871,15 +928,23 @@ static const struct seq_operations xt_match_seq_ops = {
 
 static int xt_match_open(struct inode *inode, struct file *file)
 {
+	struct seq_file *seq;
+	struct match_trav *trav;
 	int ret;
 
-	ret = seq_open(file, &xt_match_seq_ops);
-	if (!ret) {
-		struct seq_file *seq = file->private_data;
+	trav = kmalloc(sizeof(*trav), GFP_KERNEL);
+	if (trav == NULL)
+		return -ENOMEM;
 
-		seq->private = PDE(inode);
+	ret = seq_open(file, &xt_match_seq_ops);
+	if (ret < 0) {
+		kfree(trav);
+		return ret;
 	}
-	return ret;
+
+	seq = file->private_data;
+	seq->private = trav;
+	return 0;
 }
 
 static const struct file_operations xt_match_ops = {
@@ -887,7 +952,7 @@ static const struct file_operations xt_match_ops = {
 	.open	 = xt_match_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
-	.release = seq_release,
+	.release = seq_release_private,
 };
 
 static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos)
-- 
# Created with git-export-patch

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: netfilter: half a patch for the pseudoregression
  2009-01-27 22:30 netfilter: half a patch for the pseudoregression Jan Engelhardt
@ 2009-02-09 16:20 ` Patrick McHardy
  2009-02-12  4:28   ` Jan Engelhardt
  2009-02-17 18:53   ` Jan Engelhardt
  0 siblings, 2 replies; 5+ messages in thread
From: Patrick McHardy @ 2009-02-09 16:20 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List

Jan Engelhardt wrote:
> 
> Here is the sample patch that fixes ip_tables_matches, but I still 
> challenge the usefulness of /proc/net/ip_tables_* altogether.
> Those files should have been removed, or appropriately upgraded when 
> revision support was introduced.

Thats not really the question right now since it exists and people
are using it. Feel free to start a discussion on removing it once
we've fixed the regression.

> netfilter: make proc/net/ip_tables_matches print names from foreign NFPROTO
> 
> The ugliness this code adds could have been better spent at
> a full and much more helpful dump.

This might get easier by simply using the same mutex for all families.
Not sure if its worth it, in any case not for now.

The patch looks fine, please resubmit when you have fixed the second
half with proper changelog (stating that it fixes a regression and
the commit introducing it).

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: netfilter: half a patch for the pseudoregression
  2009-02-09 16:20 ` Patrick McHardy
@ 2009-02-12  4:28   ` Jan Engelhardt
  2009-02-17 18:53   ` Jan Engelhardt
  1 sibling, 0 replies; 5+ messages in thread
From: Jan Engelhardt @ 2009-02-12  4:28 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Netfilter Developer Mailing List


On Monday 2009-02-09 17:20, Patrick McHardy wrote:
>
>> netfilter: make proc/net/ip_tables_matches print names from foreign NFPROTO
>>
>> The ugliness this code adds could have been better spent at
>> a full and much more helpful dump.
>
> This might get easier by simply using the same mutex for all families.

There is (probably) a reason this mutex exists - should not touch
it before analysis to make sure performance does not go down the
gutter just because cross-nfproto mutex was unified. Maybe Stephen's
RCU work makes it less of a problem. Have not looked into that.

> The patch looks fine, please resubmit when you have fixed the second
> half with proper changelog (stating that it fixes a regression and
> the commit introducing it).

parent de9662219c15ec76867815e1ea4ee6e3bd2d5783 (v2.6.29-rc4-24-gde96622)
commit 6919d7bc8bc5e0639b6699e06cbb5af1be2d9523
Author: Jan Engelhardt <jengelh@medozas.de>
Date:   Thu Feb 12 05:27:45 2009 +0100

netfilter: make proc/net/ip* print names from foreign NFPROTO

When extensions were moved to the NFPROTO_UNSPEC wildcard in
ab4f21e6fb1c09b13c4c3cb8357babe8223471bd, they disappeared from the
procfs files.

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 net/netfilter/x_tables.c |  199 +++++++++++++++++++++++++++-----------
 1 files changed, 142 insertions(+), 57 deletions(-)

diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index bfbf521..5baccfa 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -827,59 +827,143 @@ static const struct file_operations xt_table_ops = {
 	.release = seq_release_net,
 };
 
-static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos)
+/*
+ * Traverse state for ip{,6}_{tables,matches} for helping crossing
+ * the multi-AF mutexes.
+ */
+struct nf_mttg_trav {
+	struct list_head *head, *curr;
+	uint8_t class, nfproto;
+};
+
+enum {
+	MTTG_TRAV_INIT,
+	MTTG_TRAV_NFP_UNSPEC,
+	MTTG_TRAV_NFP_SPEC,
+	MTTG_TRAV_DONE,
+};
+
+static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos,
+    bool is_target)
 {
-	struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
-	u_int16_t af = (unsigned long)pde->data;
+	static const uint8_t next_class[] = {
+		[MTTG_TRAV_NFP_UNSPEC] = MTTG_TRAV_NFP_SPEC,
+		[MTTG_TRAV_NFP_SPEC]   = MTTG_TRAV_DONE,
+	};
+	struct nf_mttg_trav *trav = seq->private;
+
+	switch (trav->class) {
+	case MTTG_TRAV_INIT:
+		trav->class = MTTG_TRAV_NFP_UNSPEC;
+		mutex_lock(&xt[NFPROTO_UNSPEC].mutex);
+		trav->head = trav->curr = is_target ?
+			&xt[NFPROTO_UNSPEC].target : &xt[NFPROTO_UNSPEC].match;
+ 		break;
+	case MTTG_TRAV_NFP_UNSPEC:
+		trav->curr = trav->curr->next;
+		if (trav->curr != trav->head)
+			break;
+		mutex_unlock(&xt[NFPROTO_UNSPEC].mutex);
+		mutex_lock(&xt[trav->nfproto].mutex);
+		trav->head = trav->curr = is_target ?
+			&xt[trav->nfproto].target : &xt[trav->nfproto].match;
+		trav->class = next_class[trav->class];
+		break;
+	case MTTG_TRAV_NFP_SPEC:
+		trav->curr = trav->curr->next;
+		if (trav->curr != trav->head)
+			break;
+		/* fallthru, _stop will unlock */
+	default:
+		return NULL;
+	}
 
-	mutex_lock(&xt[af].mutex);
-	return seq_list_start(&xt[af].match, *pos);
+	if (ppos != NULL)
+		++*ppos;
+	return trav;
 }
 
-static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *xt_mttg_seq_start(struct seq_file *seq, loff_t *pos,
+    bool is_target)
 {
-	struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
-	u_int16_t af = (unsigned long)pde->data;
+	struct nf_mttg_trav *trav = seq->private;
+	unsigned int j;
 
-	return seq_list_next(v, &xt[af].match, pos);
+	trav->class = MTTG_TRAV_INIT;
+	for (j = 0; j < *pos; ++j)
+		if (xt_mttg_seq_next(seq, NULL, NULL, is_target) == NULL)
+			return NULL;
+	return trav;
 }
 
-static void xt_match_seq_stop(struct seq_file *seq, void *v)
+static void xt_mttg_seq_stop(struct seq_file *seq, void *v)
 {
-	struct proc_dir_entry *pde = seq->private;
-	u_int16_t af = (unsigned long)pde->data;
+	struct nf_mttg_trav *trav = seq->private;
+
+	switch (trav->class) {
+	case MTTG_TRAV_NFP_UNSPEC:
+		mutex_unlock(&xt[NFPROTO_UNSPEC].mutex);
+		break;
+	case MTTG_TRAV_NFP_SPEC:
+		mutex_unlock(&xt[trav->nfproto].mutex);
+		break;
+	}
+}
 
-	mutex_unlock(&xt[af].mutex);
+static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	return xt_mttg_seq_start(seq, pos, false);
 }
 
-static int xt_match_seq_show(struct seq_file *seq, void *v)
+static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *ppos)
 {
-	struct xt_match *match = list_entry(v, struct xt_match, list);
+	return xt_mttg_seq_next(seq, v, ppos, false);
+}
 
-	if (strlen(match->name))
-		return seq_printf(seq, "%s\n", match->name);
-	else
-		return 0;
+static int xt_match_seq_show(struct seq_file *seq, void *v)
+{
+	const struct nf_mttg_trav *trav = seq->private;
+	const struct xt_match *match;
+
+	switch (trav->class) {
+	case MTTG_TRAV_NFP_UNSPEC:
+	case MTTG_TRAV_NFP_SPEC:
+		if (trav->curr == trav->head)
+			return 0;
+		match = list_entry(trav->curr, struct xt_match, list);
+		return (*match->name == '\0') ? 0 :
+		       seq_printf(seq, "%s\n", match->name);
+	}
+	return 0;
 }
 
 static const struct seq_operations xt_match_seq_ops = {
 	.start	= xt_match_seq_start,
 	.next	= xt_match_seq_next,
-	.stop	= xt_match_seq_stop,
+	.stop	= xt_mttg_seq_stop,
 	.show	= xt_match_seq_show,
 };
 
 static int xt_match_open(struct inode *inode, struct file *file)
 {
+	struct seq_file *seq;
+	struct nf_mttg_trav *trav;
 	int ret;
 
-	ret = seq_open(file, &xt_match_seq_ops);
-	if (!ret) {
-		struct seq_file *seq = file->private_data;
+	trav = kmalloc(sizeof(*trav), GFP_KERNEL);
+	if (trav == NULL)
+		return -ENOMEM;
 
-		seq->private = PDE(inode);
+	ret = seq_open(file, &xt_match_seq_ops);
+	if (ret < 0) {
+		kfree(trav);
+		return ret;
 	}
-	return ret;
+
+	seq = file->private_data;
+	seq->private = trav;
+	trav->nfproto = (unsigned long)PDE(inode)->data;
+	return 0;
 }
 
 static const struct file_operations xt_match_ops = {
@@ -887,62 +971,63 @@ static const struct file_operations xt_match_ops = {
 	.open	 = xt_match_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
-	.release = seq_release,
+	.release = seq_release_private,
 };
 
 static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
-	u_int16_t af = (unsigned long)pde->data;
-
-	mutex_lock(&xt[af].mutex);
-	return seq_list_start(&xt[af].target, *pos);
+	return xt_mttg_seq_start(seq, pos, true);
 }
 
-static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *ppos)
 {
-	struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
-	u_int16_t af = (unsigned long)pde->data;
-
-	return seq_list_next(v, &xt[af].target, pos);
-}
-
-static void xt_target_seq_stop(struct seq_file *seq, void *v)
-{
-	struct proc_dir_entry *pde = seq->private;
-	u_int16_t af = (unsigned long)pde->data;
-
-	mutex_unlock(&xt[af].mutex);
+	return xt_mttg_seq_next(seq, v, ppos, true);
 }
 
 static int xt_target_seq_show(struct seq_file *seq, void *v)
 {
-	struct xt_target *target = list_entry(v, struct xt_target, list);
-
-	if (strlen(target->name))
-		return seq_printf(seq, "%s\n", target->name);
-	else
-		return 0;
+	const struct nf_mttg_trav *trav = seq->private;
+	const struct xt_target *target;
+
+	switch (trav->class) {
+	case MTTG_TRAV_NFP_UNSPEC:
+	case MTTG_TRAV_NFP_SPEC:
+		if (trav->curr == trav->head)
+			return 0;
+		target = list_entry(trav->curr, struct xt_target, list);
+		return (*target->name == '\0') ? 0 :
+		       seq_printf(seq, "%s\n", target->name);
+	}
+	return 0;
 }
 
 static const struct seq_operations xt_target_seq_ops = {
 	.start	= xt_target_seq_start,
 	.next	= xt_target_seq_next,
-	.stop	= xt_target_seq_stop,
+	.stop	= xt_mttg_seq_stop,
 	.show	= xt_target_seq_show,
 };
 
 static int xt_target_open(struct inode *inode, struct file *file)
 {
+	struct seq_file *seq;
+	struct nf_mttg_trav *trav;
 	int ret;
 
-	ret = seq_open(file, &xt_target_seq_ops);
-	if (!ret) {
-		struct seq_file *seq = file->private_data;
+	trav = kmalloc(sizeof(*trav), GFP_KERNEL);
+	if (trav == NULL)
+		return -ENOMEM;
 
-		seq->private = PDE(inode);
+	ret = seq_open(file, &xt_target_seq_ops);
+	if (ret < 0) {
+		kfree(trav);
+		return ret;
 	}
-	return ret;
+
+	seq = file->private_data;
+	seq->private = trav;
+	trav->nfproto = (unsigned long)PDE(inode)->data;
+	return 0;
 }
 
 static const struct file_operations xt_target_ops = {
@@ -950,7 +1035,7 @@ static const struct file_operations xt_target_ops = {
 	.open	 = xt_target_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
-	.release = seq_release,
+	.release = seq_release_private,
 };
 
 #define FORMAT_TABLES	"_tables_names"
-- 
# Created with git-export-patch

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: netfilter: half a patch for the pseudoregression
  2009-02-09 16:20 ` Patrick McHardy
  2009-02-12  4:28   ` Jan Engelhardt
@ 2009-02-17 18:53   ` Jan Engelhardt
  2009-02-18 14:35     ` Patrick McHardy
  1 sibling, 1 reply; 5+ messages in thread
From: Jan Engelhardt @ 2009-02-17 18:53 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Netfilter Developer Mailing List


On Monday 2009-02-09 17:20, Patrick McHardy wrote:
> Jan Engelhardt wrote:
>>
>> Here is the sample patch that fixes ip_tables_matches, but I still challenge
>> the usefulness of /proc/net/ip_tables_* altogether.
>> Those files should have been removed, or appropriately upgraded when revision
>> support was introduced.
>
> Thats not really the question right now since it exists and people
> are using it. Feel free to start a discussion on removing it once
> we've fixed the regression.

I've also send the complete thing (twice now). Did you receive it?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: netfilter: half a patch for the pseudoregression
  2009-02-17 18:53   ` Jan Engelhardt
@ 2009-02-18 14:35     ` Patrick McHardy
  0 siblings, 0 replies; 5+ messages in thread
From: Patrick McHardy @ 2009-02-18 14:35 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List

Jan Engelhardt wrote:
> On Monday 2009-02-09 17:20, Patrick McHardy wrote:
>> Jan Engelhardt wrote:
>>> Here is the sample patch that fixes ip_tables_matches, but I still challenge
>>> the usefulness of /proc/net/ip_tables_* altogether.
>>> Those files should have been removed, or appropriately upgraded when revision
>>> support was introduced.
>> Thats not really the question right now since it exists and people
>> are using it. Feel free to start a discussion on removing it once
>> we've fixed the regression.
> 
> I've also send the complete thing (twice now). Did you receive it?

Applied, thanks. Will pass it upstream after some testing.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-02-18 14:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-27 22:30 netfilter: half a patch for the pseudoregression Jan Engelhardt
2009-02-09 16:20 ` Patrick McHardy
2009-02-12  4:28   ` Jan Engelhardt
2009-02-17 18:53   ` Jan Engelhardt
2009-02-18 14:35     ` Patrick McHardy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).