[v3,2/2] posix: Implement preadv2 and pwritev2

Message ID fadcede9-e1c5-8d17-40fa-578c439de6ba@linaro.org
State Dropped
Headers

Commit Message

Adhemerval Zanella Netto June 5, 2017, 1:37 p.m. UTC
  On 04/06/2017 10:42, H.J. Lu wrote:
> On Sat, Jun 3, 2017 at 8:28 AM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>> On Jun 03 2017, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>>
>>> X32 inherits LO_HI_LONG from x86-64.  If we change x86-64
>>> LO_HI_LONG, x32 needs to redefine LO_HI_LONG.
>>
>> Your LO_HI_LONG_FLAGS doesn't work for x32 either.
>>
> 
> My patch redefined LO_HI_LONG_FLAGS for x32.   Here is an alternate
> patch which defines different LO_HI_LONGs for x86-64 and x32.
> 
> Tested on x86-64 and x32.

Thanks for checking out this, I was being fooled by the compiler.  Patch
looks ok and I am plan to add this patch to check the above patch for correct 
check for invalid flags (which would also have show this issue with LO_HI_LONG
being used on p{read,write}v2).

However it seems to trigger what I think it is a kernel bug on version that
provides p{read,write}v, where preadv2 does fails with EOPNOTSUPP but
pwritev2 does not.  For instance, on x86_64-linux-gnu-x32 and i686-linux-gnu
(4.10.0-21-generic/x86_64):

[...]
[pid  1027] preadv2(3, 0xff96d3d0, 1, 0, 0x8 /* RWF_??? */) = -1 EOPNOTSUPP (Operation not supported)
[pid  1027] pwritev2(3, [{"\0\360bVl\206\4\10\0\0\0\0Z=l\367t\372\226\377\214\362`\367\f\0\0\0\0\320\4\10", 32}], 1, 0, 0x8 /* RWF_??? */) = 32
[...]

And on sparcv9-linux-gnu (4.12.0-rc1-sparc64-smp):

[...]
[pid 139846] preadv2(3, [{iov_base=0xffefcd88, iov_len=32}], 1, 0, 0x8 /* RWF_??? */) = -1 EOPNOTSUPP (Operation not supported)
[pid 139846] pwritev2(3, [{iov_base="\377\357\315\300p\1f\314\0\0\0\0\0\0\0\2p\3@\10\0\2B\260p\3+\330\0\1\21\220", iov_len=32}], 1, 0, 0x8 /* RWF_??? */) = 32
[...]

Any idea why kernel ignores invalid flags for pwritev2? Does it invalidate the testcase?

---

	* misc/tst-preadvwritev2-common.c: New file.
	* misc/tst-preadvwritev2.c (do_test): Add test for invalid flag.
	* misc/tst-preadvwritev64v2.c (do_test): Likewise.

---
  

Patch

diff --git a/misc/tst-preadvwritev2-common.c b/misc/tst-preadvwritev2-common.c
new file mode 100644
index 0000000..a8073e6
--- /dev/null
+++ b/misc/tst-preadvwritev2-common.c
@@ -0,0 +1,46 @@ 
+/* Common function for preadv2 and pwritev2 tests.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+
+static void
+do_test_with_invalid_flags (void)
+{
+  int invalid_flag = 0x1;
+#ifdef RWF_HIPRI
+  invalid_flag <<= 1;
+#endif
+#ifdef RWF_DSYNC
+  invalid_flag <<= 1;
+#endif
+#ifdef RWF_SYNC
+  invalid_flag <<= 1;
+#endif
+
+  char buf[32];
+  const struct iovec vec = { .iov_base = buf, .iov_len = sizeof (buf) };
+  if (preadv2 (temp_fd, &vec, 1, 0, invalid_flag) != -1)
+    FAIL_EXIT1 ("preadv2 did not fail with an invalid flag");
+  if (errno != ENOTSUP)
+    FAIL_EXIT1 ("preadv2 failure did not set errno to ENOTSUP (%d)", errno);
+
+  if (pwritev2 (temp_fd, &vec, 1, 0, invalid_flag) != -1)
+    FAIL_EXIT1 ("pwritev2 did not fail with an invalid flag");
+  if (errno != ENOTSUP)
+    FAIL_EXIT1 ("pwritev2 failure did not set errno to ENOTSUP (%d)", errno);
+}
diff --git a/misc/tst-preadvwritev2.c b/misc/tst-preadvwritev2.c
index cf36272..682c757 100644
--- a/misc/tst-preadvwritev2.c
+++ b/misc/tst-preadvwritev2.c
@@ -23,9 +23,12 @@ 
   pwritev2 (__fd, __iov, __iovcnt, __offset, 0)
 
 #include "tst-preadvwritev-common.c"
+#include "tst-preadvwritev2-common.c"
 
 static int
 do_test (void)
 {
+  do_test_with_invalid_flags ();
+
   return do_test_with_offset (0);
 }
diff --git a/misc/tst-preadvwritev64v2.c b/misc/tst-preadvwritev64v2.c
index 8d0c48e..9ddc762 100644
--- a/misc/tst-preadvwritev64v2.c
+++ b/misc/tst-preadvwritev64v2.c
@@ -25,9 +25,12 @@ 
   pwritev2 (__fd, __iov, __iovcnt, __offset, 0)
 
 #include "tst-preadvwritev-common.c"
+#include "tst-preadvwritev2-common.c"
 
 static int
 do_test (void)
 {
+  do_test_with_invalid_flags ();
+
   return do_test_with_offset (0);
 }