summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Tricca <flihp@twobit.us>2015-06-17 15:30:58 -0700
committerJoe MacDonald <joe_macdonald@mentor.com>2015-08-08 16:43:23 -0400
commit1cd60863053fd8586684552cc323c14789dd54b5 (patch)
tree9e5b04a39568b4ec5ae5399b6d88c373ef96b3a2
parent5cb8ef7d0403954ec947e743c36015738652809c (diff)
downloadmeta-selinux-1cd60863053fd8586684552cc323c14789dd54b5.tar.gz
e2fsprogs: Implement xattr block cache with simple linked list.
Signed-off-by: Philip Tricca <flihp@twobit.us> Signed-off-by: Joe MacDonald <joe_macdonald@mentor.com>
-rw-r--r--recipes-devtools/e2fsprogs/e2fsprogs/misc-xattr-create-xattr-cache.patch181
-rw-r--r--recipes-devtools/e2fsprogs/e2fsprogs_1.42.9.bbappend1
2 files changed, 182 insertions, 0 deletions
diff --git a/recipes-devtools/e2fsprogs/e2fsprogs/misc-xattr-create-xattr-cache.patch b/recipes-devtools/e2fsprogs/e2fsprogs/misc-xattr-create-xattr-cache.patch
new file mode 100644
index 0000000..38e6454
--- /dev/null
+++ b/recipes-devtools/e2fsprogs/e2fsprogs/misc-xattr-create-xattr-cache.patch
@@ -0,0 +1,181 @@
1Implement the xattr block cache as an unsorted linked list. This requires the
2add and rm functions be able to test for equality between xattr blocks. This
3is implemented as two functions. The first compares individual entries and the
4second compares the whole xattr block by iterating over the individual entries.
5
6The xattr block cache keeps memory allocated on the heap around across
7invocations of the set_inode_xattr function. To free this memory we implement
8an xattr_cleanup function that iterates over the cache freeing resources
9associated with each node.
10
11Signed-off-by: Philip Tricca <flihp@twobit.us>
12
13Index: e2fsprogs-1.42.9/misc/xattr.c
14===================================================================
15--- e2fsprogs-1.42.9.orig/misc/xattr.c
16+++ e2fsprogs-1.42.9/misc/xattr.c
17@@ -5,6 +5,7 @@
18 #include <errno.h>
19 #include <ext2fs/ext2_ext_attr.h>
20 #include <linux/xattr.h>
21+#include <stdbool.h>
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25@@ -25,6 +26,9 @@
26 #define XATTR_STDERR(fmt, args...) do {} while (0)
27 #endif
28
29+static size_t cache_hit = 0;
30+static size_t cache_miss = 0;
31+
32 /* nodes for simple linked list to track xattr blocks, calling it a cache
33 * would be a stretch ...
34 */
35@@ -76,7 +80,18 @@ xattr_free_node (xattr_node_t *node)
36 void
37 xattr_cleanup ()
38 {
39+ xattr_node_t *curr = NULL, *tmp = NULL;
40+ size_t count = 0;
41+
42 XATTR_STDERR ("Cleaning up resources from xattrs.\n");
43+ for (curr = xattr_list_head; curr != NULL; ++count) {
44+ tmp = curr;
45+ curr = curr->next;
46+ xattr_free_node (tmp);
47+ }
48+ XATTR_STDERR ("Freed %d xattr_node_ts.\n", count);
49+ XATTR_STDERR ("Cache hits: %u\n", cache_hit);
50+ XATTR_STDERR ("Cache miss: %u\n", cache_miss);
51 }
52
53 /* Get value for named xattr from file at path.
54@@ -284,6 +299,58 @@ out:
55 return ret;
56 }
57
58+static bool
59+xattr_entry_isequal (struct ext2_ext_attr_header *header_a,
60+ struct ext2_ext_attr_entry *entry_a,
61+ struct ext2_ext_attr_header *header_b,
62+ struct ext2_ext_attr_entry *entry_b)
63+{
64+ if (entry_a->e_hash == entry_b->e_hash ||
65+ entry_a->e_name_index == entry_b->e_name_index ||
66+ entry_a->e_name_len == entry_b->e_name_len ||
67+ entry_a->e_value_size == entry_b->e_value_size)
68+ {
69+ /* If entry header data all matches we check name and value */
70+ if (memcmp (EXT2_EXT_ATTR_NAME(entry_a),
71+ EXT2_EXT_ATTR_NAME(entry_b),
72+ MIN (entry_a->e_name_len, entry_b->e_name_len)) != 0)
73+ return false;
74+ if (memcmp (VALUE(header_a, entry_a),
75+ VALUE(header_b, entry_b),
76+ MIN(entry_a->e_value_size, entry_b->e_value_size)) != 0)
77+ return false;
78+ return true;
79+ } else {
80+ return false;
81+ }
82+}
83+
84+static bool
85+xattr_block_isequal (struct ext2_ext_attr_header *header_a,
86+ struct ext2_ext_attr_header *header_b)
87+{
88+ struct ext2_ext_attr_entry *entry_a = NULL, *entry_b = NULL;
89+
90+ XATTR_STDERR ("equality test: xattr blocks at 0x%x and 0x%x\n", header_a, header_b);
91+ for (entry_a = FIRST_ENTRY(header_a), entry_b = FIRST_ENTRY(header_b);
92+ !EXT2_EXT_IS_LAST_ENTRY(entry_a) && !EXT2_EXT_IS_LAST_ENTRY(entry_b);
93+ entry_a = EXT2_EXT_ATTR_NEXT(entry_a), entry_b = EXT2_EXT_ATTR_NEXT(entry_b))
94+ {
95+ if (!xattr_entry_isequal (header_a, entry_a, header_b, entry_b)) {
96+ /* bail as soon as we find entries that don't match */
97+ XATTR_STDERR ("entries do not match\n");
98+ return false;
99+ }
100+ }
101+ /* Be sure we're on the last element from each block. */
102+ if (EXT2_EXT_IS_LAST_ENTRY(entry_a) && EXT2_EXT_IS_LAST_ENTRY(entry_b)) {
103+ XATTR_STDERR ("entries match\n");
104+ return true;
105+ } else {
106+ return false;
107+ }
108+}
109+
110 /* Add an xattr node to the list specified by head. This function will update
111 * head as necessary. It will return a pointer to the xattr_node_t added to the
112 * list. In the event that an identical xattr block is already on the list this
113@@ -292,7 +359,31 @@ out:
114 static xattr_node_t*
115 xattr_add_block (xattr_node_t **head, xattr_node_t *node)
116 {
117+ xattr_node_t *curr_node = NULL, *prev_node = NULL;
118+
119 XATTR_STDERR ("Adding xattr to the the node list.\n");
120+ if (node == NULL)
121+ return NULL;
122+ /* list is empty, node becomes first node */
123+ if (!(*head)) {
124+ *head = node;
125+ return node;
126+ }
127+ for (curr_node = *head; curr_node != NULL; curr_node = curr_node->next)
128+ {
129+ /* cache hit */
130+ if (xattr_block_isequal (node->header, curr_node->header)) {
131+ ++cache_hit;
132+ return curr_node;
133+ }
134+ /* end of list */
135+ if (curr_node->next == NULL) {
136+ ++cache_miss;
137+ curr_node->next = node;
138+ return node;
139+ }
140+ }
141+ /* should never reach: assert? */
142 return node;
143 }
144
145@@ -302,8 +393,27 @@ xattr_add_block (xattr_node_t **head, xa
146 static xattr_node_t*
147 xattr_rm_block (xattr_node_t **head, xattr_node_t *node)
148 {
149+ xattr_node_t *curr_node = NULL, *prev_node = NULL;
150+
151 XATTR_STDERR ("Removing xattr from the node list.\n");
152- return node;
153+ /* no list, or empty list: nothing to search though */
154+ if (!head || !(*head))
155+ return NULL;
156+
157+ for (prev_node = NULL, curr_node = *head;
158+ curr_node != NULL;
159+ prev_node = curr_node, curr_node = curr_node->next)
160+ {
161+ if (node == curr_node) {
162+ if (prev_node)
163+ prev_node->next = curr_node->next;
164+ else
165+ *head = curr_node->next;
166+ return curr_node;
167+ }
168+ }
169+ /* reached end of list, no match */
170+ return NULL;
171 }
172
173 /* This is the entry point to the xattr module. This function copies the xattrs
174@@ -386,6 +496,7 @@ set_inode_xattr (ext2_filsys fs, ext2_in
175 }
176 if (ret = ext2fs_write_inode (fs, ino, &inode))
177 com_err(__func__, ret, "ext2fs_write_inode: returned %d", ret);
178+ return ret;
179 out:
180 xattr_free_node (node);
181 return ret;
diff --git a/recipes-devtools/e2fsprogs/e2fsprogs_1.42.9.bbappend b/recipes-devtools/e2fsprogs/e2fsprogs_1.42.9.bbappend
index 0705ec4..d8de9da 100644
--- a/recipes-devtools/e2fsprogs/e2fsprogs_1.42.9.bbappend
+++ b/recipes-devtools/e2fsprogs/e2fsprogs_1.42.9.bbappend
@@ -6,4 +6,5 @@ SRC_URI += " \
6 file://lib-ext2fs-ext2_ext_attr.h-add-xattr-index.patch \ 6 file://lib-ext2fs-ext2_ext_attr.h-add-xattr-index.patch \
7 file://misc-xattr-create-xattr-block.patch \ 7 file://misc-xattr-create-xattr-block.patch \
8 file://misc-xattr-create-xattr-block-node.patch \ 8 file://misc-xattr-create-xattr-block-node.patch \
9 file://misc-xattr-create-xattr-cache.patch \
9" 10"