public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net 1/1] mptcp: hold subflow request owners when cloning reqsk
       [not found] <cover.1776149210.git.caoruide123@gmail.com>
@ 2026-04-15  9:31 ` Ren Wei
  2026-04-16 17:45   ` Matthieu Baerts
  0 siblings, 1 reply; 5+ messages in thread
From: Ren Wei @ 2026-04-15  9:31 UTC (permalink / raw)
  To: netdev, mptcp
  Cc: davem, edumazet, kuba, pabeni, horms, ncardwell, kuniyu, dsahern,
	matttbe, martineau, geliang, daniel, kafai, yuantan098, yifanwucs,
	tomapufckgml, bird, caoruide123, enjou1224z, n05ec

From: Ruide Cao <caoruide123@gmail.com>

TCP request migration clones pending request sockets with
inet_reqsk_clone(). For MPTCP MP_JOIN requests this raw-copies
subflow_req->msk, but the cloned request does not take a new reference.

Both the original and the cloned request can later drop the same msk in
subflow_req_destructor(), and a migrated request may keep a dangling msk
pointer after the original owner has already been released.

Add a request_sock clone callback and let MPTCP grab a reference for cloned
subflow requests that carry an msk. This keeps ownership balanced across
both successful migrations and failed clone/insert paths without changing
other protocols.

Fixes: c905dee62232 ("tcp: Migrate TCP_NEW_SYN_RECV requests at retransmitting SYN+ACKs.")
Cc: stable@kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Signed-off-by: Ruide Cao <caoruide123@gmail.com>
Tested-by: Ren Wei <enjou1224z@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
 include/net/request_sock.h      |  2 ++
 net/ipv4/inet_connection_sock.c |  3 +++
 net/mptcp/subflow.c             | 13 +++++++++++++
 3 files changed, 18 insertions(+)

diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 5a9c826a7092..560e464c400f 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -36,6 +36,8 @@ struct request_sock_ops {
 				      struct sk_buff *skb,
 				      enum sk_rst_reason reason);
 	void		(*destructor)(struct request_sock *req);
+	void		(*init_clone)(const struct request_sock *req,
+				      struct request_sock *new_req);
 };
 
 struct saved_syn {
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index e961936b6be7..140a9e96ad58 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -954,6 +954,9 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
 	if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
 		rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
 
+	if (req->rsk_ops->init_clone)
+		req->rsk_ops->init_clone(req, nreq);
+
 	return nreq;
 }
 
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 4ff5863aa9fd..5f4069647822 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -47,6 +47,17 @@ static void subflow_req_destructor(struct request_sock *req)
 	mptcp_token_destroy_request(req);
 }
 
