Skip to contentSkip to conversation

aoe: convert aoeblk to blk-mq

bug report Dan Carpenter 1 participant 1 message Jun 30, 2021 Block layer

lore
Share & tools
lore
#0 lore raw

Hello Jens Axboe,

The patch 3582dd291788: "aoe: convert aoeblk to blk-mq" from Oct 12, 2018, leads to the following static checker warning:

	block/blk-mq.c:151 blk_mq_freeze_queue_wait()
	warn: sleeping in atomic context

The problem is that aoedev_downdev() can sleep now.

There are two callers of aoedev_downdev() and originally they were both called under spinlock. One was fixed in commit 430380b4637a ("block: aoe: Fix kernel crash due to atomic sleep when exiting") but the other is still buggy.

drivers/block/aoe/aoecmd.c

   726  static void
   727  rexmit_timer(struct timer_list *timer)
   728  {
   729          struct aoedev *d;
   730          struct aoetgt *t;
   731          struct aoeif *ifp;
   732          struct frame *f;
   733          struct list_head *head, *pos, *nx;
   734          LIST_HEAD(flist);
   735          register long timeout;
   736          ulong flags, n;
   737          int i;
   738          int utgts;      /* number of aoetgt descriptors (not slots) */
   739          int since;
   740  
   741          d = from_timer(d, timer, timer);
   742  
   743          spin_lock_irqsave(&d->lock, flags);
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

spin lock held.

744
745 /* timeout based on observed timings and variations */
746 timeout = rto(d);
747
748 utgts = count_targets(d, NULL);
749
750 if (d->flags & DEVFL_TKILL) {
751 spin_unlock_irqrestore(&d->lock, flags);
752 return;
753 }
754
755 /* collect all frames to rexmit into flist */
756 for (i = 0; i < NFACTIVE; i++) {
757 head = &d->factive[i];
758 list_for_each_safe(pos, nx, head) {
759 f = list_entry(pos, struct frame, head);
760 if (tsince_hr(f) < timeout)
761 break; /* end of expired frames */
762 /* move to flist for later processing */
763 list_move_tail(pos, &flist);
764 }
765 }
766
767 /* process expired frames */
768 while (!list_empty(&flist)) {

   769                  pos = flist.next;
   770                  f = list_entry(pos, struct frame, head);
   771                  since = tsince_hr(f);
   772                  n = f->waited_total + since;
   773                  n /= USEC_PER_SEC;
   774                  if (aoe_deadsecs
   775                  && n > aoe_deadsecs
   776                  && !(f->flags & FFL_PROBE)) {
   777                          /* Waited too long.  Device failure.
   778                           * Hang all frames on first hash bucket for downdev
   779                           * to clean up.
   780                           */
   781                          list_splice(&flist, &d->factive[0]);
   782                          aoedev_downdev(d);
                                ^^^^^^^^^^^^^^^^^

Sleeps in atomic if we call blk_mq_freeze_queue().

   783                          goto out;
   784                  }
   785  
   786                  t = f->t;
   787                  n = f->waited + since;
   788                  n /= USEC_PER_SEC;
   789                  if (aoe_deadsecs && utgts > 0
   790                  && (n > aoe_deadsecs / utgts || n > HARD_SCORN_SECS))
   791                          scorn(t); /* avoid this target */
   792

regards,
dan carpenter