All of lore.kernel.org
 help / color / mirror / Atom feed
From: kernel test robot <lkp@intel.com>
To: kbuild-all@lists.01.org
Subject: Re: [RFC PATCH 05/13] futex2: Add compatibility entry point for x86_x32 ABI
Date: Wed, 17 Feb 2021 04:19:37 +0800	[thread overview]
Message-ID: <202102170413.yRD6dfTO-lkp@intel.com> (raw)
In-Reply-To: <20210215152404.250281-6-andrealmeid@collabora.com>

[-- Attachment #1: Type: text/plain, Size: 18261 bytes --]

Hi "André,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on tip/locking/core]
[also build test WARNING on tip/x86/asm arm64/for-next/core tip/perf/core linus/master v5.11]
[cannot apply to next-20210216]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Andr-Almeida/Add-futex2-syscalls/20210215-233004
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 3765d01bab73bdb920ef711203978f02cd26e4da
config: x86_64-randconfig-s022-20210215 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-215-g0fb77bb6-dirty
        # https://github.com/0day-ci/linux/commit/e6093387f473950baee3fada6d63ff84621c5463
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Andr-Almeida/Add-futex2-syscalls/20210215-233004
        git checkout e6093387f473950baee3fada6d63ff84621c5463
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


"sparse warnings: (new ones prefixed by >>)"
   kernel/futex2.c:111:21: sparse: sparse: symbol 'futex_table' was not declared. Should it be static?
   kernel/futex2.c:112:14: sparse: sparse: symbol 'futex2_hashsize' was not declared. Should it be static?
   kernel/futex2.c:358:13: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected void const volatile [noderef] __user *ptr @@     got unsigned long [usertype] address @@
   kernel/futex2.c:358:13: sparse:     expected void const volatile [noderef] __user *ptr
   kernel/futex2.c:358:13: sparse:     got unsigned long [usertype] address
   kernel/futex2.c:517:51: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *uaddr @@     got void * @@
   kernel/futex2.c:517:51: sparse:     expected void [noderef] __user *uaddr
   kernel/futex2.c:517:51: sparse:     got void *
   kernel/futex2.c:532:45: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected unsigned int [noderef] [usertype] __user *uaddr @@     got unsigned int [usertype] *[assigned] uaddr @@
   kernel/futex2.c:532:45: sparse:     expected unsigned int [noderef] [usertype] __user *uaddr
   kernel/futex2.c:532:45: sparse:     got unsigned int [usertype] *[assigned] uaddr
   kernel/futex2.c:541:29: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __user *ptr @@     got unsigned int [usertype] *[assigned] uaddr @@
   kernel/futex2.c:541:29: sparse:     expected void const volatile [noderef] __user *ptr
   kernel/futex2.c:541:29: sparse:     got unsigned int [usertype] *[assigned] uaddr
   kernel/futex2.c:828:48: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *uaddr @@     got void *[addressable] uaddr @@
   kernel/futex2.c:828:48: sparse:     expected void [noderef] __user *uaddr
   kernel/futex2.c:828:48: sparse:     got void *[addressable] uaddr
   kernel/futex2.c:1115:19: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected void *uaddr @@     got void [noderef] __user * @@
   kernel/futex2.c:1115:19: sparse:     expected void *uaddr
   kernel/futex2.c:1115:19: sparse:     got void [noderef] __user *
>> kernel/futex2.c:884:57: sparse: sparse: cast removes address space '__user' of expression
>> kernel/futex2.c:884:57: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct compat_futex_waitv [noderef] __user *uwaitv @@     got struct compat_futex_waitv * @@
   kernel/futex2.c:884:57: sparse:     expected struct compat_futex_waitv [noderef] __user *uwaitv
   kernel/futex2.c:884:57: sparse:     got struct compat_futex_waitv *
   kernel/futex2.c:993:13: sparse: sparse: context imbalance in 'futex_double_unlock' - unexpected unlock
   kernel/futex2.c:1012:34: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *uaddr @@     got void *uaddr @@
   kernel/futex2.c:1012:34: sparse:     expected void [noderef] __user *uaddr
   kernel/futex2.c:1012:34: sparse:     got void *uaddr
   kernel/futex2.c:1016:34: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *uaddr @@     got void *uaddr @@
   kernel/futex2.c:1016:34: sparse:     expected void [noderef] __user *uaddr
   kernel/futex2.c:1016:34: sparse:     got void *uaddr
   kernel/futex2.c:1022:42: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *uaddr @@     got void *uaddr @@
   kernel/futex2.c:1022:42: sparse:     expected void [noderef] __user *uaddr
   kernel/futex2.c:1022:42: sparse:     got void *uaddr
   kernel/futex2.c:1028:42: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *uaddr @@     got void *uaddr @@
   kernel/futex2.c:1028:42: sparse:     expected void [noderef] __user *uaddr
   kernel/futex2.c:1028:42: sparse:     got void *uaddr
   kernel/futex2.c:1047:40: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected unsigned int [noderef] [usertype] __user *uaddr @@     got void *uaddr @@
   kernel/futex2.c:1047:40: sparse:     expected unsigned int [noderef] [usertype] __user *uaddr
   kernel/futex2.c:1047:40: sparse:     got void *uaddr
   kernel/futex2.c:1051:21: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __user *ptr @@     got unsigned int [usertype] *[noderef] __user @@
   kernel/futex2.c:1051:21: sparse:     expected void const volatile [noderef] __user *ptr
   kernel/futex2.c:1051:21: sparse:     got unsigned int [usertype] *[noderef] __user
   kernel/futex2.c:1000:19: sparse: sparse: context imbalance in '__se_compat_sys_futex_requeue' - different lock contexts for basic block
   kernel/futex2.c:1199:57: sparse: sparse: cast removes address space '__user' of expression
>> kernel/futex2.c:1199:57: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct compat_futex_requeue [noderef] __user *uaddr @@     got struct compat_futex_requeue * @@
   kernel/futex2.c:1199:57: sparse:     expected struct compat_futex_requeue [noderef] __user *uaddr
   kernel/futex2.c:1199:57: sparse:     got struct compat_futex_requeue *
   kernel/futex2.c:1204:57: sparse: sparse: cast removes address space '__user' of expression
   kernel/futex2.c:1204:57: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct compat_futex_requeue [noderef] __user *uaddr @@     got struct compat_futex_requeue * @@
   kernel/futex2.c:1204:57: sparse:     expected struct compat_futex_requeue [noderef] __user *uaddr
   kernel/futex2.c:1204:57: sparse:     got struct compat_futex_requeue *
   kernel/futex2.c:1012:34: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *uaddr @@     got void *uaddr @@
   kernel/futex2.c:1012:34: sparse:     expected void [noderef] __user *uaddr
   kernel/futex2.c:1012:34: sparse:     got void *uaddr
   kernel/futex2.c:1016:34: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *uaddr @@     got void *uaddr @@
   kernel/futex2.c:1016:34: sparse:     expected void [noderef] __user *uaddr
   kernel/futex2.c:1016:34: sparse:     got void *uaddr
   kernel/futex2.c:1022:42: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *uaddr @@     got void *uaddr @@
   kernel/futex2.c:1022:42: sparse:     expected void [noderef] __user *uaddr
   kernel/futex2.c:1022:42: sparse:     got void *uaddr
   kernel/futex2.c:1028:42: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *uaddr @@     got void *uaddr @@
   kernel/futex2.c:1028:42: sparse:     expected void [noderef] __user *uaddr
   kernel/futex2.c:1028:42: sparse:     got void *uaddr
   kernel/futex2.c:1047:40: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected unsigned int [noderef] [usertype] __user *uaddr @@     got void *uaddr @@
   kernel/futex2.c:1047:40: sparse:     expected unsigned int [noderef] [usertype] __user *uaddr
   kernel/futex2.c:1047:40: sparse:     got void *uaddr
   kernel/futex2.c:1051:21: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __user *ptr @@     got unsigned int [usertype] *[noderef] __user @@
   kernel/futex2.c:1051:21: sparse:     expected void const volatile [noderef] __user *ptr
   kernel/futex2.c:1051:21: sparse:     got unsigned int [usertype] *[noderef] __user
   kernel/futex2.c:1000:19: sparse: sparse: context imbalance in '__se_sys_futex_requeue' - different lock contexts for basic block

vim +/__user +884 kernel/futex2.c

   841	
   842	/**
   843	 * sys_futex_waitv - Wait on a list of futexes
   844	 * @waiters:    List of futexes to wait on
   845	 * @nr_futexes: Length of futexv
   846	 * @flags:      Flag for timeout (monotonic/realtime)
   847	 * @timo:	Optional absolute timeout.
   848	 *
   849	 * Given an array of `struct futex_waitv`, wait on each uaddr. The thread wakes
   850	 * if a futex_wake() is performed at any uaddr. The syscall returns immediately
   851	 * if any waiter has *uaddr != val. *timo is an optional timeout value for the
   852	 * operation. Each waiter has individual flags. The `flags` argument for the
   853	 * syscall should be used solely for specifying the timeout as realtime, if
   854	 * needed. Flags for shared futexes, sizes, etc. should be used on the
   855	 * individual flags of each waiter.
   856	 *
   857	 * Returns the array index of one of the awaken futexes. There's no given
   858	 * information of how many were awakened, or any particular attribute of it (if
   859	 * it's the first awakened, if it is of the smaller index...).
   860	 */
   861	SYSCALL_DEFINE4(futex_waitv, struct futex_waitv __user *, waiters,
   862			unsigned int, nr_futexes, unsigned int, flags,
   863			struct __kernel_timespec __user *, timo)
   864	{
   865		struct futexv_head *futexv;
   866		int ret;
   867	
   868		if (flags & ~FUTEXV_MASK)
   869			return -EINVAL;
   870	
   871		if (!nr_futexes || nr_futexes > FUTEX_WAITV_MAX || !waiters)
   872			return -EINVAL;
   873	
   874		futexv = kmalloc((sizeof(struct futex_waiter) * nr_futexes) +
   875				 sizeof(*futexv), GFP_KERNEL);
   876		if (!futexv)
   877			return -ENOMEM;
   878	
   879		futexv->hint = false;
   880		futexv->task = current;
   881	
   882	#ifdef CONFIG_X86_X32_ABI
   883		if (in_x32_syscall()) {
 > 884			ret = compat_futex_parse_waitv(futexv, (struct compat_futex_waitv *)waiters,
   885						       nr_futexes);
   886		} else
   887	#endif
   888		{
   889			ret = futex_parse_waitv(futexv, waiters, nr_futexes);
   890		}
   891	
   892		if (!ret)
   893			ret = futex_set_timer_and_wait(futexv, nr_futexes, timo, flags);
   894	
   895		kfree(futexv);
   896	
   897		return ret;
   898	}
   899	
   900	/**
   901	 * futex_get_parent - For a given futex in a futexv list, get a pointer to the futexv
   902	 * @waiter: Address of futex in the list
   903	 * @index: Index of futex in the list
   904	 *
   905	 * Return: A pointer to its futexv struct
   906	 */
   907	static inline struct futexv_head *futex_get_parent(uintptr_t waiter,
   908							   unsigned int index)
   909	{
   910		uintptr_t parent = waiter - sizeof(struct futexv_head)
   911				   - (uintptr_t)(index * sizeof(struct futex_waiter));
   912	
   913		return (struct futexv_head *)parent;
   914	}
   915	
   916	/**
   917	 * futex_mark_wake - Find the task to be wake and add it in wake queue
   918	 * @waiter: Waiter to be wake
   919	 * @bucket: Bucket to be decremented
   920	 * @wake_q: Wake queue to insert the task
   921	 */
   922	static void futex_mark_wake(struct futex_waiter *waiter,
   923				    struct futex_bucket *bucket,
   924				    struct wake_q_head *wake_q)
   925	{
   926		struct task_struct *task;
   927		struct futexv_head *parent = futex_get_parent((uintptr_t)waiter,
   928							      waiter->index);
   929	
   930		parent->hint = true;
   931		task = parent->task;
   932		get_task_struct(task);
   933		list_del_init_careful(&waiter->list);
   934		wake_q_add_safe(wake_q, task);
   935		bucket_dec_waiters(bucket);
   936	}
   937	
   938	static inline bool futex_match(struct futex_key key1, struct futex_key key2)
   939	{
   940		return (key1.index == key2.index &&
   941			key1.pointer == key2.pointer &&
   942			key1.offset == key2.offset);
   943	}
   944	
   945	/**
   946	 * sys_futex_wake - Wake a number of futexes waiting on an address
   947	 * @uaddr:   Address of futex to be woken up
   948	 * @nr_wake: Number of futexes waiting in uaddr to be woken up
   949	 * @flags:   Flags for size and shared
   950	 *
   951	 * Wake `nr_wake` threads waiting at uaddr.
   952	 *
   953	 * Returns the number of woken threads on success, error code otherwise.
   954	 */
   955	SYSCALL_DEFINE3(futex_wake, void __user *, uaddr, unsigned int, nr_wake,
   956			unsigned int, flags)
   957	{
   958		bool shared = (flags & FUTEX_SHARED_FLAG) ? true : false;
   959		unsigned int size = flags & FUTEX_SIZE_MASK;
   960		struct futex_waiter waiter, *aux, *tmp;
   961		struct futex_bucket *bucket;
   962		DEFINE_WAKE_Q(wake_q);
   963		int ret = 0;
   964	
   965		if (flags & ~FUTEX2_MASK)
   966			return -EINVAL;
   967	
   968		if (size != FUTEX_32)
   969			return -EINVAL;
   970	
   971		bucket = futex_get_bucket(uaddr, &waiter.key, shared);
   972		if (IS_ERR(bucket))
   973			return PTR_ERR(bucket);
   974	
   975		if (!bucket_get_waiters(bucket) || !nr_wake)
   976			return 0;
   977	
   978		spin_lock(&bucket->lock);
   979		list_for_each_entry_safe(aux, tmp, &bucket->list, list) {
   980			if (futex_match(waiter.key, aux->key)) {
   981				futex_mark_wake(aux, bucket, &wake_q);
   982				if (++ret >= nr_wake)
   983					break;
   984			}
   985		}
   986		spin_unlock(&bucket->lock);
   987	
   988		wake_up_q(&wake_q);
   989	
   990		return ret;
   991	}
   992	
   993	static void futex_double_unlock(struct futex_bucket *b1, struct futex_bucket *b2)
   994	{
   995		spin_unlock(&b1->lock);
   996		if (b1 != b2)
   997			spin_unlock(&b2->lock);
   998	}
   999	
  1000	static inline int __futex_requeue(struct futex_requeue rq1,
  1001					  struct futex_requeue rq2, unsigned int nr_wake,
  1002					  unsigned int nr_requeue, unsigned int cmpval,
  1003					  bool shared1, bool shared2)
  1004	{
  1005		struct futex_waiter w1, w2, *aux, *tmp;
  1006		bool retry = false;
  1007		struct futex_bucket *b1, *b2;
  1008		DEFINE_WAKE_Q(wake_q);
  1009		u32 uval;
  1010		int ret;
  1011	
  1012		b1 = futex_get_bucket(rq1.uaddr, &w1.key, shared1);
  1013		if (IS_ERR(b1))
  1014			return PTR_ERR(b1);
  1015	
  1016		b2 = futex_get_bucket(rq2.uaddr, &w2.key, shared2);
  1017		if (IS_ERR(b2))
  1018			return PTR_ERR(b2);
  1019	
  1020	retry:
  1021		if (shared1 && retry) {
  1022			b1 = futex_get_bucket(rq1.uaddr, &w1.key, shared1);
  1023			if (IS_ERR(b1))
  1024				return PTR_ERR(b1);
  1025		}
  1026	
  1027		if (shared2 && retry) {
> 1028			b2 = futex_get_bucket(rq2.uaddr, &w2.key, shared2);
  1029			if (IS_ERR(b2))
  1030				return PTR_ERR(b2);
  1031		}
  1032	
  1033		bucket_inc_waiters(b2);
  1034		/*
  1035		 * To ensure the locks are taken in the same order for all threads (and
  1036		 * thus avoiding deadlocks), take the "smaller" one first
  1037		 */
  1038		if (b1 <= b2) {
  1039			spin_lock(&b1->lock);
  1040			if (b1 < b2)
  1041				spin_lock_nested(&b2->lock, SINGLE_DEPTH_NESTING);
  1042		} else {
  1043			spin_lock(&b2->lock);
  1044			spin_lock_nested(&b1->lock, SINGLE_DEPTH_NESTING);
  1045		}
  1046	
  1047		ret = futex_get_user(&uval, rq1.uaddr);
  1048	
  1049		if (unlikely(ret)) {
  1050			futex_double_unlock(b1, b2);
  1051			if (__get_user(uval, (u32 * __user)rq1.uaddr))
  1052				return -EFAULT;
  1053	
  1054			bucket_dec_waiters(b2);
  1055			retry = true;
  1056			goto retry;
  1057		}
  1058	
  1059		if (uval != cmpval) {
  1060			futex_double_unlock(b1, b2);
  1061	
  1062			bucket_dec_waiters(b2);
  1063			return -EAGAIN;
  1064		}
  1065	
  1066		list_for_each_entry_safe(aux, tmp, &b1->list, list) {
  1067			if (futex_match(w1.key, aux->key)) {
  1068				if (ret < nr_wake) {
  1069					futex_mark_wake(aux, b1, &wake_q);
  1070					ret++;
  1071					continue;
  1072				}
  1073	
  1074				if (ret >= nr_wake + nr_requeue)
  1075					break;
  1076	
  1077				aux->key.pointer = w2.key.pointer;
  1078				aux->key.index = w2.key.index;
  1079				aux->key.offset = w2.key.offset;
  1080	
  1081				if (b1 != b2) {
  1082					list_del_init_careful(&aux->list);
  1083					bucket_dec_waiters(b1);
  1084	
  1085					list_add_tail(&aux->list, &b2->list);
  1086					bucket_inc_waiters(b2);
  1087				}
  1088				ret++;
  1089			}
  1090		}
  1091	
  1092		futex_double_unlock(b1, b2);
  1093		wake_up_q(&wake_q);
  1094		bucket_dec_waiters(b2);
  1095	
  1096		return ret;
  1097	}
  1098	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 35261 bytes --]

  reply	other threads:[~2021-02-16 20:19 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-15 15:23 [RFC PATCH 00/13] Add futex2 syscalls André Almeida
2021-02-15 15:23 ` [RFC PATCH 01/13] futex2: Implement wait and wake functions André Almeida
2021-02-15 19:59   ` Gabriel Krisman Bertazi
2021-02-18 13:29     ` André Almeida
2021-02-18 15:48       ` Gabriel Krisman Bertazi
2021-02-16  9:02   ` Peter Zijlstra
2021-02-18 20:09     ` André Almeida
2021-02-16  9:35   ` Peter Zijlstra
2021-02-16  9:56   ` Peter Zijlstra
2021-02-16 10:20     ` Sebastian Andrzej Siewior
2021-02-16 12:42       ` Peter Zijlstra
2021-02-16 22:12     ` Gabriel Krisman Bertazi
2021-02-15 15:23 ` [RFC PATCH 02/13] futex2: Add support for shared futexes André Almeida
2021-02-16  4:32   ` kernel test robot
2021-02-15 15:23 ` [RFC PATCH 03/13] futex2: Implement vectorized wait André Almeida
2021-02-15 16:30   ` kernel test robot
2021-02-15 17:15   ` kernel test robot
2021-02-15 20:03   ` Gabriel Krisman Bertazi
2021-02-15 20:06     ` Zebediah Figura
2021-02-15 20:08   ` Gabriel Krisman Bertazi
2021-02-15 15:23 ` [RFC PATCH 04/13] futex2: Implement requeue operation André Almeida
2021-02-15 16:31   ` kernel test robot
2021-02-15 17:28   ` kernel test robot
2021-02-15 17:33   ` kernel test robot
2021-02-15 15:23 ` [RFC PATCH 05/13] futex2: Add compatibility entry point for x86_x32 ABI André Almeida
2021-02-16 20:19   ` kernel test robot [this message]
2021-02-15 15:23 ` [RFC PATCH 06/13] docs: locking: futex2: Add documentation André Almeida
2021-02-16 18:34   ` Randy Dunlap
2021-02-18 19:12     ` André Almeida
2021-02-15 15:23 ` [RFC PATCH 07/13] selftests: futex2: Add wake/wait test André Almeida
2021-02-15 15:23 ` [RFC PATCH 08/13] selftests: futex2: Add timeout test André Almeida
2021-02-15 15:24 ` [RFC PATCH 09/13] selftests: futex2: Add wouldblock test André Almeida
2021-02-15 15:24 ` [RFC PATCH 10/13] selftests: futex2: Add waitv test André Almeida
2021-02-15 15:24 ` [RFC PATCH 11/13] selftests: futex2: Add requeue test André Almeida
2021-02-15 15:24 ` [RFC PATCH 12/13] perf bench: Add futex2 benchmark tests André Almeida
2021-02-15 15:24 ` [RFC PATCH 13/13] kernel: Enable waitpid() for futex2 André Almeida

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=202102170413.yRD6dfTO-lkp@intel.com \
    --to=lkp@intel.com \
    --cc=kbuild-all@lists.01.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.