public inbox for linux-wireless@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Ville Nummela <ville.nummela@kempower.com>,
	Johannes Berg <johannes.berg@intel.com>,
	Sasha Levin <sashal@kernel.org>,
	linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 7.0-5.10] wifi: rsi_91x_usb: do not pause rfkill polling when stopping mac80211
Date: Mon, 20 Apr 2026 09:16:48 -0400	[thread overview]
Message-ID: <20260420132314.1023554-14-sashal@kernel.org> (raw)
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Ville Nummela <ville.nummela@kempower.com>

[ Upstream commit 777d8ba5aada960c666f810d5d820ab55ebb64c3 ]

Removing rsi_91x USB adapter could cause rtnetlink to lock up.
When rsi_mac80211_stop is called, wiphy_lock is locked. Call to
wiphy_rfkill_stop_polling would wait until the work queue has
finished, but because the work queue waits for wiphy_lock, that
would never happen.

Moving the call to rsi_disconnect avoids the lock up.

Signed-off-by: Ville Nummela <ville.nummela@kempower.com>
Link: https://patch.msgid.link/20260318081912.87744-1-ville.nummela@kempower.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Now I have all the information needed. Let me compile the full analysis.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

### Step 1.1: Subject Line
- **Subsystem**: `wifi: rsi_91x_usb` (USB WiFi driver for RSI 91x
  chipset)
- **Action verb**: "do not pause" - indicates preventing incorrect
  behavior that causes a hang
- **Summary**: Stop rfkill polling from being paused during mac80211
  stop, which causes a deadlock

Record: [wifi: rsi_91x_usb] [do not pause] [Avoid deadlock by moving
rfkill stop polling out of mac80211 stop callback]

### Step 1.2: Tags
- **Signed-off-by**: Ville Nummela (author, external contributor from
  Kempower)
- **Link**: `https://patch.msgid.link/20260318081912.87744-1-
  ville.nummela@kempower.com`
- **Signed-off-by**: Johannes Berg (Intel, the wireless subsystem
  maintainer - applied the patch)
- No Fixes: tag (expected for manual review)
- No Reported-by, Tested-by, Reviewed-by

Record: Patch authored by external contributor (Ville Nummela), applied
by the wifi subsystem maintainer (Johannes Berg). No explicit stable
nomination.

### Step 1.3: Commit Body Analysis
The message describes a **deadlock**:
1. Removing the RSI USB adapter causes rtnetlink to lock up
2. `rsi_mac80211_stop` is called with `wiphy_lock` held
3. `wiphy_rfkill_stop_polling` calls `cancel_delayed_work_sync`, which
   waits for the rfkill poll work to finish
4. The rfkill poll work needs `wiphy_lock` to complete (via
   `guard(wiphy)` in `cfg80211_rfkill_poll`)
5. Classic ABBA deadlock: Thread A holds wiphy_lock, waits for work;
   work needs wiphy_lock

Record: Real deadlock. Trigger: USB adapter removal. Failure: system
hang (rtnetlink lockup).

### Step 1.4: Hidden Bug Fix Detection
This is explicitly a deadlock fix, not disguised. The description
clearly explains the locking inversion.

Record: Explicit deadlock fix, not hidden.

## PHASE 2: DIFF ANALYSIS

### Step 2.1: Inventory
- **Files changed**: 3
  - `drivers/net/wireless/rsi/rsi_91x_mac80211.c`: +16/-1 (new function
    + remove call)
  - `drivers/net/wireless/rsi/rsi_91x_usb.c`: +2/-0 (call new function)
  - `drivers/net/wireless/rsi/rsi_common.h`: +1/-0 (declare new
    function)
- **Total**: ~19 lines added, 1 removed
- **Functions modified**: `rsi_mac80211_stop()` (removed
  `wiphy_rfkill_stop_polling` call), `rsi_disconnect()` (added call to
  new function)
- **Functions added**: `rsi_mac80211_rfkill_exit()` (new helper)
- **Scope**: Small, single-subsystem, well-contained

### Step 2.2: Code Flow Change
1. **rsi_mac80211_stop()**: BEFORE: called `wiphy_rfkill_stop_polling()`
   while holding `common->mutex` (and with `wiphy_lock` held by caller).
   AFTER: no longer calls it.
2. **rsi_disconnect()** (USB): BEFORE: went straight to
   `rsi_mac80211_detach()`. AFTER: calls `rsi_mac80211_rfkill_exit()`
   first (without wiphy_lock held), then `rsi_mac80211_detach()`.
