<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-size:small">Hi Xu,</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Apr 16, 2020 at 3:29 PM Yang Xu <<a href="mailto:xuyang2018.jy@cn.fujitsu.com" target="_blank">xuyang2018.jy@cn.fujitsu.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Also, add O_DIRECT flag test. This flag was introduced since<br>
commit 9883035ae7ed ("pipes: add a "packetized pipe" mode for writing").<br>
<br>
Signed-off-by: Yang Xu <<a href="mailto:xuyang2018.jy@cn.fujitsu.com" target="_blank">xuyang2018.jy@cn.fujitsu.com</a>><br>
---<br>
include/lapi/fcntl.h | 4 +<br>
runtest/syscalls | 1 -<br>
testcases/kernel/syscalls/pipe2/.gitignore | 1 -<br>
testcases/kernel/syscalls/pipe2/pipe2_01.c | 234 ++++++---------------<br>
testcases/kernel/syscalls/pipe2/pipe2_02.c | 175 ---------------<br>
5 files changed, 65 insertions(+), 350 deletions(-)<br>
delete mode 100644 testcases/kernel/syscalls/pipe2/pipe2_02.c<br>
<br>
diff --git a/include/lapi/fcntl.h b/include/lapi/fcntl.h<br>
index 24aa46e1f..576a18daf 100644<br>
--- a/include/lapi/fcntl.h<br>
+++ b/include/lapi/fcntl.h<br>
@@ -9,6 +9,10 @@<br>
#include <fcntl.h><br>
#include <sys/socket.h><br>
<br>
+#ifndef O_DIRECT<br>
+# define O_DIRECT 040000<br>
+#endif<br>
+<br>
#ifndef O_CLOEXEC<br>
# define O_CLOEXEC 02000000<br>
#endif<br>
diff --git a/runtest/syscalls b/runtest/syscalls<br>
index 44254d7da..79b671d50 100644<br>
--- a/runtest/syscalls<br>
+++ b/runtest/syscalls<br>
@@ -911,7 +911,6 @@ pipe12 pipe12<br>
pipe13 pipe13<br>
<br>
pipe2_01 pipe2_01<br>
-pipe2_02 pipe2_02<br>
<br>
pivot_root01 pivot_root01<br>
<br>
diff --git a/testcases/kernel/syscalls/pipe2/.gitignore b/testcases/kernel/syscalls/pipe2/.gitignore<br>
index cd38bb309..42350bbdc 100644<br>
--- a/testcases/kernel/syscalls/pipe2/.gitignore<br>
+++ b/testcases/kernel/syscalls/pipe2/.gitignore<br>
@@ -1,2 +1 @@<br>
/pipe2_01<br>
-/pipe2_02<br>
diff --git a/testcases/kernel/syscalls/pipe2/pipe2_01.c b/testcases/kernel/syscalls/pipe2/pipe2_01.c<br>
index 5f3ad8f0f..86f3f18d6 100644<br>
--- a/testcases/kernel/syscalls/pipe2/pipe2_01.c<br>
+++ b/testcases/kernel/syscalls/pipe2/pipe2_01.c<br>
@@ -1,186 +1,74 @@<br>
-/******************************************************************************/<br>
-/* */<br>
-/* Copyright (c) Ulrich Drepper <<a href="mailto:drepper@redhat.com" target="_blank">drepper@redhat.com</a>> */<br>
-/* Copyright (c) International Business Machines Corp., 2009 */<br>
-/* */<br>
-/* This program is free software; you can redistribute it and/or modify */<br>
-/* it under the terms of the GNU General Public License as published by */<br>
-/* the Free Software Foundation; either version 2 of the License, or */<br>
-/* (at your option) any later version. */<br>
-/* */<br>
-/* This program is distributed in the hope that it will be useful, */<br>
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */<br>
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */<br>
-/* the GNU General Public License for more details. */<br>
-/* */<br>
-/* You should have received a copy of the GNU General Public License */<br>
-/* along with this program; if not, write to the Free Software */<br>
-/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */<br>
-/* */<br>
-/******************************************************************************/<br>
-/******************************************************************************/<br>
-/* */<br>
-/* File: pipe2_01.c */<br>
-/* */<br>
-/* Description: This Program tests the new system call introduced in 2.6.27. */<br>
-/* Ulrich´s comment as in: */<br>
-/* <a href="http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=ed8cae8ba01348bfd83333f4648dd807b04d7f08" rel="noreferrer" target="_blank">http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=ed8cae8ba01348bfd83333f4648dd807b04d7f08</a> */<br>
-/* says: */<br>
-/* This patch introduces the new syscall pipe2 which is like pipe but it also */<br>
-/* takes an additional parameter which takes a flag value. This patch */<br>
-/* implements the handling of O_CLOEXEC for the flag. I did not add support */<br>
-/* for the new syscall for the architectures which have a special sys_pipe */<br>
-/* implementation. I think the maintainers of those archs have the chance to */<br>
-/* go with the unified implementation but that's up to them. */<br>
-/* */<br>
-/* The implementation introduces do_pipe_flags. I did that instead of */<br>
-/* changing all callers of do_pipe because some of the callers are written in */<br>
-/* assembler. I would probably screw up changing the assembly code. To avoid */<br>
-/* breaking code do_pipe is now a small wrapper around do_pipe_flags. Once */<br>
-/* all callers are changed over to do_pipe_flags the old do_pipe function can */<br>
-/* be removed. */<br>
-/* The following test must be adjusted for architectures other than x86 and */<br>
-/* x86-64 and in case the syscall numbers changed. */<br>
-/* */<br>
-/* Usage: <for command-line> */<br>
-/* pipe2_01 [-c n] [-e][-i n] [-I x] [-p x] [-t] */<br>
-/* where, -c n : Run n copies concurrently. */<br>
-/* -e : Turn on errno logging. */<br>
-/* -i n : Execute test n times. */<br>
-/* -I x : Execute test for x seconds. */<br>
-/* -P x : Pause for x seconds between iterations. */<br>
-/* -t : Turn on syscall timing. */<br>
-/* */<br>
-/* Total Tests: 1 */<br>
-/* */<br>
-/* Test Name: pipe2_01 */<br>
-/* */<br>
-/* Author: Ulrich Drepper <<a href="mailto:drepper@redhat.com" target="_blank">drepper@redhat.com</a>> */<br>
-/* */<br>
-/* History: Created - Jan 13 2009 - Ulrich Drepper <<a href="mailto:drepper@redhat.com" target="_blank">drepper@redhat.com</a>> */<br>
-/* Ported to LTP */<br>
-/* - Jan 13 2009 - Subrata <<a href="mailto:subrata@linux.vnet.ibm.com" target="_blank">subrata@linux.vnet.ibm.com</a>> */<br>
-/******************************************************************************/<br>
-#include <fcntl.h><br>
+// SPDX-License-Identifier: GPL-2.0-or-late<br>
+/*<br>
+ * Copyright (c) Ulrich Drepper <<a href="mailto:drepper@redhat.com" target="_blank">drepper@redhat.com</a>><br>
+ * Copyright (c) International Business Machines Corp., 2009<br>
+ * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.<br>
+ *<br>
+ * Author: Ulrich Drepper <<a href="mailto:drepper@redhat.com" target="_blank">drepper@redhat.com</a>><br>
+ *<br>
+ * History:<br>
+ * Created - Jan 13 2009 - Ulrich Drepper <<a href="mailto:drepper@redhat.com" target="_blank">drepper@redhat.com</a>><br>
+ * Ported to LTP - Jan 13 2009 - Subrata <<a href="mailto:subrata@linux.vnet.ibm.com" target="_blank">subrata@linux.vnet.ibm.com</a>><br>
+ * Converted into new api - Apri 15 2020 - Yang Xu <<a href="mailto:xuyang2018.jy@cn.fujitsu.com" target="_blank">xuyang2018.jy@cn.fujitsu.com</a>><br>
+ */<br>
+#define _GNU_SOURCE<br>
#include <stdio.h><br>
#include <unistd.h><br>
-#include <sys/syscall.h><br>
-#include <errno.h><br>
-<br>
-#include "test.h"<br>
#include "lapi/fcntl.h"<br>
-#include "lapi/syscalls.h"<br>
-<br>
-char *TCID = "pipe2_01";<br>
-int testno;<br>
-int TST_TOTAL = 1;<br>
+#include "tst_test.h"<br>
<br>
-/* Extern Global Functions */<br>
-/******************************************************************************/<br>
-/* */<br>
-/* Function: cleanup */<br>
-/* */<br>
-/* Description: Performs all one time clean up for this test on successful */<br>
-/* completion, premature exit or failure. Closes all temporary */<br>
-/* files, removes all temporary directories exits the test with */<br>
-/* appropriate return code by calling tst_exit() function. */<br>
-/* */<br>
-/* Input: None. */<br>
-/* */<br>
-/* Output: None. */<br>
-/* */<br>
-/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */<br>
-/* On success - Exits calling tst_exit(). With '0' return code. */<br>
-/* */<br>
-/******************************************************************************/<br>
-void cleanup(void)<br>
-{<br>
+static int fds[2];<br>
<br>
- tst_rmdir();<br>
-<br>
-}<br>
+static struct tcase {<br>
+ int flags;<br>
+ int check_cmd;<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">The 'check_cmd' sounds strange here since we don't do any check for the cmd, can we use 'cmd' directly?</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+ int check_read_side;<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">A pipe has a read-end and a write-end. So I prefer to call this 'check_read_end', do you agree?</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+ char *message;<br>
+} tcases[] = {<br>
+ {0, F_GETFD, 1, "Test pipe2 with 0 flag"},<br>
+ {O_CLOEXEC, F_GETFD, 1, "Test pipe2 using O_CLOEXEC flag"},<br>
+ /*<br>
+ * It may get EINVAL error on older kernel because this flag was<br>
+ * introduced since kernel 3.4. We only test flag in write side<br>
+ * because this flag was used to make pipe buffer marked with the<br>
+ * PIPE_BUF_FLAG_PACKET flag. In read side, kernel also check buffer<br>
+ * flag instead of O_DIRECT. So it make no sense to check this flag<br>
+ * in fds[0].<br>
+ */<br>
+ {O_DIRECT, F_GETFL, 0, "Test pipe2 using O_DIRECT flag"},<br>
+ {O_NONBLOCK, F_GETFL, 1, "Test pipe2 using O_NONBLOCK flag"},<br>
+};<br>
<br>
-/* Local Functions */<br>
-/******************************************************************************/<br>
-/* */<br>
-/* Function: setup */<br>
-/* */<br>
-/* Description: Performs all one time setup for this test. This function is */<br>
-/* typically used to capture signals, create temporary dirs */<br>
-/* and temporary files that may be used in the course of this */<br>
-/* test. */<br>
-/* */<br>
-/* Input: None. */<br>
-/* */<br>
-/* Output: None. */<br>
-/* */<br>
-/* Return: On failure - Exits by calling cleanup(). */<br>
-/* On success - returns 0. */<br>
-/* */<br>
-/******************************************************************************/<br>
-void setup(void)<br>
+static void cleanup(void)<br>
{<br>
- /* Capture signals if any */<br>
- /* Create temporary directories */<br>
- TEST_PAUSE;<br>
- tst_tmpdir();<br>
+ if (fds[0] > 0)<br>
+ SAFE_CLOSE(fds[0]);<br>
+ if (fds[1] > 1)<br>
+ SAFE_CLOSE(fds[1]);<br>
}<br>
<br>
-int main(int argc, char *argv[])<br>
+static void verify_pipe2(unsigned int n)<br>
{<br>
- int fd[2], i, coe;<br>
- int lc;<br>
+ struct tcase *tc = &tcases[n];<br>
+ int get_flag = 0, i = 0;<br>
<br>
- tst_parse_opts(argc, argv, NULL, NULL);<br>
- if ((tst_kvercmp(2, 6, 27)) < 0) {<br>
- tst_brkm(TCONF,<br>
- NULL,<br>
- "This test can only run on kernels that are 2.6.27 and higher");<br>
+ tst_res(TINFO, "%s ", tc->message);<br>
+ SAFE_PIPE2(fds, tc->flags);<br>
+ for (i = 0; i < 2; i++) {<br>
+ if (i == 0 && !tc->check_read_side)<br>
+ continue;<br>
+ get_flag = SAFE_FCNTL(fds[i], tc->check_cmd);<br>
+ if ((get_flag && tc->flags) || (tc->flags == get_flag))<br>
+ tst_res(TPASS, "pipe2 fds[%d] gets expected flag(%d)", i, tc->flags);<br>
+ else<br>
+ tst_res(TFAIL, "pipe2 fds[%d] doesn't get expected flag(%d), get flag(%d)",<br>
+ i, tc->flags, get_flag);<br>
}<br>
- setup();<br>
-<br>
- for (lc = 0; TEST_LOOPING(lc); ++lc) {<br>
- tst_count = 0;<br>
- for (testno = 0; testno < TST_TOTAL; ++testno) {<br>
- if (ltp_syscall(__NR_pipe2, fd, 0) != 0) {<br>
- tst_brkm(TFAIL, cleanup, "pipe2(0) failed");<br>
- }<br>
- for (i = 0; i < 2; ++i) {<br>
- coe = fcntl(fd[i], F_GETFD);<br>
- if (coe == -1) {<br>
- tst_brkm(TBROK, cleanup,<br>
- "fcntl failed");<br>
- }<br>
- if (coe & FD_CLOEXEC) {<br>
- tst_brkm(TFAIL,<br>
- cleanup, "pipe2(0) set close-on-exit for fd[%d]",<br>
- i);<br>
- }<br>
- }<br>
- close(fd[0]);<br>
- close(fd[1]);<br>
-<br>
- if (ltp_syscall(__NR_pipe2, fd, O_CLOEXEC) != 0) {<br>
- tst_brkm(TFAIL, cleanup,<br>
- "pipe2(O_CLOEXEC) failed");<br>
- }<br>
- for (i = 0; i < 2; ++i) {<br>
- coe = fcntl(fd[i], F_GETFD);<br>
- if (coe == -1) {<br>
- tst_brkm(TBROK, cleanup,<br>
- "fcntl failed");<br>
- }<br>
- if ((coe & FD_CLOEXEC) == 0) {<br>
- tst_brkm(TFAIL,<br>
- cleanup, "pipe2(O_CLOEXEC) does not set close-on-exit for fd[%d]",<br>
- i);<br>
- }<br>
- }<br>
- close(fd[0]);<br>
- close(fd[1]);<br>
- tst_resm(TPASS, "pipe2(O_CLOEXEC) PASSED");<br>
- cleanup();<br>
- }<br>
- }<br>
- tst_exit();<br>
+ cleanup();<br>
}<br>
+<br>
+static struct tst_test test = {<br>
+ .tcnt = ARRAY_SIZE(tcases),<br>
+ .test = verify_pipe2,<br>
+ .cleanup = cleanup,<br>
+};<br>
diff --git a/testcases/kernel/syscalls/pipe2/pipe2_02.c b/testcases/kernel/syscalls/pipe2/pipe2_02.c<br>
deleted file mode 100644<br>
index 39f02ff8c..000000000<br>
--- a/testcases/kernel/syscalls/pipe2/pipe2_02.c<br>
+++ /dev/null<br>
@@ -1,175 +0,0 @@<br>
-/******************************************************************************/<br>
-/* */<br>
-/* Copyright (c) Ulrich Drepper <<a href="mailto:drepper@redhat.com" target="_blank">drepper@redhat.com</a>> */<br>
-/* Copyright (c) International Business Machines Corp., 2009 */<br>
-/* */<br>
-/* This program is free software; you can redistribute it and/or modify */<br>
-/* it under the terms of the GNU General Public License as published by */<br>
-/* the Free Software Foundation; either version 2 of the License, or */<br>
-/* (at your option) any later version. */<br>
-/* */<br>
-/* This program is distributed in the hope that it will be useful, */<br>
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */<br>
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */<br>
-/* the GNU General Public License for more details. */<br>
-/* */<br>
-/* You should have received a copy of the GNU General Public License */<br>
-/* along with this program; if not, write to the Free Software */<br>
-/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */<br>
-/* */<br>
-/******************************************************************************/<br>
-/******************************************************************************/<br>
-/* */<br>
-/* File: pipe2_02.c */<br>
-/* */<br>
-/* Description: This Program tests the new system call introduced in 2.6.27. */<br>
-/* Ulrich´s comment as in: */<br>
-/* <a href="http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=be61a86d7237dd80510615f38ae21d6e1e98660c" rel="noreferrer" target="_blank">http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=be61a86d7237dd80510615f38ae21d6e1e98660c</a> */<br>
-/* which says: */<br>
-/* This patch adds O_NONBLOCK support to pipe2. It is minimally more involved*/<br>
-/* than the patches for eventfd <a href="http://et.al" rel="noreferrer" target="_blank">et.al</a> but still trivial. The interfaces of */<br>
-/* the create_write_pipe and create_read_pipe helper functions were changed */<br>
-/* and the one other caller as well. */<br>
-/* The following test must be adjusted for architectures other than x86 and */<br>
-/* x86-64 and in case the syscall numbers changed. */<br>
-/* */<br>
-/* Usage: <for command-line> */<br>
-/* pipe2_02 [-c n] [-e][-i n] [-I x] [-p x] [-t] */<br>
-/* where, -c n : Run n copies concurrently. */<br>
-/* -e : Turn on errno logging. */<br>
-/* -i n : Execute test n times. */<br>
-/* -I x : Execute test for x seconds. */<br>
-/* -P x : Pause for x seconds between iterations. */<br>
-/* -t : Turn on syscall timing. */<br>
-/* */<br>
-/* Total Tests: 1 */<br>
-/* */<br>
-/* Test Name: pipe2_02 */<br>
-/* */<br>
-/* Author: Ulrich Drepper <<a href="mailto:drepper@redhat.com" target="_blank">drepper@redhat.com</a>> */<br>
-/* */<br>
-/* History: Created - Jan 13 2009 - Ulrich Drepper <<a href="mailto:drepper@redhat.com" target="_blank">drepper@redhat.com</a>> */<br>
-/* Ported to LTP */<br>
-/* - Jan 13 2009 - Subrata <<a href="mailto:subrata@linux.vnet.ibm.com" target="_blank">subrata@linux.vnet.ibm.com</a>> */<br>
-/******************************************************************************/<br>
-#include <fcntl.h><br>
-#include <stdio.h><br>
-#include <unistd.h><br>
-#include <sys/syscall.h><br>
-#include <errno.h><br>
-<br>
-#include "test.h"<br>
-#include "lapi/fcntl.h"<br>
-#include "lapi/syscalls.h"<br>
-<br>
-char *TCID = "pipe2_02";<br>
-int testno;<br>
-int TST_TOTAL = 1;<br>
-<br>
-/* Extern Global Functions */<br>
-/******************************************************************************/<br>
-/* */<br>
-/* Function: cleanup */<br>
-/* */<br>
-/* Description: Performs all one time clean up for this test on successful */<br>
-/* completion, premature exit or failure. Closes all temporary */<br>
-/* files, removes all temporary directories exits the test with */<br>
-/* appropriate return code by calling tst_exit() function. */<br>
-/* */<br>
-/* Input: None. */<br>
-/* */<br>
-/* Output: None. */<br>
-/* */<br>
-/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */<br>
-/* On success - Exits calling tst_exit(). With '0' return code. */<br>
-/* */<br>
-/******************************************************************************/<br>
-void cleanup(void)<br>
-{<br>
-<br>
- tst_rmdir();<br>
-<br>
-}<br>
-<br>
-/* Local Functions */<br>
-/******************************************************************************/<br>
-/* */<br>
-/* Function: setup */<br>
-/* */<br>
-/* Description: Performs all one time setup for this test. This function is */<br>
-/* typically used to capture signals, create temporary dirs */<br>
-/* and temporary files that may be used in the course of this */<br>
-/* test. */<br>
-/* */<br>
-/* Input: None. */<br>
-/* */<br>
-/* Output: None. */<br>
-/* */<br>
-/* Return: On failure - Exits by calling cleanup(). */<br>
-/* On success - returns 0. */<br>
-/* */<br>
-/******************************************************************************/<br>
-void setup(void)<br>
-{<br>
- /* Capture signals if any */<br>
- /* Create temporary directories */<br>
- TEST_PAUSE;<br>
- tst_tmpdir();<br>
-}<br>
-<br>
-int main(int argc, char *argv[])<br>
-{<br>
- int fds[2], fl, i;<br>
- int lc;<br>
-<br>
- tst_parse_opts(argc, argv, NULL, NULL);<br>
- if ((tst_kvercmp(2, 6, 27)) < 0) {<br>
- tst_brkm(TCONF,<br>
- NULL,<br>
- "This test can only run on kernels that are 2.6.27 and higher");<br>
- }<br>
- setup();<br>
-<br>
- for (lc = 0; TEST_LOOPING(lc); ++lc) {<br>
- tst_count = 0;<br>
- for (testno = 0; testno < TST_TOTAL; ++testno) {<br>
- if (ltp_syscall(__NR_pipe2, fds, 0) == -1) {<br>
- tst_brkm(TFAIL, cleanup, "pipe2(0) failed");<br>
- }<br>
- for (i = 0; i < 2; ++i) {<br>
- fl = fcntl(fds[i], F_GETFL);<br>
- if (fl == -1) {<br>
- tst_brkm(TBROK, cleanup,<br>
- "fcntl failed");<br>
- }<br>
- if (fl & O_NONBLOCK) {<br>
- tst_brkm(TFAIL,<br>
- cleanup, "pipe2(0) set non-blocking mode for fds[%d]",<br>
- i);<br>
- }<br>
- close(fds[i]);<br>
- }<br>
-<br>
- if (ltp_syscall(__NR_pipe2, fds, O_NONBLOCK) == -1) {<br>
- tst_brkm(TFAIL, cleanup,<br>
- "pipe2(O_NONBLOCK) failed");<br>
- }<br>
- for (i = 0; i < 2; ++i) {<br>
- fl = fcntl(fds[i], F_GETFL);<br>
- if (fl == -1) {<br>
- tst_brkm(TBROK, cleanup,<br>
- "fcntl failed");<br>
- }<br>
- if ((fl & O_NONBLOCK) == 0) {<br>
- tst_brkm(TFAIL,<br>
- cleanup, "pipe2(O_NONBLOCK) does not set non-blocking mode for fds[%d]\n",<br>
- i);<br>
- }<br>
- close(fds[i]);<br>
- }<br>
- tst_resm(TPASS, "pipe2(O_NONBLOCK) PASSED");<br>
- cleanup();<br>
- }<br>
- }<br>
- tst_exit();<br>
-}<br>
-- <br>
2.23.0<br>
<br>
<br>
<br>
<br>
-- <br>
Mailing list info: <a href="https://lists.linux.it/listinfo/ltp" rel="noreferrer" target="_blank">https://lists.linux.it/listinfo/ltp</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr"><div dir="ltr"><div>Regards,<br></div><div>Li Wang<br></div></div></div></div>