Commit 7aae6dd80e265aa9402ed507caaff4a5dba55069

Authored by Tejun Heo
Committed by Greg Kroah-Hartman
1 parent dc0afa8388

idr: fix obscure bug in allocation path

In sub_alloc(), when bitmap search fails, it goes up one level to
continue search.  This is done by updating the id cursor and searching
the upper level again.  If the cursor was at the end of the upper
level, we need to go further than that.

This wasn't implemented and when that happens the part of the cursor
which indexes into the upper level wraps and sub_alloc() ends up
searching the wrong bitmap.  It allocates id which doesn't match the
actual slot.

This patch fixes this by restarting from the top if the search needs
to go higher than one level.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 1 changed file with 14 additions and 2 deletions Side-by-side Diff

... ... @@ -100,10 +100,11 @@
100 100 int n, m, sh;
101 101 struct idr_layer *p, *new;
102 102 struct idr_layer *pa[MAX_LEVEL];
103   - int l, id;
  103 + int l, id, oid;
104 104 long bm;
105 105  
106 106 id = *starting_id;
  107 + restart:
107 108 p = idp->top;
108 109 l = idp->layers;
109 110 pa[l--] = NULL;
110 111  
111 112  
... ... @@ -117,12 +118,23 @@
117 118 if (m == IDR_SIZE) {
118 119 /* no space available go back to previous layer. */
119 120 l++;
  121 + oid = id;
120 122 id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
  123 +
  124 + /* if already at the top layer, we need to grow */
121 125 if (!(p = pa[l])) {
122 126 *starting_id = id;
123 127 return -2;
124 128 }
125   - continue;
  129 +
  130 + /* If we need to go up one layer, continue the
  131 + * loop; otherwise, restart from the top.
  132 + */
  133 + sh = IDR_BITS * (l + 1);
  134 + if (oid >> sh == id >> sh)
  135 + continue;
  136 + else
  137 + goto restart;
126 138 }
127 139 if (m != n) {
128 140 sh = IDR_BITS*l;