Skip to content

Commit c62fb26

Browse files
mmarcinidledford
authored andcommitted
IB/hfi1,IB/qib: Fix qp_stats sleep with rcu read lock held
The qp init function does a kzalloc() while holding the RCU lock that encounters the following warning with a debug kernel when a cat of the qp_stats is done: [ 231.723948] rcu_scheduler_active = 1, debug_locks = 0 [ 231.731939] 3 locks held by cat/11355: [ 231.736492] #0: (debugfs_srcu){......}, at: [<ffffffff813001a5>] debugfs_use_file_start+0x5/0x90 [ 231.746955] rib#1: (&p->lock){+.+.+.}, at: [<ffffffff81289a6c>] seq_read+0x4c/0x3c0 [ 231.755873] rib#2: (rcu_read_lock){......}, at: [<ffffffffa0a0c535>] _qp_stats_seq_start+0x5/0xd0 [hfi1] [ 231.766862] The init functions do an implicit next which requires the rcu read lock before the kzalloc(). Fix for both drivers is to change the scope of the init function to only do the allocation and the initialization of the just allocated iter. The implict next is moved back into the respective start functions to fix the issue. Signed-off-by: Ira Weiny <[email protected]> Signed-off-by: Mike Marciniszyn <[email protected]> CC: <[email protected]> # 4.6.x- Reviewed-by: Leon Romanovsky <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent abb658e commit c62fb26

File tree

4 files changed

+18
-16
lines changed

4 files changed

+18
-16
lines changed

drivers/infiniband/hw/hfi1/debugfs.c

+9-5
Original file line numberDiff line numberDiff line change
@@ -223,28 +223,32 @@ DEBUGFS_SEQ_FILE_OPEN(ctx_stats)
223223
DEBUGFS_FILE_OPS(ctx_stats);
224224

225225
static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos)
226-
__acquires(RCU)
226+
__acquires(RCU)
227227
{
228228
struct qp_iter *iter;
229229
loff_t n = *pos;
230230

231-
rcu_read_lock();
232231
iter = qp_iter_init(s->private);
232+
233+
/* stop calls rcu_read_unlock */
234+
rcu_read_lock();
235+
233236
if (!iter)
234237
return NULL;
235238

236-
while (n--) {
239+
do {
237240
if (qp_iter_next(iter)) {
238241
kfree(iter);
239242
return NULL;
240243
}
241-
}
244+
} while (n--);
242245

243246
return iter;
244247
}
245248

246249
static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
247250
loff_t *pos)
251+
__must_hold(RCU)
248252
{
249253
struct qp_iter *iter = iter_ptr;
250254

@@ -259,7 +263,7 @@ static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
259263
}
260264

261265
static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr)
262-
__releases(RCU)
266+
__releases(RCU)
263267
{
264268
rcu_read_unlock();
265269
}

drivers/infiniband/hw/hfi1/qp.c

-4
Original file line numberDiff line numberDiff line change
@@ -656,10 +656,6 @@ struct qp_iter *qp_iter_init(struct hfi1_ibdev *dev)
656656

657657
iter->dev = dev;
658658
iter->specials = dev->rdi.ibdev.phys_port_cnt * 2;
659-
if (qp_iter_next(iter)) {
660-
kfree(iter);
661-
return NULL;
662-
}
663659

664660
return iter;
665661
}

drivers/infiniband/hw/qib/qib_debugfs.c

+9-3
Original file line numberDiff line numberDiff line change
@@ -189,27 +189,32 @@ static int _ctx_stats_seq_show(struct seq_file *s, void *v)
189189
DEBUGFS_FILE(ctx_stats)
190190

191191
static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos)
192+
__acquires(RCU)
192193
{
193194
struct qib_qp_iter *iter;
194195
loff_t n = *pos;
195196

196-
rcu_read_lock();
197197
iter = qib_qp_iter_init(s->private);
198+
199+
/* stop calls rcu_read_unlock */
200+
rcu_read_lock();
201+
198202
if (!iter)
199203
return NULL;
200204

201-
while (n--) {
205+
do {
202206
if (qib_qp_iter_next(iter)) {
203207
kfree(iter);
204208
return NULL;
205209
}
206-
}
210+
} while (n--);
207211

208212
return iter;
209213
}
210214

211215
static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
212216
loff_t *pos)
217+
__must_hold(RCU)
213218
{
214219
struct qib_qp_iter *iter = iter_ptr;
215220

@@ -224,6 +229,7 @@ static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
224229
}
225230

226231
static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr)
232+
__releases(RCU)
227233
{
228234
rcu_read_unlock();
229235
}

drivers/infiniband/hw/qib/qib_qp.c

-4
Original file line numberDiff line numberDiff line change
@@ -573,10 +573,6 @@ struct qib_qp_iter *qib_qp_iter_init(struct qib_ibdev *dev)
573573
return NULL;
574574

575575
iter->dev = dev;
576-
if (qib_qp_iter_next(iter)) {
577-
kfree(iter);
578-
return NULL;
579-
}
580576

581577
return iter;
582578
}

0 commit comments

Comments
 (0)