3. **New `rsi_mac80211_rfkill_exit()`**: Calls
   `wiphy_rfkill_stop_polling()` without wiphy_lock held, breaking the
   deadlock.

### Step 2.3: Bug Mechanism
- **Category**: Deadlock/lock ordering
- **Mechanism**: `rsi_mac80211_stop()` (called with `wiphy_lock` held)
  invokes `wiphy_rfkill_stop_polling()` which calls
  `cancel_delayed_work_sync()`. The work item (`cfg80211_rfkill_poll`)
  needs `wiphy_lock`. Classic ABBA deadlock.
- **Fix**: Move the polling stop to `rsi_disconnect()`, before
  `rsi_mac80211_detach()`, where `wiphy_lock` is NOT held.

### Step 2.4: Fix Quality
- Obviously correct: removes the deadlocking call from the locked
  context, moves it to unlocked context
- Minimal/surgical: small change, well-contained within the rsi driver
- Other drivers (ath9k, rtlwifi, mt76, etc.) all call
  `wiphy_rfkill_stop_polling()` from their deinit paths, NOT from
  `.stop` - confirming this is the right pattern
- Regression risk: very low. The rfkill polling is stopped slightly
  earlier in the teardown sequence

## PHASE 3: GIT HISTORY INVESTIGATION

