]> git.pld-linux.org Git - packages/xfsprogs.git/blob - xfsprogs-repair-nofutexhang.patch
- up to 3.1.7; po patch merged upstream; add patches: 1) avoid hanging on futexes...
[packages/xfsprogs.git] / xfsprogs-repair-nofutexhang.patch
1
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.
8
9 Signed-off-by: Christoph Hellwig <hch@lst.de>
10
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
15 @@ -25,7 +25,6 @@
16  #include "threads.h"
17  #include "err_protos.h"
18  
19 -static pthread_mutex_t ino_flist_lock;
20  extern avlnode_t       *avl_firstino(avlnode_t *root);
21  
22  /*
23 @@ -38,18 +37,6 @@
24   */
25  static avltree_desc_t  **inode_uncertain_tree_ptrs;
26  
27 -#define ALLOC_NUM_INOS         100
28 -
29 -/* free lists -- inode nodes and extent nodes */
30 -
31 -typedef struct ino_flist_s  {
32 -       ino_tree_node_t         *list;
33 -       ino_tree_node_t         *last;
34 -       long long               cnt;
35 -} ino_flist_t;
36 -
37 -static ino_flist_t ino_flist;  /* free list must be initialized before use */
38 -
39  /* memory optimised nlink counting for all inodes */
40  
41  static void nlink_grow_8_to_16(ino_tree_node_t *irec);
42 @@ -238,102 +225,63 @@
43  }
44  
45  /*
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
49   * is one list per ag.
50   */
51  
52  /*
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
56   *
57   * IMPORTANT:  all inodes (inode records) start off as free and
58   *             unconfirmed.
59   */
60 -/* ARGSUSED */
61 -static ino_tree_node_t *
62 -mk_ino_tree_nodes(
63 +static struct ino_tree_node *
64 +alloc_ino_node(
65         xfs_agino_t             starting_ino)
66  {
67 -       int                     i;
68 -       ino_tree_node_t         *ino_rec;
69 -       avlnode_t               *node;
70 -
71 -       pthread_mutex_lock(&ino_flist_lock);
72 -       if (ino_flist.cnt == 0)  {
73 -               ASSERT(ino_flist.list == NULL);
74 -
75 -               if ((ino_rec = malloc(sizeof(ino_tree_node_t[ALLOC_NUM_INOS])))
76 -                                       == NULL)
77 -                       do_error(_("inode map malloc failed\n"));
78 -
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;
83 -                       ino_flist.cnt++;
84 -                       ino_rec++;
85 -               }
86 -       }
87 +       struct ino_tree_node    *irec;
88  
89 -       ASSERT(ino_flist.list != NULL);
90 -
91 -       ino_rec = ino_flist.list;
92 -       ino_flist.list = (ino_tree_node_t *) ino_rec->avl_node.avl_nextino;
93 -       ino_flist.cnt--;
94 -       node = &ino_rec->avl_node;
95 -       node->avl_nextino = node->avl_forw = node->avl_back = NULL;
96 -       pthread_mutex_unlock(&ino_flist_lock);
97 -
98 -       /* initialize node */
99 -
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));
109 +       if (!irec)
110 +               do_error(_("inode map malloc failed\n"));
111 +
112 +       irec->avl_node.avl_nextino = NULL;
113 +       irec->avl_node.avl_forw = NULL;
114 +       irec->avl_node.avl_back = NULL;
115 +
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"));
125 -
126 -       return(ino_rec);
127 +       return irec;
128  }
129  
130 -/*
131 - * return inode record to free list, will be initialized when
132 - * it gets pulled off list
133 - */
134  static void
135 -free_ino_tree_node(ino_tree_node_t *ino_rec)
136 +free_ino_tree_node(
137 +       struct ino_tree_node    *irec)
138  {
139 -       ino_rec->avl_node.avl_nextino = NULL;
140 -       ino_rec->avl_node.avl_forw = NULL;
141 -       ino_rec->avl_node.avl_back = NULL;
142 -
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;
147 -       } else  {
148 -               ASSERT(ino_flist.cnt == 0);
149 -               ino_rec->avl_node.avl_nextino = NULL;
150 -       }
151 +       irec->avl_node.avl_nextino = NULL;
152 +       irec->avl_node.avl_forw = NULL;
153 +       irec->avl_node.avl_back = NULL;
154  
155 -       ino_flist.list = ino_rec;
156 -       ino_flist.cnt++;
157 -
158 -       free(ino_rec->disk_nlinks);
159 -
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);
168                 }
169 -               free(ino_rec->ino_un.ex_data);
170 +               free(irec->ino_un.ex_data);
171  
172         }
173 -       pthread_mutex_unlock(&ino_flist_lock);
174 +
175 +       free(irec);
176  }
177  
178  /*
179 @@ -379,17 +327,15 @@
180          * check to see if record containing inode is already in the tree.
181          * if not, add it
182          */
183 -       if ((ino_rec = (ino_tree_node_t *)
184 -                       avl_findrange(inode_uncertain_tree_ptrs[agno],
185 -                               s_ino)) == NULL)  {
186 -               ino_rec = mk_ino_tree_nodes(s_ino);
187 -               ino_rec->ino_startnum = s_ino;
188 -
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"));
193 -               }
194 +       ino_rec = (ino_tree_node_t *)
195 +               avl_findrange(inode_uncertain_tree_ptrs[agno], s_ino);
196 +       if (!ino_rec) {
197 +               ino_rec = alloc_ino_node(s_ino);
198 +
199 +               if (!avl_insert(inode_uncertain_tree_ptrs[agno],
200 +                               &ino_rec->avl_node))
201 +                       do_error(
202 +       _("add_aginode_uncertain - duplicate inode range\n"));
203         }
204  
205         if (free)
206 @@ -454,43 +400,38 @@
207  
208  
209  /*
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
214   */
215 +
216  /*
217 - * set up an inode tree record for a group of inodes that will
218 - * include the requested inode.
219 - *
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
223 + * requested inode.
224   *
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
229   *
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
237 - * don't.
238 - */
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.
248 + */
249 +static struct ino_tree_node *
250 +add_inode(
251 +       struct xfs_mount        *mp,
252 +       xfs_agnumber_t          agno,
253 +       xfs_agino_t             agino)
254  {
255 -       ino_tree_node_t *ino_rec;
256 -
257 -       /* no record exists, make some and put them into the tree */
258 -
259 -       ino_rec = mk_ino_tree_nodes(ino);
260 -       ino_rec->ino_startnum = ino;
261 +       struct ino_tree_node    *irec;
262  
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"));
268 -       }
269 -
270 -       return(ino_rec);
271 +       return irec;
272  }
273  
274  /*
275 @@ -816,7 +757,6 @@
276         int i;
277         int agcount = mp->m_sb.sb_agcount;
278  
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"));
283 @@ -839,9 +779,6 @@
284                 avl_init_tree(inode_uncertain_tree_ptrs[i], &avl_ino_tree_ops);
285         }
286  
287 -       ino_flist.cnt = 0;
288 -       ino_flist.list = NULL;
289 -
290         if ((last_rec = malloc(sizeof(ino_tree_node_t *) * agcount)) == NULL)
291                 do_error(_("couldn't malloc uncertain inode cache area\n"));
292  
293
This page took 0.049028 seconds and 3 git commands to generate.