+static void subflow_req_clone(const struct request_sock *req,
+			      struct request_sock *new_req)
+{
+	struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(new_req);
+
+	(void)req;
+
+	if (subflow_req->msk)
+		sock_hold((struct sock *)subflow_req->msk);
+}
+
 static void subflow_generate_hmac(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
 				  void *hmac)
 {
@@ -2143,6 +2154,7 @@ void __init mptcp_subflow_init(void)
 	mptcp_subflow_v4_request_sock_ops = tcp_request_sock_ops;
 	mptcp_subflow_v4_request_sock_ops.slab_name = "request_sock_subflow_v4";
 	mptcp_subflow_v4_request_sock_ops.destructor = subflow_v4_req_destructor;
+	mptcp_subflow_v4_request_sock_ops.init_clone = subflow_req_clone;
 
 	if (subflow_ops_init(&mptcp_subflow_v4_request_sock_ops) != 0)
 		panic("MPTCP: failed to init subflow v4 request sock ops\n");
@@ -2184,6 +2196,7 @@ void __init mptcp_subflow_v6_init(void)
 	mptcp_subflow_v6_request_sock_ops = tcp6_request_sock_ops;
 	mptcp_subflow_v6_request_sock_ops.slab_name = "request_sock_subflow_v6";
 	mptcp_subflow_v6_request_sock_ops.destructor = subflow_v6_req_destructor;
+	mptcp_subflow_v6_request_sock_ops.init_clone = subflow_req_clone;
 
 	if (subflow_ops_init(&mptcp_subflow_v6_request_sock_ops) != 0)
 		panic("MPTCP: failed to init subflow v6 request sock ops\n");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net 1/1] mptcp: hold subflow request owners when cloning reqsk
  2026-04-15  9:31 ` [PATCH net 1/1] mptcp: hold subflow request owners when cloning reqsk Ren Wei
@ 2026-04-16 17:45   ` Matthieu Baerts
  2026-04-16 18:48     ` Kuniyuki Iwashima
  0 siblings, 1 reply; 5+ messages in thread
From: Matthieu Baerts @ 2026-04-16 17:45 UTC (permalink / raw)
  To: Ren Wei, netdev, mptcp
  Cc: davem, edumazet, kuba, pabeni, horms, ncardwell, kuniyu, dsahern,
	martineau, geliang, daniel, kafai, yuantan098, yifanwucs,
	tomapufckgml, bird, caoruide123, enjou1224z

Hi Ren,

On 15/04/2026 11:31, Ren Wei wrote:
> From: Ruide Cao <caoruide123@gmail.com>
> 
> TCP request migration clones pending request sockets with
> inet_reqsk_clone(). For MPTCP MP_JOIN requests this raw-copies
> subflow_req->msk, but the cloned request does not take a new reference.
> 
> Both the original and the cloned request can later drop the same msk in
> subflow_req_destructor(), and a migrated request may keep a dangling msk
> pointer after the original owner has already been released.
> 
> Add a request_sock clone callback and let MPTCP grab a reference for cloned
> subflow requests that carry an msk. This keeps ownership balanced across
> both successful migrations and failed clone/insert paths without changing
> other protocols.

Thank you for this patch!

Indeed, it looks like this path has not been covered by the MPTCP test
suite so far.

By chance, do you have any simpler reproducer using packetdrill? (the
MPTCP fork)

  https://github.com/multipath-tcp/packetdrill

Also, I see Sashiko is pointing to a potential issue with MP_CAPABLE and
the token, also only visible with net.ipv4.tcp_migrate_req=1:

https://sashiko.dev/#/patchset/86e2514b533bf4d55d4aa2fdbf1404022e8c9430.1776149210.git.caoruide123%40gmail.com

Are you also looking at that?

> Fixes: c905dee62232 ("tcp: Migrate TCP_NEW_SYN_RECV requests at retransmitting SYN+ACKs.")
> Cc: stable@kernel.org
> Reported-by: Yuan Tan <yuantan098@gmail.com>
> Reported-by: Yifan Wu <yifanwucs@gmail.com>
> Reported-by: Juefei Pu <tomapufckgml@gmail.com>
> Reported-by: Xin Liu <bird@lzu.edu.cn>
> Signed-off-by: Ruide Cao <caoruide123@gmail.com>
> Tested-by: Ren Wei <enjou1224z@gmail.com>
> Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
> ---
>  include/net/request_sock.h      |  2 ++
>  net/ipv4/inet_connection_sock.c |  3 +++
>  net/mptcp/subflow.c             | 13 +++++++++++++
>  3 files changed, 18 insertions(+)
> 
> diff --git a/include/net/request_sock.h b/include/net/request_sock.h
> index 5a9c826a7092..560e464c400f 100644
> --- a/include/net/request_sock.h
> +++ b/include/net/request_sock.h
> @@ -36,6 +36,8 @@ struct request_sock_ops {
>  				      struct sk_buff *skb,
>  				      enum sk_rst_reason reason);
>  	void		(*destructor)(struct request_sock *req);
> +	void		(*init_clone)(const struct request_sock *req,
> +				      struct request_sock *new_req);

@TCP/INET maintainers: are you OK with this new function pointer?

Currently, MPTCP is the only user, and "req" is not used, see below.

>  };
>  
>  struct saved_syn {
> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
> index e961936b6be7..140a9e96ad58 100644
> --- a/net/ipv4/inet_connection_sock.c
> +++ b/net/ipv4/inet_connection_sock.c
> @@ -954,6 +954,9 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
>  	if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
>  		rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);

(Maybe TCP with fastopen could be this other user to call
rcu_assign_pointer()? (net-next material))

> +	if (req->rsk_ops->init_clone)
> +		req->rsk_ops->init_clone(req, nreq);
> +
>  	return nreq;
>  }
>  
> diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> index 4ff5863aa9fd..5f4069647822 100644
> --- a/net/mptcp/subflow.c
> +++ b/net/mptcp/subflow.c
> @@ -47,6 +47,17 @@ static void subflow_req_destructor(struct request_sock *req)
>  	mptcp_token_destroy_request(req);
>  }
>  
> +static void subflow_req_clone(const struct request_sock *req,
> +			      struct request_sock *new_req)
> +{
> +	struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(new_req);
> +
> +	(void)req;


Note: if 'req' is not used, and MPTCP is currently the only user of this
new init_clone() callback, perhaps enough to pass only 'new_req' for the
moment? 'req' can be added later if other users need it, no?

With only init_close(nreq) in a v2, or if TCP maintainers prefer to keep
it, feel free to add:

Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>


Cheers,
Matt
-- 
Sponsored by the NGI0 Core fund.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net 1/1] mptcp: hold subflow request owners when cloning reqsk
  2026-04-16 17:45   ` Matthieu Baerts