### Step 3.1: Blame
- `wiphy_rfkill_stop_polling(hw->wiphy)` in `rsi_mac80211_stop()` was
  added by commit `edba3532c65223` ("rsi: add support for rf-kill
  functionality") by Pavani Muthyala, 2017-08-03.
- The deadlock was introduced when `cfg80211_rfkill_poll()` acquired
  wiphy_lock: commit `8e2f6f2366219` ("wifi: cfg80211: lock wiphy mutex
  for rfkill poll") by Johannes Berg, 2023-11-24, first in v6.7-rc4.
- `drv_stop()` has had `lockdep_assert_wiphy()` since commit
  `0e8185ce1ddebf` (v6.7-rc1).

Record: Bug is a latent deadlock since v6.7 (when wiphy_lock was added
to the rfkill poll path). Buggy rfkill call in rsi since 2017, but it
only became a deadlock with v6.7.

### Step 3.2: No Fixes: tag present (expected).

### Step 3.3: File History
Recent changes to rsi files are mostly cleanups and unrelated bug fixes.
No prerequisites identified.

### Step 3.4: Author
Ville Nummela appears to be an external contributor (Kempower). This is
their first rsi commit. However, the patch was applied by Johannes Berg,
the wifi subsystem maintainer.

### Step 3.5: Dependencies
The fix is standalone. It uses only existing APIs
(`wiphy_rfkill_stop_polling`) and creates a simple wrapper function. No
dependencies on other patches.

## PHASE 4: MAILING LIST RESEARCH

Lore is protected by anti-bot measures, preventing direct access. B4 dig
could not find the commit in the local tree. The Link tag confirms the
patch was submitted and reviewed through the standard wireless-next
workflow and applied by Johannes Berg.

Record: Could not access lore discussion. Patch applied by subsystem
maintainer.

## PHASE 5: CODE SEMANTIC ANALYSIS

### Step 5.1: Functions Modified
- `rsi_mac80211_stop()` - the `.stop` mac80211 callback
- `rsi_disconnect()` - USB disconnect handler
- New: `rsi_mac80211_rfkill_exit()`

### Step 5.2: Callers
- `rsi_mac80211_stop()` is called by mac80211 via `drv_stop()`
  (confirmed: `lockdep_assert_wiphy()` at driver-ops.c:39). Called when
  interface goes down.
- `rsi_disconnect()` is the USB `.disconnect` callback, called by USB
  subsystem on device removal.

### Step 5.3-5.4: Call Chain for Deadlock
Verified complete deadlock chain:
1. USB removal -> `rsi_disconnect()` -> `rsi_mac80211_detach()` ->
   `ieee80211_unregister_hw()` -> interface shutdown -> `drv_stop()`
   [acquires wiphy_lock] -> `rsi_mac80211_stop()`
2. `rsi_mac80211_stop()` -> `wiphy_rfkill_stop_polling()` ->
   `rfkill_pause_polling()` ->
   `cancel_delayed_work_sync(&rfkill->poll_work)`
3. Work item: `rfkill_poll()` -> `cfg80211_rfkill_poll()` ->
   `guard(wiphy)(&rdev->wiphy)` [tries to acquire wiphy_lock] -> BLOCKED

### Step 5.5: Similar Patterns
All other wifi drivers (ath9k, rtlwifi, mt76, rtl818x, brcmsmac) call
`wiphy_rfkill_stop_polling()` from their deinit/disconnect path, NOT
from `.stop`. RSI was unique in calling it from `.stop`.

## PHASE 6: STABLE TREE ANALYSIS

### Step 6.1: Buggy Code in Stable
- The deadlock requires both:
  - `wiphy_rfkill_stop_polling()` in `rsi_mac80211_stop()` (since 2017,
    commit edba3532)
  - `wiphy_lock` acquisition in `cfg80211_rfkill_poll()` (since v6.7,
    commit 8e2f6f23)
- The deadlock exists in v6.7+ stable trees (6.12.y, 6.6.y if 8e2f6f23
  was backported)

### Step 6.2: Backport Complications
The fix is simple and self-contained. The rsi driver code in this area
has been stable. Clean apply expected for recent stable trees.

### Step 6.3: No related fixes already in stable.

## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT

- **Subsystem**: wifi (drivers/net/wireless/rsi/) - USB WiFi driver
- **Criticality**: IMPORTANT - WiFi is commonly used, RSI chipsets are
  used in embedded/IoT
- **Maintainer**: Applied by Johannes Berg (the wireless subsystem
  maintainer), strong trust signal

## PHASE 8: IMPACT AND RISK ASSESSMENT

### Step 8.1: Affected Users
Users of RSI 91x USB WiFi adapters. When removing the adapter
(physically or via software), the system hangs.

### Step 8.2: Trigger Conditions
- **Trigger**: Removing RSI USB WiFi adapter (unplug or modprobe -r)
- **Frequency**: Every time the adapter is removed
- **Unprivileged**: Physical access needed, but could also be triggered
  by system suspend/resume or hotplug events

### Step 8.3: Failure Mode Severity
- **Failure mode**: System hang / deadlock (rtnetlink locks up)
- **Severity**: CRITICAL - system becomes partially or fully unusable;
  rtnetlink lockup affects all networking operations

### Step 8.4: Risk-Benefit
- **Benefit**: HIGH - prevents guaranteed system hang on USB adapter
  removal
- **Risk**: VERY LOW - 19 lines changed, moves existing call to correct
  context, pattern matches all other wifi drivers
- **Ratio**: Strongly favorable

## PHASE 9: FINAL SYNTHESIS

### Step 9.1: Evidence Summary

**FOR backporting:**
- Fixes a real, reproducible deadlock (system hang) on USB adapter
  removal
- Small, surgical fix (~20 lines across 3 files in one driver)
- Obviously correct: moves `wiphy_rfkill_stop_polling()` from locked
  context to unlocked context
- Pattern matches all other wifi drivers (ath9k, rtlwifi, mt76, etc.)
- Applied by wireless subsystem maintainer (Johannes Berg)
- Standalone fix with no dependencies
- Bug exists since v6.7 (when wiphy_lock was added to rfkill poll)

**AGAINST backporting:**
- No explicit stable nomination or Fixes: tag (expected for manual
  review)
- Only fixes USB path (SDIO has same latent issue but wasn't addressed -
  minor concern)
- Author is external contributor with no previous rsi commits (mitigated
  by maintainer sign-off)

### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **YES** - clear deadlock fix, correct
   locking pattern
2. Fixes a real bug? **YES** - deadlock causing system hang
3. Important issue? **YES** - deadlock = CRITICAL severity
4. Small and contained? **YES** - ~20 lines in one driver
5. No new features or APIs? **YES** - only moves existing functionality
6. Can apply to stable trees? **YES** - standalone, no dependencies

### Step 9.3: Exception Categories
Not an exception case - this is a straightforward deadlock fix.

### Step 9.4: Decision
This is a clear, small, surgical fix for a real deadlock that causes
system hang when removing an RSI USB WiFi adapter. It follows the same
pattern used by all other wifi drivers. Applied by the wifi subsystem
maintainer.

## Verification

- [Phase 1] Parsed tags: Link to patch.msgid.link, SOB by author and
  Johannes Berg (maintainer)
- [Phase 2] Diff analysis: 1 line removed from `rsi_mac80211_stop()`,
  16-line new function `rsi_mac80211_rfkill_exit()` added, 2 lines
  calling it in `rsi_disconnect()`
- [Phase 3] git blame: `wiphy_rfkill_stop_polling` in `.stop` added by
  edba3532c65223 (2017)
- [Phase 3] git show 8e2f6f2366219: confirmed `wiphy_lock` added to
  `cfg80211_rfkill_poll()` in v6.7-rc4
- [Phase 3] git show 0e8185ce1ddebf: confirmed `lockdep_assert_wiphy()`
  in `drv_stop()` since v6.7-rc1
- [Phase 3] git describe --contains 8e2f6f2366219: deadlock exists since
  v6.7-rc4
- [Phase 4] Could not access lore (anti-bot protection); patch Link tag
  confirms standard review
- [Phase 5] Verified deadlock chain: `drv_stop()` holds wiphy_lock
  (driver-ops.c:39) -> `rsi_mac80211_stop()` -> `rfkill_pause_polling()`
  -> `cancel_delayed_work_sync()` blocks on work item needing wiphy_lock
  via `guard(wiphy)` in `cfg80211_rfkill_poll()` (core.c:224)
- [Phase 5] Confirmed all other wifi drivers (ath9k, rtlwifi, mt76,
  rtl818x, brcmsmac) call `wiphy_rfkill_stop_polling()` from deinit
  path, not `.stop`
- [Phase 6] Bug exists in v6.7+ trees; code in rsi driver unchanged in
  affected area
- [Phase 8] Failure mode: deadlock/system hang, severity CRITICAL
- UNVERIFIED: Could not access lore discussion for reviewer feedback

**YES**

 drivers/net/wireless/rsi/rsi_91x_mac80211.c | 17 ++++++++++++++++-
 drivers/net/wireless/rsi/rsi_91x_usb.c      |  2 ++
 drivers/net/wireless/rsi/rsi_common.h       |  1 +
 3 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index c7ae8031436ae..3faf2235728be 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -325,6 +325,22 @@ void rsi_mac80211_detach(struct rsi_hw *adapter)
 }
 EXPORT_SYMBOL_GPL(rsi_mac80211_detach);
 
+/**
+ * rsi_mac80211_rfkill_exit() - This function is used to stop rfkill polling
+ *                              when the device is removed.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: None.
+ */
+void rsi_mac80211_rfkill_exit(struct rsi_hw *adapter)
+{
+	struct ieee80211_hw *hw = adapter->hw;
+
+	if (hw)
+		wiphy_rfkill_stop_polling(hw->wiphy);
+}
+EXPORT_SYMBOL_GPL(rsi_mac80211_rfkill_exit);
+
 /**
  * rsi_indicate_tx_status() - This function indicates the transmit status.
  * @adapter: Pointer to the adapter structure.
@@ -422,7 +438,6 @@ static void rsi_mac80211_stop(struct ieee80211_hw *hw, bool suspend)
 	rsi_dbg(ERR_ZONE, "===> Interface DOWN <===\n");
 	mutex_lock(&common->mutex);
 	common->iface_down = true;
-	wiphy_rfkill_stop_polling(hw->wiphy);
 
 	/* Block all rx frames */
 	rsi_send_rx_filter_frame(common, 0xffff);
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index d83204701e27e..8765cac6f875b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -877,6 +877,8 @@ static void rsi_disconnect(struct usb_interface *pfunction)
 	if (!adapter)
 		return;
 
+	rsi_mac80211_rfkill_exit(adapter);
+
 	rsi_mac80211_detach(adapter);
 
 	if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 &&
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index 7aa5124575cfe..591602beeec68 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -79,6 +79,7 @@ static inline int rsi_kill_thread(struct rsi_thread *handle)
 }
 
 void rsi_mac80211_detach(struct rsi_hw *hw);
