diff options
-rw-r--r-- | net/netfilter/nf_conntrack_labels.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c index 3a30900891c1..bd7f26b97ac6 100644 --- a/net/netfilter/nf_conntrack_labels.c +++ b/net/netfilter/nf_conntrack_labels.c | |||
@@ -33,14 +33,18 @@ int nf_connlabel_set(struct nf_conn *ct, u16 bit) | |||
33 | } | 33 | } |
34 | EXPORT_SYMBOL_GPL(nf_connlabel_set); | 34 | EXPORT_SYMBOL_GPL(nf_connlabel_set); |
35 | 35 | ||
36 | static void replace_u32(u32 *address, u32 mask, u32 new) | 36 | static int replace_u32(u32 *address, u32 mask, u32 new) |
37 | { | 37 | { |
38 | u32 old, tmp; | 38 | u32 old, tmp; |
39 | 39 | ||
40 | do { | 40 | do { |
41 | old = *address; | 41 | old = *address; |
42 | tmp = (old & mask) ^ new; | 42 | tmp = (old & mask) ^ new; |
43 | if (old == tmp) | ||
44 | return 0; | ||
43 | } while (cmpxchg(address, old, tmp) != old); | 45 | } while (cmpxchg(address, old, tmp) != old); |
46 | |||
47 | return 1; | ||
44 | } | 48 | } |
45 | 49 | ||
46 | int nf_connlabels_replace(struct nf_conn *ct, | 50 | int nf_connlabels_replace(struct nf_conn *ct, |
@@ -49,6 +53,7 @@ int nf_connlabels_replace(struct nf_conn *ct, | |||
49 | { | 53 | { |
50 | struct nf_conn_labels *labels; | 54 | struct nf_conn_labels *labels; |
51 | unsigned int size, i; | 55 | unsigned int size, i; |
56 | int changed = 0; | ||
52 | u32 *dst; | 57 | u32 *dst; |
53 | 58 | ||
54 | labels = nf_ct_labels_find(ct); | 59 | labels = nf_ct_labels_find(ct); |
@@ -60,16 +65,15 @@ int nf_connlabels_replace(struct nf_conn *ct, | |||
60 | words32 = size / sizeof(u32); | 65 | words32 = size / sizeof(u32); |
61 | 66 | ||
62 | dst = (u32 *) labels->bits; | 67 | dst = (u32 *) labels->bits; |
63 | if (words32) { | 68 | for (i = 0; i < words32; i++) |
64 | for (i = 0; i < words32; i++) | 69 | changed |= replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]); |
65 | replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]); | ||
66 | } | ||
67 | 70 | ||
68 | size /= sizeof(u32); | 71 | size /= sizeof(u32); |
69 | for (i = words32; i < size; i++) /* pad */ | 72 | for (i = words32; i < size; i++) /* pad */ |
70 | replace_u32(&dst[i], 0, 0); | 73 | replace_u32(&dst[i], 0, 0); |
71 | 74 | ||
72 | nf_conntrack_event_cache(IPCT_LABEL, ct); | 75 | if (changed) |
76 | nf_conntrack_event_cache(IPCT_LABEL, ct); | ||
73 | return 0; | 77 | return 0; |
74 | } | 78 | } |
75 | EXPORT_SYMBOL_GPL(nf_connlabels_replace); | 79 | EXPORT_SYMBOL_GPL(nf_connlabels_replace); |