@ 2026-04-16 18:48     ` Kuniyuki Iwashima
  2026-04-16 21:18       ` Matthieu Baerts
  0 siblings, 1 reply; 5+ messages in thread
From: Kuniyuki Iwashima @ 2026-04-16 18:48 UTC (permalink / raw)
  To: Matthieu Baerts
  Cc: Ren Wei, netdev, mptcp, davem, edumazet, kuba, pabeni, horms,
	ncardwell, dsahern, martineau, geliang, daniel, kafai, yuantan098,
	yifanwucs, tomapufckgml, bird, caoruide123, enjou1224z

On Thu, Apr 16, 2026 at 10:45 AM Matthieu Baerts <matttbe@kernel.org> wrote:
>
> Hi Ren,
>
> On 15/04/2026 11:31, Ren Wei wrote:
> > From: Ruide Cao <caoruide123@gmail.com>
> >
> > TCP request migration clones pending request sockets with
> > inet_reqsk_clone(). For MPTCP MP_JOIN requests this raw-copies
> > subflow_req->msk, but the cloned request does not take a new reference.
> >
> > Both the original and the cloned request can later drop the same msk in
> > subflow_req_destructor(), and a migrated request may keep a dangling msk
> > pointer after the original owner has already been released.
> >
> > Add a request_sock clone callback and let MPTCP grab a reference for cloned
> > subflow requests that carry an msk. This keeps ownership balanced across
> > both successful migrations and failed clone/insert paths without changing
> > other protocols.
>
> Thank you for this patch!
>
> Indeed, it looks like this path has not been covered by the MPTCP test
> suite so far.
>
> By chance, do you have any simpler reproducer using packetdrill? (the
> MPTCP fork)
>
>   https://github.com/multipath-tcp/packetdrill
>
> Also, I see Sashiko is pointing to a potential issue with MP_CAPABLE and
> the token, also only visible with net.ipv4.tcp_migrate_req=1:
>
> https://sashiko.dev/#/patchset/86e2514b533bf4d55d4aa2fdbf1404022e8c9430.1776149210.git.caoruide123%40gmail.com
>
> Are you also looking at that?
>
> > Fixes: c905dee62232 ("tcp: Migrate TCP_NEW_SYN_RECV requests at retransmitting SYN+ACKs.")
> > Cc: stable@kernel.org
> > Reported-by: Yuan Tan <yuantan098@gmail.com>
> > Reported-by: Yifan Wu <yifanwucs@gmail.com>
> > Reported-by: Juefei Pu <tomapufckgml@gmail.com>
> > Reported-by: Xin Liu <bird@lzu.edu.cn>
> > Signed-off-by: Ruide Cao <caoruide123@gmail.com>
> > Tested-by: Ren Wei <enjou1224z@gmail.com>
> > Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
> > ---
> >  include/net/request_sock.h      |  2 ++
> >  net/ipv4/inet_connection_sock.c |  3 +++
> >  net/mptcp/subflow.c             | 13 +++++++++++++
> >  3 files changed, 18 insertions(+)
> >
> > diff --git a/include/net/request_sock.h b/include/net/request_sock.h
> > index 5a9c826a7092..560e464c400f 100644
> > --- a/include/net/request_sock.h
> > +++ b/include/net/request_sock.h
> > @@ -36,6 +36,8 @@ struct request_sock_ops {
> >                                     struct sk_buff *skb,
> >                                     enum sk_rst_reason reason);
> >       void            (*destructor)(struct request_sock *req);
> > +     void            (*init_clone)(const struct request_sock *req,
> > +                                   struct request_sock *new_req);
>
> @TCP/INET maintainers: are you OK with this new function pointer?
>
> Currently, MPTCP is the only user, and "req" is not used, see below.
>
> >  };
> >
> >  struct saved_syn {
> > diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
> > index e961936b6be7..140a9e96ad58 100644
> > --- a/net/ipv4/inet_connection_sock.c
> > +++ b/net/ipv4/inet_connection_sock.c
> > @@ -954,6 +954,9 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
> >       if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
> >               rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
>
> (Maybe TCP with fastopen could be this other user to call
> rcu_assign_pointer()? (net-next material))
>
> > +     if (req->rsk_ops->init_clone)
> > +             req->rsk_ops->init_clone(req, nreq);

I think a simple direct call is better.

#ifdef CONFIG_MPTCP
    if (tcp_rsk(req)->is_mptcp)
        mptcp_reqsk_clone(nreq);
#endif


> > +
> >       return nreq;
> >  }
> >
> > diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> > index 4ff5863aa9fd..5f4069647822 100644
> > --- a/net/mptcp/subflow.c
> > +++ b/net/mptcp/subflow.c
> > @@ -47,6 +47,17 @@ static void subflow_req_destructor(struct request_sock *req)
> >       mptcp_token_destroy_request(req);
> >  }
> >
> > +static void subflow_req_clone(const struct request_sock *req,
> > +                           struct request_sock *new_req)
> > +{
> > +     struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(new_req);
> > +
> > +     (void)req;
>
>
> Note: if 'req' is not used, and MPTCP is currently the only user of this
> new init_clone() callback, perhaps enough to pass only 'new_req' for the
> moment? 'req' can be added later if other users need it, no?
>
> With only init_close(nreq) in a v2, or if TCP maintainers prefer to keep
> it, feel free to add:
>
> Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
>
>
> Cheers,
> Matt
> --
> Sponsored by the NGI0 Core fund.
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net 1/1] mptcp: hold subflow request owners when cloning reqsk
  2026-04-16 18:48     ` Kuniyuki Iwashima
@ 2026-04-16 21:18       ` Matthieu Baerts
  2026-04-17  1:58         ` Kuniyuki Iwashima
  0 siblings, 1 reply; 5+ messages in thread
From: Matthieu Baerts @ 2026-04-16 21:18 UTC (permalink / raw)
  To: Kuniyuki Iwashima
  Cc: Ren Wei, netdev, mptcp, davem, edumazet, kuba, pabeni, horms,
	ncardwell, dsahern, martineau, geliang, daniel, kafai, yuantan098,
	yifanwucs, tomapufckgml, bird, caoruide123, enjou1224z

Hi Kuniyuki,

Thank you for your reply!

16 Apr 2026 20:48:58 Kuniyuki Iwashima <kuniyu@google.com>:

> On Thu, Apr 16, 2026 at 10:45 AM Matthieu Baerts <matttbe@kernel.org> wrote:
>>
>> Hi Ren,
>>
>> On 15/04/2026 11:31, Ren Wei wrote:
>>> From: Ruide Cao <caoruide123@gmail.com>
>>>
>>> TCP request migration clones pending request sockets with
>>> inet_reqsk_clone(). For MPTCP MP_JOIN requests this raw-copies
>>> subflow_req->msk, but the cloned request does not take a new reference.
>>>
>>> Both the original and the cloned request can later drop the same msk in
>>> subflow_req_destructor(), and a migrated request may keep a dangling msk
>>> pointer after the original owner has already been released.
>>>
>>> Add a request_sock clone callback and let MPTCP grab a reference for cloned
>>> subflow requests that carry an msk. This keeps ownership balanced across
>>> both successful migrations and failed clone/insert paths without changing
>>> other protocols.

(...)

>>> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
>>> index e961936b6be7..140a9e96ad58 100644
>>> --- a/net/ipv4/inet_connection_sock.c
>>> +++ b/net/ipv4/inet_connection_sock.c
>>> @@ -954,6 +954,9 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
>>>       if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
>>>               rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
>>
>> (Maybe TCP with fastopen could be this other user to call
>> rcu_assign_pointer()? (net-next material))
>>
>>> +     if (req->rsk_ops->init_clone)
>>> +             req->rsk_ops->init_clone(req, nreq);
>
> I think a simple direct call is better.
>
> #ifdef CONFIG_MPTCP
>     if (tcp_rsk(req)->is_mptcp)
>         mptcp_reqsk_clone(nreq);
> #endif

Fine by me!

I guess it is needed to check the protocol, similar to what is fine with
TFO above:

  if (sk->sk_protocol == IPPROTO_TCP) {
      if TFO
          ...
      if MPTCP (+ifdef)
          ...
  }

Cheers,
Matt

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net 1/1] mptcp: hold subflow request owners when cloning reqsk
  2026-04-16 21:18       ` Matthieu Baerts