+void rsi_mac80211_rfkill_exit(struct rsi_hw *hw);
 u16 rsi_get_connected_channel(struct ieee80211_vif *vif);
 struct rsi_hw *rsi_91x_init(u16 oper_mode);
 void rsi_91x_deinit(struct rsi_hw *adapter);
-- 
2.53.0


  parent reply	other threads:[~2026-04-20 13:23 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20260420132314.1023554-1-sashal@kernel.org>
2026-04-20 13:16 ` [PATCH AUTOSEL 7.0-6.18] wifi: ath12k: Fix the assignment of logical link index Sasha Levin
2026-04-20 13:16 ` [PATCH AUTOSEL 7.0-6.12] wifi: rtw89: ser: Wi-Fi 7 reset HALT C2H after reading it Sasha Levin
2026-04-20 13:16 ` Sasha Levin [this message]
2026-04-20 13:16 ` [PATCH AUTOSEL 7.0-6.18] wifi: rtw88: add quirks to disable PCI ASPM and deep LPS for HP P3S95EA#ACB Sasha Levin
2026-04-20 13:16 ` [PATCH AUTOSEL 6.18] wifi: brcmfmac: validate bsscfg indices in IF events Sasha Levin
2026-04-20 13:17 ` [PATCH AUTOSEL 7.0-6.6] wifi: mac80211: set band information only for non-MLD when probing stations using NULL frame Sasha Levin
2026-04-20 13:17 ` [PATCH AUTOSEL 7.0-6.19] wifi: mt76: avoid to set ACK for MCU command if wait_resp is not set Sasha Levin
2026-04-20 13:17 ` [PATCH AUTOSEL 7.0-6.19] wifi: rtw89: Add support for TP-Link Archer TX50U Sasha Levin
2026-04-20 13:17 ` [PATCH AUTOSEL 7.0-6.1] wifi: mac80211: use ap_addr for 4-address NULL frame destination Sasha Levin
2026-04-20 13:17 ` [PATCH AUTOSEL 7.0-6.18] wifi: ath12k: Set up MLO after SSR Sasha Levin
2026-04-20 13:18 ` [PATCH AUTOSEL 7.0-6.18] wifi: iwlwifi: mld: always assign a fw id to a vif Sasha Levin
2026-04-20 13:18 ` [PATCH AUTOSEL 6.18] wifi: wl1251: validate packet IDs before indexing tx_frames Sasha Levin
2026-04-20 13:18 ` [PATCH AUTOSEL 7.0-6.18] wifi: mt76: flush pending TX before channel switch Sasha Levin
2026-04-20 13:18 ` [PATCH AUTOSEL 7.0-6.6] wifi: mt76: fix list corruption in mt76_wcid_cleanup Sasha Levin
2026-04-20 13:18 ` [PATCH AUTOSEL 7.0-6.12] wifi: mt76: add missing lock protection in mt76_sta_state for sta_event callback Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.18] wifi: mt76: mt7996: Disable Rx hdr_trans in monitor mode Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.18] wifi: iwlwifi: restrict TOP reset to some devices Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.12] wifi: mt76: mt7925: Skip scan process during suspend Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-5.10] wifi: mt76: mt76x02: wake queues after reconfig Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.12] wifi: mt76: mt7925: resolve link after acquiring mt76 mutex Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.19] wifi: rtw89: mac: remove A-die off setting for RTL8852C and RTL8922A Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.18] wifi: mt76: mt7996: fix queue pause after scan due to wrong channel switch reason Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.18] wifi: brcmfmac: of: defer probe for MAC address Sasha Levin
2026-04-20 13:19 ` [PATCH AUTOSEL 7.0-6.19] wifi: rtw89: Add support for Buffalo WI-U3-2400XE2 Sasha Levin
2026-04-20 13:20 ` [PATCH AUTOSEL 7.0-6.19] wifi: rtw89: Add support for Elecom WDC-XE2402TU3-B Sasha Levin
2026-04-20 13:20 ` [PATCH AUTOSEL 7.0-6.6] wifi: mt76: mt7996: reset device after MCU message timeout Sasha Levin
2026-04-20 13:21 ` [PATCH AUTOSEL 7.0-5.10] wifi: rtw88: TX QOS Null data the same way as Null data Sasha Levin
2026-04-20 13:21 ` [PATCH AUTOSEL 7.0-6.18] wifi: rtw88: validate RX rate to prevent out-of-bound Sasha Levin
2026-04-20 13:21 ` [PATCH AUTOSEL 7.0-6.18] wifi: ath12k: Skip adding inactive partner vdev info Sasha Levin
2026-04-20 13:21 ` [PATCH AUTOSEL 7.0-6.18] wifi: mt76: mt7996: fix frequency separation for station STR mode Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260420132314.1023554-14-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=johannes.berg@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=patches@lists.linux.dev \
    --cc=stable@vger.kernel.org \
    --cc=ville.nummela@kempower.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox