struct hd_struct *part;
char name_buf[BDEVNAME_SIZE];
char devt_buf[BDEVT_SIZE];
- u8 uuid[PARTITION_META_INFO_UUIDLTH * 2 + 1];
+ char uuid_buf[PARTITION_META_INFO_UUIDLTH * 2 + 5];
/*
* Don't show empty devices or things that have been
while ((part = disk_part_iter_next(&piter))) {
bool is_part0 = part == &disk->part0;
- uuid[0] = 0;
+ uuid_buf[0] = '\0';
if (part->info)
- part_unpack_uuid(part->info->uuid, uuid);
+ snprintf(uuid_buf, sizeof(uuid_buf), "%pU",
+ part->info->uuid);
printk("%s%s %10llu %s %s", is_part0 ? "" : " ",
bdevt_str(part_devt(part), devt_buf),
(unsigned long long)part->nr_sects >> 1,
- disk_name(disk, part->partno, name_buf), uuid);
+ disk_name(disk, part->partno, name_buf),
+ uuid_buf);
if (is_part0) {
if (disk->driverfs_dev != NULL &&
disk->driverfs_dev->driver != NULL)
mutex_unlock(&ev->block_mutex);
}
+/**
+ * CONTEXT: ev->lock should be held when calling this function
+ */
static void __disk_unblock_events(struct gendisk *disk, bool check_now)
{
struct disk_events *ev = disk->ev;
unsigned long intv;
- unsigned long flags;
-
- spin_lock_irqsave(&ev->lock, flags);
if (WARN_ON_ONCE(ev->block <= 0))
- goto out_unlock;
+ return;
if (--ev->block)
- goto out_unlock;
+ return;
/*
* Not exactly a latency critical operation, set poll timer
queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
else if (intv)
queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, intv);
-out_unlock:
- spin_unlock_irqrestore(&ev->lock, flags);
}
/**
*/
void disk_unblock_events(struct gendisk *disk)
{
- if (disk->ev)
+ struct disk_events *ev = disk->ev;
+ unsigned long flags;
+
+ if (ev) {
+ spin_lock_irqsave(&ev->lock, flags);
__disk_unblock_events(disk, false);
+ spin_unlock_irqrestore(&ev->lock, flags);
+ }
}
/**
/* uncondtionally schedule event check and wait for it to finish */
disk_block_events(disk);
- queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
+ /* We need to put the work on system_nrt_wq here since there is a
+ * deadlock that happens while probing a usb device while suspending. If
+ * we put work on a freezable worqueue here, a usb probe will wait here
+ * until the workqueue is unfrozen during suspend. Since suspend waits
+ * on all probes to complete, we have a deadlock
+ */
+ queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
flush_delayed_work(&ev->dwork);
+ spin_lock_irq(&ev->lock);
__disk_unblock_events(disk, false);
/* then, fetch and clear pending events */
- spin_lock_irq(&ev->lock);
WARN_ON_ONCE(ev->clearing & mask); /* cleared by workfn */
pending = ev->pending & mask;
ev->pending &= ~mask;
disk_block_events(disk);
disk->ev->poll_msecs = intv;
+ spin_lock_irq(&disk->ev->lock);
__disk_unblock_events(disk, true);
+ spin_unlock_irq(&disk->ev->lock);
return count;
}
* Block count is initialized to 1 and the following initial
* unblock kicks it into action.
*/
+ spin_lock_irq(&disk->ev->lock);
__disk_unblock_events(disk, true);
+ spin_unlock_irq(&disk->ev->lock);
}
static void disk_del_events(struct gendisk *disk)