Page MenuHomeFreeBSD

D43725.diff
No OneTemporary

D43725.diff

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h
--- a/sys/compat/linuxkpi/common/src/linux_80211.h
+++ b/sys/compat/linuxkpi/common/src/linux_80211.h
@@ -156,6 +156,8 @@
struct ieee80211_node * (*iv_update_bss)(struct ieee80211vap *,
struct ieee80211_node *);
TAILQ_HEAD(, lkpi_sta) lsta_head;
+ struct lkpi_sta *lvif_bss;
+ bool lvif_bss_synched;
bool added_to_drv; /* Driver knows; i.e. we called add_interface(). */
bool hw_queue_stopped[IEEE80211_NUM_ACS];
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -610,6 +610,7 @@
return (NULL);
}
+#if 0
static struct linuxkpi_ieee80211_channel *
lkpi_get_lkpi80211_chan(struct ieee80211com *ic, struct ieee80211_node *ni)
{
@@ -634,6 +635,7 @@
return (chan);
}
+#endif
struct linuxkpi_ieee80211_channel *
linuxkpi_ieee80211_get_channel(struct wiphy *wiphy, uint32_t freq)
@@ -1039,19 +1041,37 @@
uint32_t changed;
int error;
- chan = lkpi_get_lkpi80211_chan(vap->iv_ic, vap->iv_bss);
+ /*
+ * In here we use vap->iv_bss until lvif->lvif_bss is set.
+ * For all later (STATE >= AUTH) functions we need to use the lvif
+ * cache which will be tracked even through (*iv_update_bss)().
+ */
+
+ if (vap->iv_bss == NULL) {
+ ic_printf(vap->iv_ic, "%s: no iv_bss for vap %p\n", __func__, vap);
+ return (EINVAL);
+ }
+ ni = ieee80211_ref_node(vap->iv_bss);
+ if (ni->ni_chan == NULL || ni->ni_chan == IEEE80211_CHAN_ANYC) {
+ ic_printf(vap->iv_ic, "%s: no channel set for iv_bss ni %p "
+ "on vap %p\n", __func__, ni, vap);
+ ieee80211_free_node(ni);
+ return (EINVAL);
+ }
+
+ lhw = vap->iv_ic->ic_softc;
+ chan = lkpi_find_lkpi80211_chan(lhw, ni->ni_chan);
if (chan == NULL) {
- ic_printf(vap->iv_ic, "%s: failed to get channel\n", __func__);
+ ic_printf(vap->iv_ic, "%s: failed to get LKPI channel from "
+ "iv_bss ni %p on vap %p\n", __func__, ni, vap);
+ ieee80211_free_node(ni);
return (ESRCH);
}
- lhw = vap->iv_ic->ic_softc;
hw = LHW_TO_HW(lhw);
lvif = VAP_TO_LVIF(vap);
vif = LVIF_TO_VIF(lvif);
- ni = ieee80211_ref_node(vap->iv_bss);
-
IEEE80211_UNLOCK(vap->iv_ic);
LKPI_80211_LHW_LOCK(lhw);
@@ -1076,6 +1096,8 @@
conf->def.center_freq1 = chan->center_freq;
conf->def.center_freq2 = 0;
IMPROVE("Check vht_cap from band not just chan?");
+ KASSERT(ni->ni_chan != NULL && ni->ni_chan != IEEE80211_CHAN_ANYC,
+ ("%s:%d: ni %p ni_chan %p\n", __func__, __LINE__, ni, ni->ni_chan));
#ifdef LKPI_80211_HT
if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) {
if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
@@ -1186,6 +1208,8 @@
* workflow so live with this. It is a compat layer after all.
*/
if (ni->ni_drv_data == NULL) {
+ ic_printf(vap->iv_ic, "%s:%d: lkpi_lsta_alloc to be called: "
+ "ni %p lsta %p\n", __func__, __LINE__, ni, ni->ni_drv_data);
lsta = lkpi_lsta_alloc(vap, ni->ni_macaddr, hw, ni);
if (lsta == NULL) {
error = ENOMEM;
@@ -1198,8 +1222,22 @@
lsta = ni->ni_drv_data;
}
- /* Insert the [l]sta into the list of known stations. */
LKPI_80211_LVIF_LOCK(lvif);
+ /* XXX-BZ KASSERT later? */
+ /* XXX-BZ this should have caught the upper lkpi_lsta_alloc() too! */
+ if (lvif->lvif_bss_synched || lvif->lvif_bss != NULL)
+ ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p "
+ "lvif_bss->ni %p synched %d, ni %p lsta %p\n", __func__, __LINE__,
+ lvif, vap, vap->iv_bss, lvif->lvif_bss,
+ (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL,
+ lvif->lvif_bss_synched, ni, lsta);
+
+ /* Reference the ni for this cache of lsta. */
+ ieee80211_ref_node(vap->iv_bss);
+ lvif->lvif_bss = lsta;
+ lvif->lvif_bss_synched = true;
+
+ /* Insert the [l]sta into the list of known stations. */
TAILQ_INSERT_TAIL(&lvif->lsta_head, lsta, lsta_entry);
LKPI_80211_LVIF_UNLOCK(lvif);
@@ -1271,9 +1309,23 @@
lvif = VAP_TO_LVIF(vap);
vif = LVIF_TO_VIF(lvif);
- /* Keep ni around. */
- ni = ieee80211_ref_node(vap->iv_bss);
- lsta = ni->ni_drv_data;
+ LKPI_80211_LVIF_LOCK(lvif);
+#ifdef LINUXKPI_DEBUG_80211
+ /* XXX-BZ KASSERT later; state going down so no action. */
+ if (lvif->lvif_bss == NULL)
+ ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p "
+ "lvif_bss->ni %p synched %d\n", __func__, __LINE__,
+ lvif, vap, vap->iv_bss, lvif->lvif_bss,
+ (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL,
+ lvif->lvif_bss_synched);
+#endif
+
+ lsta = lvif->lvif_bss;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ KASSERT(lsta != NULL && lsta->ni != NULL, ("%s: lsta %p ni %p "
+ "lvif %p vap %p\n", __func__,
+ lsta, (lsta != NULL) ? lsta->ni : NULL, lvif, vap));
+ ni = lsta->ni; /* Reference held for lvif_bss. */
sta = LSTA_TO_STA(lsta);
lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
@@ -1323,6 +1375,13 @@
lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
+ LKPI_80211_LVIF_LOCK(lvif);
+ /* Remove ni reference for this cache of lsta. */
+ lvif->lvif_bss = NULL;
+ lvif->lvif_bss_synched = false;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ ieee80211_free_node(ni); /* was lvif->lvif_bss->ni */
+
lkpi_lsta_remove(lsta, lvif);
/* conf_tx */
@@ -1346,8 +1405,6 @@
out:
LKPI_80211_LHW_UNLOCK(lhw);
IEEE80211_LOCK(vap->iv_ic);
- if (ni != NULL)
- ieee80211_free_node(ni);
return (error);
}
@@ -1369,7 +1426,6 @@
struct ieee80211_hw *hw;
struct lkpi_vif *lvif;
struct ieee80211_vif *vif;
- struct ieee80211_node *ni;
struct lkpi_sta *lsta;
struct ieee80211_prep_tx_info prep_tx_info;
int error;
@@ -1381,15 +1437,30 @@
IEEE80211_UNLOCK(vap->iv_ic);
LKPI_80211_LHW_LOCK(lhw);
- ni = NULL;
+
+ LKPI_80211_LVIF_LOCK(lvif);
+ /* XXX-BZ KASSERT later? */
+ if (!lvif->lvif_bss_synched || lvif->lvif_bss == NULL) {
+#ifdef LINUXKPI_DEBUG_80211
+ ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p "
+ "lvif_bss->ni %p synched %d\n", __func__, __LINE__,
+ lvif, vap, vap->iv_bss, lvif->lvif_bss,
+ (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL,
+ lvif->lvif_bss_synched);
+#endif
+ error = ENOTRECOVERABLE;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ goto out;
+ }
+ lsta = lvif->lvif_bss;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+
+ KASSERT(lsta != NULL, ("%s: lsta %p\n", __func__, lsta));
/* Finish auth. */
IMPROVE("event callback");
/* Update sta_state (NONE to AUTH). */
- ni = ieee80211_ref_node(vap->iv_bss);
- lsta = ni->ni_drv_data;
- KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
KASSERT(lsta->state == IEEE80211_STA_NONE, ("%s: lsta %p state not "
"NONE: %#x\n", __func__, lsta, lsta->state));
error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_AUTH);
@@ -1433,8 +1504,6 @@
out:
LKPI_80211_LHW_UNLOCK(lhw);
IEEE80211_LOCK(vap->iv_ic);
- if (ni != NULL)
- ieee80211_free_node(ni);
return (error);
}
@@ -1446,20 +1515,37 @@
struct ieee80211_hw *hw;
struct lkpi_vif *lvif;
struct ieee80211_vif *vif;
- struct ieee80211_node *ni;
struct lkpi_sta *lsta;
struct ieee80211_prep_tx_info prep_tx_info;
+ int error;
lhw = vap->iv_ic->ic_softc;
hw = LHW_TO_HW(lhw);
lvif = VAP_TO_LVIF(vap);
vif = LVIF_TO_VIF(lvif);
- ni = ieee80211_ref_node(vap->iv_bss);
-
IEEE80211_UNLOCK(vap->iv_ic);
LKPI_80211_LHW_LOCK(lhw);
- lsta = ni->ni_drv_data;
+
+ LKPI_80211_LVIF_LOCK(lvif);
+ /* XXX-BZ KASSERT later? */
+ if (!lvif->lvif_bss_synched || lvif->lvif_bss == NULL) {
+#ifdef LINUXKPI_DEBUG_80211
+ ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p "
+ "lvif_bss->ni %p synched %d\n", __func__, __LINE__,
+ lvif, vap, vap->iv_bss, lvif->lvif_bss,
+ (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL,
+ lvif->lvif_bss_synched);
+#endif
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ error = ENOTRECOVERABLE;
+ goto out;
+ }
+ lsta = lvif->lvif_bss;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+
+ KASSERT(lsta != NULL, ("%s: lsta %p! lvif %p vap %p\n", __func__,
+ lsta, lvif, vap));
IMPROVE("event callback?");
@@ -1481,12 +1567,12 @@
lsta->in_mgd = true;
}
+ error = 0;
+out:
LKPI_80211_LHW_UNLOCK(lhw);
IEEE80211_LOCK(vap->iv_ic);
- if (ni != NULL)
- ieee80211_free_node(ni);
- return (0);
+ return (error);
}
static int
@@ -1508,16 +1594,30 @@
lvif = VAP_TO_LVIF(vap);
vif = LVIF_TO_VIF(lvif);
- /* Keep ni around. */
- ni = ieee80211_ref_node(vap->iv_bss);
- lsta = ni->ni_drv_data;
+ IEEE80211_UNLOCK(vap->iv_ic);
+ LKPI_80211_LHW_LOCK(lhw);
+
+ LKPI_80211_LVIF_LOCK(lvif);
+#ifdef LINUXKPI_DEBUG_80211
+ /* XXX-BZ KASSERT later; state going down so no action. */
+ if (lvif->lvif_bss == NULL)
+ ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p "
+ "lvif_bss->ni %p synched %d\n", __func__, __LINE__,
+ lvif, vap, vap->iv_bss, lvif->lvif_bss,
+ (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL,
+ lvif->lvif_bss_synched);
+#endif
+ lsta = lvif->lvif_bss;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ KASSERT(lsta != NULL && lsta->ni != NULL, ("%s: lsta %p ni %p "
+ "lvif %p vap %p\n", __func__,
+ lsta, (lsta != NULL) ? lsta->ni : NULL, lvif, vap));
+
+ ni = lsta->ni; /* Reference held for lvif_bss. */
sta = LSTA_TO_STA(lsta);
lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
- IEEE80211_UNLOCK(vap->iv_ic);
- LKPI_80211_LHW_LOCK(lhw);
-
/* flush, drop. */
lkpi_80211_mo_flush(hw, vif, nitems(sta->txq), true);
@@ -1613,6 +1713,13 @@
bss_changed |= BSS_CHANGED_BSSID;
lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
+ LKPI_80211_LVIF_LOCK(lvif);
+ /* Remove ni reference for this cache of lsta. */
+ lvif->lvif_bss = NULL;
+ lvif->lvif_bss_synched = false;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ ieee80211_free_node(ni); /* was lvif->lvif_bss->ni */
+
lkpi_lsta_remove(lsta, lvif);
/* conf_tx */
@@ -1638,8 +1745,6 @@
LKPI_80211_LHW_UNLOCK(lhw);
IEEE80211_LOCK(vap->iv_ic);
outni:
- if (ni != NULL)
- ieee80211_free_node(ni);
return (error);
}
@@ -1697,16 +1802,34 @@
IEEE80211_UNLOCK(vap->iv_ic);
LKPI_80211_LHW_LOCK(lhw);
- ni = NULL;
+
+ LKPI_80211_LVIF_LOCK(lvif);
+ /* XXX-BZ KASSERT later? */
+ if (!lvif->lvif_bss_synched || lvif->lvif_bss == NULL) {
+#ifdef LINUXKPI_DEBUG_80211
+ ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p "
+ "lvif_bss->ni %p synched %d\n", __func__, __LINE__,
+ lvif, vap, vap->iv_bss, lvif->lvif_bss,
+ (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL,
+ lvif->lvif_bss_synched);
+#endif
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ error = ENOTRECOVERABLE;
+ goto out;
+ }
+ lsta = lvif->lvif_bss;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ KASSERT(lsta != NULL && lsta->ni != NULL, ("%s: lsta %p ni %p "
+ "lvif %p vap %p\n", __func__,
+ lsta, (lsta != NULL) ? lsta->ni : NULL, lvif, vap));
+
+ ni = lsta->ni; /* Reference held for lvif_bss. */
IMPROVE("ponder some of this moved to ic_newassoc, scan_assoc_success, "
"and to lesser extend ieee80211_notify_node_join");
/* Finish assoc. */
/* Update sta_state (AUTH to ASSOC) and set aid. */
- ni = ieee80211_ref_node(vap->iv_bss);
- lsta = ni->ni_drv_data;
- KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
KASSERT(lsta->state == IEEE80211_STA_AUTH, ("%s: lsta %p state not "
"AUTH: %#x\n", __func__, lsta, lsta->state));
sta = LSTA_TO_STA(lsta);
@@ -1819,8 +1942,6 @@
out:
LKPI_80211_LHW_UNLOCK(lhw);
IEEE80211_LOCK(vap->iv_ic);
- if (ni != NULL)
- ieee80211_free_node(ni);
return (error);
}
@@ -1856,9 +1977,23 @@
lvif = VAP_TO_LVIF(vap);
vif = LVIF_TO_VIF(lvif);
- /* Keep ni around. */
- ni = ieee80211_ref_node(vap->iv_bss);
- lsta = ni->ni_drv_data;
+ LKPI_80211_LVIF_LOCK(lvif);
+#ifdef LINUXKPI_DEBUG_80211
+ /* XXX-BZ KASSERT later; state going down so no action. */
+ if (lvif->lvif_bss == NULL)
+ ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p "
+ "lvif_bss->ni %p synched %d\n", __func__, __LINE__,
+ lvif, vap, vap->iv_bss, lvif->lvif_bss,
+ (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL,
+ lvif->lvif_bss_synched);
+#endif
+ lsta = lvif->lvif_bss;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ KASSERT(lsta != NULL && lsta->ni != NULL, ("%s: lsta %p ni %p "
+ "lvif %p vap %p\n", __func__,
+ lsta, (lsta != NULL) ? lsta->ni : NULL, lvif, vap));
+
+ ni = lsta->ni; /* Reference held for lvif_bss. */
sta = LSTA_TO_STA(lsta);
lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
@@ -1954,8 +2089,6 @@
LKPI_80211_LHW_UNLOCK(lhw);
IEEE80211_LOCK(vap->iv_ic);
outni:
- if (ni != NULL)
- ieee80211_free_node(ni);
return (error);
}
@@ -1978,16 +2111,30 @@
lvif = VAP_TO_LVIF(vap);
vif = LVIF_TO_VIF(lvif);
- /* Keep ni around. */
- ni = ieee80211_ref_node(vap->iv_bss);
- lsta = ni->ni_drv_data;
+ IEEE80211_UNLOCK(vap->iv_ic);
+ LKPI_80211_LHW_LOCK(lhw);
+
+ LKPI_80211_LVIF_LOCK(lvif);
+#ifdef LINUXKPI_DEBUG_80211
+ /* XXX-BZ KASSERT later; state going down so no action. */
+ if (lvif->lvif_bss == NULL)
+ ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p "
+ "lvif_bss->ni %p synched %d\n", __func__, __LINE__,
+ lvif, vap, vap->iv_bss, lvif->lvif_bss,
+ (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL,
+ lvif->lvif_bss_synched);
+#endif
+ lsta = lvif->lvif_bss;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ KASSERT(lsta != NULL && lsta->ni != NULL, ("%s: lsta %p ni %p "
+ "lvif %p vap %p\n", __func__,
+ lsta, (lsta != NULL) ? lsta->ni : NULL, lvif, vap));
+
+ ni = lsta->ni; /* Reference held for lvif_bss. */
sta = LSTA_TO_STA(lsta);
lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
- IEEE80211_UNLOCK(vap->iv_ic);
- LKPI_80211_LHW_LOCK(lhw);
-
/* flush, drop. */
lkpi_80211_mo_flush(hw, vif, nitems(sta->txq), true);
@@ -2107,6 +2254,13 @@
bss_changed |= BSS_CHANGED_BSSID;
lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
+ LKPI_80211_LVIF_LOCK(lvif);
+ /* Remove ni reference for this cache of lsta. */
+ lvif->lvif_bss = NULL;
+ lvif->lvif_bss_synched = false;
+ LKPI_80211_LVIF_UNLOCK(lvif);
+ ieee80211_free_node(ni); /* was lvif->lvif_bss->ni */
+
lkpi_lsta_remove(lsta, lvif);
/* conf_tx */
@@ -2132,8 +2286,6 @@
LKPI_80211_LHW_UNLOCK(lhw);
IEEE80211_LOCK(vap->iv_ic);
outni:
- if (ni != NULL)
- ieee80211_free_node(ni);
return (error);
}
@@ -2306,53 +2458,18 @@
lkpi_iv_update_bss(struct ieee80211vap *vap, struct ieee80211_node *ni)
{
struct lkpi_vif *lvif;
- struct ieee80211_node *obss;
- struct lkpi_sta *lsta;
- struct ieee80211_sta *sta;
-
- obss = vap->iv_bss;
-
-#ifdef LINUXKPI_DEBUG_80211
- if (linuxkpi_debug_80211 & D80211_TRACE)
- ic_printf(vap->iv_ic, "%s: obss %p ni_drv_data %p "
- "ni %p ni_drv_data %p\n", __func__,
- obss, (obss != NULL) ? obss->ni_drv_data : NULL,
- ni, (ni != NULL) ? ni->ni_drv_data : NULL);
-#endif
+ struct ieee80211_node *rni;
- /* Nothing to copy from. Just return. */
- if (obss == NULL || obss->ni_drv_data == NULL)
- goto out;
-
- /* Nothing to copy to. Just return. */
- IMPROVE("clearing the obss might still be needed?");
- if (ni == NULL)
- goto out;
+ IEEE80211_LOCK_ASSERT(vap->iv_ic);
- /* Nothing changed? panic? */
- if (obss == ni)
- goto out;
+ lvif = VAP_TO_LVIF(vap);
- lsta = obss->ni_drv_data;
- obss->ni_drv_data = ni->ni_drv_data;
- ni->ni_drv_data = lsta;
- if (lsta != NULL) {
- lsta->ni = ni;
- sta = LSTA_TO_STA(lsta);
- IEEE80211_ADDR_COPY(sta->addr, lsta->ni->ni_macaddr);
- IEEE80211_ADDR_COPY(sta->deflink.addr, sta->addr);
- }
- lsta = obss->ni_drv_data;
- if (lsta != NULL) {
- lsta->ni = obss;
- sta = LSTA_TO_STA(lsta);
- IEEE80211_ADDR_COPY(sta->addr, lsta->ni->ni_macaddr);
- IEEE80211_ADDR_COPY(sta->deflink.addr, sta->addr);
- }
+ LKPI_80211_LVIF_LOCK(lvif);
+ lvif->lvif_bss_synched = false;
+ LKPI_80211_LVIF_UNLOCK(lvif);
-out:
- lvif = VAP_TO_LVIF(vap);
- return (lvif->iv_update_bss(vap, ni));
+ rni = lvif->iv_update_bss(vap, ni);
+ return (rni);
}
#ifdef LKPI_80211_WME
@@ -2473,6 +2590,8 @@
lvif = malloc(len, M_80211_VAP, M_WAITOK | M_ZERO);
mtx_init(&lvif->mtx, "lvif", NULL, MTX_DEF);
TAILQ_INIT(&lvif->lsta_head);
+ lvif->lvif_bss = NULL;
+ lvif->lvif_bss_synched = false;
vap = LVIF_TO_VAP(lvif);
vif = LVIF_TO_VIF(lvif);

File Metadata

Mime Type
text/plain
Expires
Fri, Sep 27, 9:38 PM (22 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
12944334
Default Alt Text
D43725.diff (16 KB)

Event Timeline