@ 2026-04-17  1:58         ` Kuniyuki Iwashima
  0 siblings, 0 replies; 5+ messages in thread
From: Kuniyuki Iwashima @ 2026-04-17  1:58 UTC (permalink / raw)
  To: Matthieu Baerts
  Cc: Ren Wei, netdev, mptcp, davem, edumazet, kuba, pabeni, horms,
	ncardwell, dsahern, martineau, geliang, daniel, kafai, yuantan098,
	yifanwucs, tomapufckgml, bird, caoruide123, enjou1224z

On Thu, Apr 16, 2026 at 2:18 PM Matthieu Baerts <matttbe@kernel.org> wrote:
>
> Hi Kuniyuki,
>
> Thank you for your reply!
>
> 16 Apr 2026 20:48:58 Kuniyuki Iwashima <kuniyu@google.com>:
>
> > On Thu, Apr 16, 2026 at 10:45 AM Matthieu Baerts <matttbe@kernel.org> wrote:
> >>
> >> Hi Ren,
> >>
> >> On 15/04/2026 11:31, Ren Wei wrote:
> >>> From: Ruide Cao <caoruide123@gmail.com>
> >>>
> >>> TCP request migration clones pending request sockets with
> >>> inet_reqsk_clone(). For MPTCP MP_JOIN requests this raw-copies
> >>> subflow_req->msk, but the cloned request does not take a new reference.
> >>>
> >>> Both the original and the cloned request can later drop the same msk in
> >>> subflow_req_destructor(), and a migrated request may keep a dangling msk
> >>> pointer after the original owner has already been released.
> >>>
> >>> Add a request_sock clone callback and let MPTCP grab a reference for cloned
> >>> subflow requests that carry an msk. This keeps ownership balanced across
> >>> both successful migrations and failed clone/insert paths without changing
> >>> other protocols.
>
> (...)
>
> >>> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
> >>> index e961936b6be7..140a9e96ad58 100644
> >>> --- a/net/ipv4/inet_connection_sock.c
> >>> +++ b/net/ipv4/inet_connection_sock.c
> >>> @@ -954,6 +954,9 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
> >>>       if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
> >>>               rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
> >>
> >> (Maybe TCP with fastopen could be this other user to call
> >> rcu_assign_pointer()? (net-next material))
> >>
> >>> +     if (req->rsk_ops->init_clone)
> >>> +             req->rsk_ops->init_clone(req, nreq);
> >
> > I think a simple direct call is better.
> >
> > #ifdef CONFIG_MPTCP
> >     if (tcp_rsk(req)->is_mptcp)
> >         mptcp_reqsk_clone(nreq);
> > #endif
>
> Fine by me!
>
> I guess it is needed to check the protocol, similar to what is fine with
> TFO above:
>
>   if (sk->sk_protocol == IPPROTO_TCP) {

I don't remember why I added this check for TFO,
but I think this is not needed.  The migration feature was
not supported by DCCP and it's already removed anyway.
I'll remove the check once net-next opens.


>       if TFO
>           ...
>       if MPTCP (+ifdef)
>           ...
>   }
>
> Cheers,
> Matt

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-04-17  1:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <cover.1776149210.git.caoruide123@gmail.com>
2026-04-15  9:31 ` [PATCH net 1/1] mptcp: hold subflow request owners when cloning reqsk Ren Wei
2026-04-16 17:45   ` Matthieu Baerts
2026-04-16 18:48     ` Kuniyuki Iwashima
2026-04-16 21:18       ` Matthieu Baerts
2026-04-17  1:58         ` Kuniyuki Iwashima

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox