2 Instead of allocating inode records in chunks and keeping a freelist of them
3 which never gets released to the system memory allocator use plain malloc
4 and free for them. The freelist just means adding a global lock instead
5 of relying on malloc and free which could be implemented lockless, and the
6 freelist is almost completely worthless as we are done allocating new
7 inode records once we start freeing them in major quantities.
9 Signed-off-by: Christoph Hellwig <hch@lst.de>
11 Index: xfsprogs-dev/repair/incore_ino.c
12 ===================================================================
13 --- xfsprogs-dev.orig/repair/incore_ino.c 2011-11-09 18:52:15.041861085 +0000
14 +++ xfsprogs-dev/repair/incore_ino.c 2011-11-09 19:36:39.389806408 +0000
17 #include "err_protos.h"
19 -static pthread_mutex_t ino_flist_lock;
20 extern avlnode_t *avl_firstino(avlnode_t *root);
25 static avltree_desc_t **inode_uncertain_tree_ptrs;
27 -#define ALLOC_NUM_INOS 100
29 -/* free lists -- inode nodes and extent nodes */
31 -typedef struct ino_flist_s {
32 - ino_tree_node_t *list;
33 - ino_tree_node_t *last;
37 -static ino_flist_t ino_flist; /* free list must be initialized before use */
39 /* memory optimised nlink counting for all inodes */
41 static void nlink_grow_8_to_16(ino_tree_node_t *irec);
42 @@ -238,102 +225,63 @@
46 - * next is the uncertain inode list -- a sorted (in ascending order)
47 + * Next is the uncertain inode list -- a sorted (in ascending order)
48 * list of inode records sorted on the starting inode number. There
53 - * common code for creating inode records for use by trees and lists.
54 + * Common code for creating inode records for use by trees and lists.
55 * called only from add_inodes and add_inodes_uncertain
57 * IMPORTANT: all inodes (inode records) start off as free and
61 -static ino_tree_node_t *
63 +static struct ino_tree_node *
65 xfs_agino_t starting_ino)
68 - ino_tree_node_t *ino_rec;
71 - pthread_mutex_lock(&ino_flist_lock);
72 - if (ino_flist.cnt == 0) {
73 - ASSERT(ino_flist.list == NULL);
75 - if ((ino_rec = malloc(sizeof(ino_tree_node_t[ALLOC_NUM_INOS])))
77 - do_error(_("inode map malloc failed\n"));
79 - for (i = 0; i < ALLOC_NUM_INOS; i++) {
80 - ino_rec->avl_node.avl_nextino =
81 - (avlnode_t *) ino_flist.list;
82 - ino_flist.list = ino_rec;
87 + struct ino_tree_node *irec;
89 - ASSERT(ino_flist.list != NULL);
91 - ino_rec = ino_flist.list;
92 - ino_flist.list = (ino_tree_node_t *) ino_rec->avl_node.avl_nextino;
94 - node = &ino_rec->avl_node;
95 - node->avl_nextino = node->avl_forw = node->avl_back = NULL;
96 - pthread_mutex_unlock(&ino_flist_lock);
98 - /* initialize node */
100 - ino_rec->ino_startnum = 0;
101 - ino_rec->ino_confirmed = 0;
102 - ino_rec->ino_isa_dir = 0;
103 - ino_rec->ir_free = (xfs_inofree_t) - 1;
104 - ino_rec->ino_un.ex_data = NULL;
105 - ino_rec->nlinkops = &nlinkops[0];
106 - ino_rec->disk_nlinks = calloc(1, nlinkops[0].nlink_size);
107 - if (ino_rec->disk_nlinks == NULL)
108 + irec = malloc(sizeof(*irec));
110 + do_error(_("inode map malloc failed\n"));
112 + irec->avl_node.avl_nextino = NULL;
113 + irec->avl_node.avl_forw = NULL;
114 + irec->avl_node.avl_back = NULL;
116 + irec->ino_startnum = starting_ino;
117 + irec->ino_confirmed = 0;
118 + irec->ino_isa_dir = 0;
119 + irec->ir_free = (xfs_inofree_t) - 1;
120 + irec->ino_un.ex_data = NULL;
121 + irec->nlinkops = &nlinkops[0];
122 + irec->disk_nlinks = calloc(1, nlinkops[0].nlink_size);
123 + if (!irec->disk_nlinks)
124 do_error(_("could not allocate nlink array\n"));
131 - * return inode record to free list, will be initialized when
132 - * it gets pulled off list
135 -free_ino_tree_node(ino_tree_node_t *ino_rec)
137 + struct ino_tree_node *irec)
139 - ino_rec->avl_node.avl_nextino = NULL;
140 - ino_rec->avl_node.avl_forw = NULL;
141 - ino_rec->avl_node.avl_back = NULL;
143 - pthread_mutex_lock(&ino_flist_lock);
144 - if (ino_flist.list != NULL) {
145 - ASSERT(ino_flist.cnt > 0);
146 - ino_rec->avl_node.avl_nextino = (avlnode_t *) ino_flist.list;
148 - ASSERT(ino_flist.cnt == 0);
149 - ino_rec->avl_node.avl_nextino = NULL;
151 + irec->avl_node.avl_nextino = NULL;
152 + irec->avl_node.avl_forw = NULL;
153 + irec->avl_node.avl_back = NULL;
155 - ino_flist.list = ino_rec;
158 - free(ino_rec->disk_nlinks);
160 - if (ino_rec->ino_un.ex_data != NULL) {
161 + free(irec->disk_nlinks);
162 + if (irec->ino_un.ex_data != NULL) {
163 if (full_ino_ex_data) {
164 - free(ino_rec->ino_un.ex_data->parents);
165 - free(ino_rec->ino_un.ex_data->counted_nlinks);
166 + free(irec->ino_un.ex_data->parents);
167 + free(irec->ino_un.ex_data->counted_nlinks);
169 - free(ino_rec->ino_un.ex_data);
170 + free(irec->ino_un.ex_data);
173 - pthread_mutex_unlock(&ino_flist_lock);
179 @@ -379,17 +327,15 @@
180 * check to see if record containing inode is already in the tree.
183 - if ((ino_rec = (ino_tree_node_t *)
184 - avl_findrange(inode_uncertain_tree_ptrs[agno],
186 - ino_rec = mk_ino_tree_nodes(s_ino);
187 - ino_rec->ino_startnum = s_ino;
189 - if (avl_insert(inode_uncertain_tree_ptrs[agno],
190 - (avlnode_t *) ino_rec) == NULL) {
191 - do_error(_("add_aginode_uncertain - "
192 - "duplicate inode range\n"));
194 + ino_rec = (ino_tree_node_t *)
195 + avl_findrange(inode_uncertain_tree_ptrs[agno], s_ino);
197 + ino_rec = alloc_ino_node(s_ino);
199 + if (!avl_insert(inode_uncertain_tree_ptrs[agno],
200 + &ino_rec->avl_node))
202 + _("add_aginode_uncertain - duplicate inode range\n"));
206 @@ -454,43 +400,38 @@
210 - * next comes the inode trees. One per ag. AVL trees
211 - * of inode records, each inode record tracking 64 inodes
212 + * Next comes the inode trees. One per AG, AVL trees of inode records, each
213 + * inode record tracking 64 inodes
217 - * set up an inode tree record for a group of inodes that will
218 - * include the requested inode.
220 - * does NOT error-check for duplicate records. Caller is
221 - * responsible for checking that.
222 + * Set up an inode tree record for a group of inodes that will include the
225 - * ino must be the start of an XFS_INODES_PER_CHUNK (64) inode chunk
226 + * This does NOT do error-check for duplicate records. The caller is
227 + * responsible for checking that. Ino must be the start of an
228 + * XFS_INODES_PER_CHUNK (64) inode chunk
230 - * Each inode resides in a 64-inode chunk which can be part
231 - * one or more chunks (MAX(64, inodes-per-block). The fs allocates
232 - * in chunks (as opposed to 1 chunk) when a block can hold more than
233 - * one chunk (inodes per block > 64). Allocating in one chunk pieces
234 - * causes us problems when it takes more than one fs block to contain
235 - * an inode chunk because the chunks can start on *any* block boundary.
236 - * So we assume that the caller has a clue because at this level, we
239 -static ino_tree_node_t *
240 -add_inode(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t ino)
241 + * Each inode resides in a 64-inode chunk which can be part one or more chunks
242 + * (MAX(64, inodes-per-block). The fs allocates in chunks (as opposed to 1
243 + * chunk) when a block can hold more than one chunk (inodes per block > 64).
244 + * Allocating in one chunk pieces causes us problems when it takes more than
245 + * one fs block to contain an inode chunk because the chunks can start on
246 + * *any* block boundary. So we assume that the caller has a clue because at
247 + * this level, we don't.
249 +static struct ino_tree_node *
251 + struct xfs_mount *mp,
252 + xfs_agnumber_t agno,
255 - ino_tree_node_t *ino_rec;
257 - /* no record exists, make some and put them into the tree */
259 - ino_rec = mk_ino_tree_nodes(ino);
260 - ino_rec->ino_startnum = ino;
261 + struct ino_tree_node *irec;
263 - if (avl_insert(inode_tree_ptrs[agno],
264 - (avlnode_t *) ino_rec) == NULL) {
265 + irec = alloc_ino_node(agino);
266 + if (!avl_insert(inode_tree_ptrs[agno], &irec->avl_node))
267 do_warn(_("add_inode - duplicate inode range\n"));
277 int agcount = mp->m_sb.sb_agcount;
279 - pthread_mutex_init(&ino_flist_lock, NULL);
280 if ((inode_tree_ptrs = malloc(agcount *
281 sizeof(avltree_desc_t *))) == NULL)
282 do_error(_("couldn't malloc inode tree descriptor table\n"));
284 avl_init_tree(inode_uncertain_tree_ptrs[i], &avl_ino_tree_ops);
288 - ino_flist.list = NULL;
290 if ((last_rec = malloc(sizeof(ino_tree_node_t *) * agcount)) == NULL)
291 do_error(_("couldn't malloc uncertain inode cache area\n"));