Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'rework/write_atomic-unsafe' into for-linus

+48 -18
+16 -3
include/linux/console.h
··· 186 186 * printing callbacks must not be called. 187 187 * @CON_NBCON: Console can operate outside of the legacy style console_lock 188 188 * constraints. 189 + * @CON_NBCON_ATOMIC_UNSAFE: The write_atomic() callback is not safe and is 190 + * therefore only used by nbcon_atomic_flush_unsafe(). 189 191 */ 190 192 enum cons_flags { 191 193 CON_PRINTBUFFER = BIT(0), ··· 199 197 CON_EXTENDED = BIT(6), 200 198 CON_SUSPENDED = BIT(7), 201 199 CON_NBCON = BIT(8), 200 + CON_NBCON_ATOMIC_UNSAFE = BIT(9), 202 201 }; 203 202 204 203 /** ··· 611 608 extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt); 612 609 extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt); 613 610 extern void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt); 611 + extern bool nbcon_allow_unsafe_takeover(void); 614 612 extern bool nbcon_kdb_try_acquire(struct console *con, 615 613 struct nbcon_write_context *wctxt); 616 614 extern void nbcon_kdb_release(struct nbcon_write_context *wctxt); ··· 631 627 return false; 632 628 633 629 if (flags & CON_NBCON) { 634 - /* The write_atomic() callback is optional. */ 635 - if (use_atomic && !con->write_atomic) 636 - return false; 630 + if (use_atomic) { 631 + /* The write_atomic() callback is optional. */ 632 + if (!con->write_atomic) 633 + return false; 634 + 635 + /* 636 + * An unsafe write_atomic() callback is only usable 637 + * when unsafe takeovers are allowed. 638 + */ 639 + if ((flags & CON_NBCON_ATOMIC_UNSAFE) && !nbcon_allow_unsafe_takeover()) 640 + return false; 641 + } 637 642 638 643 /* 639 644 * For the !use_atomic case, @printk_kthreads_running is not
+32 -15
kernel/printk/nbcon.c
··· 1437 1437 return NBCON_PRIO_NORMAL; 1438 1438 } 1439 1439 1440 + /* 1441 + * Track if it is allowed to perform unsafe hostile takeovers of console 1442 + * ownership. When true, console drivers might perform unsafe actions while 1443 + * printing. It is externally available via nbcon_allow_unsafe_takeover(). 1444 + */ 1445 + static bool panic_nbcon_allow_unsafe_takeover; 1446 + 1447 + /** 1448 + * nbcon_allow_unsafe_takeover - Check if unsafe console takeovers are allowed 1449 + * 1450 + * Return: True, when it is permitted to perform unsafe console printing 1451 + * 1452 + * This is also used by console_is_usable() to determine if it is allowed to 1453 + * call write_atomic() callbacks flagged as unsafe (CON_NBCON_ATOMIC_UNSAFE). 1454 + */ 1455 + bool nbcon_allow_unsafe_takeover(void) 1456 + { 1457 + return panic_on_this_cpu() && panic_nbcon_allow_unsafe_takeover; 1458 + } 1459 + 1440 1460 /** 1441 1461 * nbcon_legacy_emit_next_record - Print one record for an nbcon console 1442 1462 * in legacy contexts ··· 1527 1507 * write_atomic() callback 1528 1508 * @con: The nbcon console to flush 1529 1509 * @stop_seq: Flush up until this record 1530 - * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers 1531 1510 * 1532 1511 * Return: 0 if @con was flushed up to @stop_seq Otherwise, error code on 1533 1512 * failure. ··· 1545 1526 * returned, it cannot be expected that the unfinalized record will become 1546 1527 * available. 1547 1528 */ 1548 - static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq, 1549 - bool allow_unsafe_takeover) 1529 + static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq) 1550 1530 { 1551 1531 struct nbcon_write_context wctxt = { }; 1552 1532 struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt); ··· 1554 1536 ctxt->console = con; 1555 1537 ctxt->spinwait_max_us = 2000; 1556 1538 ctxt->prio = nbcon_get_default_prio(); 1557 - ctxt->allow_unsafe_takeover = allow_unsafe_takeover; 1539 + ctxt->allow_unsafe_takeover = nbcon_allow_unsafe_takeover(); 1558 1540 1559 1541 while (nbcon_seq_read(con) < stop_seq) { 1560 1542 if (!nbcon_context_try_acquire(ctxt, false)) ··· 1586 1568 * write_atomic() callback 1587 1569 * @con: The nbcon console to flush 1588 1570 * @stop_seq: Flush up until this record 1589 - * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers 1590 1571 * 1591 1572 * This will stop flushing before @stop_seq if another context has ownership. 1592 1573 * That context is then responsible for the flushing. Likewise, if new records 1593 1574 * are added while this context was flushing and there is no other context 1594 1575 * to handle the printing, this context must also flush those records. 1595 1576 */ 1596 - static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq, 1597 - bool allow_unsafe_takeover) 1577 + static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq) 1598 1578 { 1599 1579 struct console_flush_type ft; 1600 1580 unsigned long flags; ··· 1607 1591 */ 1608 1592 local_irq_save(flags); 1609 1593 1610 - err = __nbcon_atomic_flush_pending_con(con, stop_seq, allow_unsafe_takeover); 1594 + err = __nbcon_atomic_flush_pending_con(con, stop_seq); 1611 1595 1612 1596 local_irq_restore(flags); 1613 1597 ··· 1639 1623 * __nbcon_atomic_flush_pending - Flush all nbcon consoles using their 1640 1624 * write_atomic() callback 1641 1625 * @stop_seq: Flush up until this record 1642 - * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers 1643 1626 */ 1644 - static void __nbcon_atomic_flush_pending(u64 stop_seq, bool allow_unsafe_takeover) 1627 + static void __nbcon_atomic_flush_pending(u64 stop_seq) 1645 1628 { 1646 1629 struct console *con; 1647 1630 int cookie; ··· 1658 1643 if (nbcon_seq_read(con) >= stop_seq) 1659 1644 continue; 1660 1645 1661 - nbcon_atomic_flush_pending_con(con, stop_seq, allow_unsafe_takeover); 1646 + nbcon_atomic_flush_pending_con(con, stop_seq); 1662 1647 } 1663 1648 console_srcu_read_unlock(cookie); 1664 1649 } ··· 1674 1659 */ 1675 1660 void nbcon_atomic_flush_pending(void) 1676 1661 { 1677 - __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb), false); 1662 + __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb)); 1678 1663 } 1679 1664 1680 1665 /** ··· 1686 1671 */ 1687 1672 void nbcon_atomic_flush_unsafe(void) 1688 1673 { 1689 - __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb), true); 1674 + panic_nbcon_allow_unsafe_takeover = true; 1675 + __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb)); 1676 + panic_nbcon_allow_unsafe_takeover = false; 1690 1677 } 1691 1678 1692 1679 /** ··· 1911 1894 * using the legacy loop. 1912 1895 */ 1913 1896 if (ft.nbcon_atomic) { 1914 - __nbcon_atomic_flush_pending_con(con, prb_next_reserve_seq(prb), false); 1897 + __nbcon_atomic_flush_pending_con(con, prb_next_reserve_seq(prb)); 1915 1898 } else if (ft.legacy_direct) { 1916 1899 if (console_trylock()) 1917 1900 console_unlock(); ··· 1981 1964 * The console was locked only when the write_atomic() callback 1982 1965 * was usable. 1983 1966 */ 1984 - __nbcon_atomic_flush_pending_con(ctxt->console, prb_next_reserve_seq(prb), false); 1967 + __nbcon_atomic_flush_pending_con(ctxt->console, prb_next_reserve_seq(prb)); 1985 1968 }