Re: [PATCH v2] splice: sendfile() at once fails for big files

2015-05-06 Thread Jens Axboe

On 05/06/2015 08:40 AM, Jens Axboe wrote:

On 05/06/2015 08:38 AM, leroy christophe wrote:


Le 06/05/2015 16:23, Jens Axboe a écrit :

On 05/05/2015 09:41 PM, Linus Torvalds wrote:

Jens, ping?

The test results should make this a no-brainer, but I hate how random
these flag ops.


Missed the original, apparently. I too am confused how this is a
correctness fix and not just an optimization.

+   if (read_len < len)
+   sd->flags |= SPLICE_F_MORE;
+   else if (!more)
+   sd->flags &= ~SPLICE_F_MORE;

Should that check be for 'more', not '!more'?



@@ -1204,6 +1204,7 @@ ssize_t splice_direct_to_actor(struct file *in,
struct splice_desc *sd,
   * Don't block on output, we have to drain the direct pipe.
   */
  sd->flags &= ~SPLICE_F_NONBLOCK;
+more = sd->flags & SPLICE_F_MORE;

  while (len) {
  size_t read_len;
@@ -1216,6 +1217,10 @@ ssize_t splice_direct_to_actor(struct file *in,
struct splice_desc *sd,
  read_len = ret;
  sd->total_len = read_len;

+if (read_len < len)
+sd->flags |= SPLICE_F_MORE;
+else if (!more)
+sd->flags &= ~SPLICE_F_MORE;



'more' contains whether sendfile() has been called with SPLICE_F_MORE or
not.
Until all bytes are processed, we have to force SPLICE_F_MORE regardless
of how sendfile() was called.
Once all bytes have been read, we have to reset the flags according to
how sendfile() was called, so if 'more' is NOT set, we have to clear
SPLICE_F_MORE from sd->flags (which was unconditionaly set for
processing the first bytes)


Ah gotcha, that looks correct. Patch is fine with me then.


Needs a comment added to that effect, imho.

--
Jens Axboe

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] splice: sendfile() at once fails for big files

2015-05-06 Thread Jens Axboe

On 05/06/2015 08:38 AM, leroy christophe wrote:


Le 06/05/2015 16:23, Jens Axboe a écrit :

On 05/05/2015 09:41 PM, Linus Torvalds wrote:

Jens, ping?

The test results should make this a no-brainer, but I hate how random
these flag ops.


Missed the original, apparently. I too am confused how this is a
correctness fix and not just an optimization.

+   if (read_len < len)
+   sd->flags |= SPLICE_F_MORE;
+   else if (!more)
+   sd->flags &= ~SPLICE_F_MORE;

Should that check be for 'more', not '!more'?



@@ -1204,6 +1204,7 @@ ssize_t splice_direct_to_actor(struct file *in,
struct splice_desc *sd,
   * Don't block on output, we have to drain the direct pipe.
   */
  sd->flags &= ~SPLICE_F_NONBLOCK;
+more = sd->flags & SPLICE_F_MORE;

  while (len) {
  size_t read_len;
@@ -1216,6 +1217,10 @@ ssize_t splice_direct_to_actor(struct file *in,
struct splice_desc *sd,
  read_len = ret;
  sd->total_len = read_len;

+if (read_len < len)
+sd->flags |= SPLICE_F_MORE;
+else if (!more)
+sd->flags &= ~SPLICE_F_MORE;



'more' contains whether sendfile() has been called with SPLICE_F_MORE or
not.
Until all bytes are processed, we have to force SPLICE_F_MORE regardless
of how sendfile() was called.
Once all bytes have been read, we have to reset the flags according to
how sendfile() was called, so if 'more' is NOT set, we have to clear
SPLICE_F_MORE from sd->flags (which was unconditionaly set for
processing the first bytes)


Ah gotcha, that looks correct. Patch is fine with me then.

--
Jens Axboe

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] splice: sendfile() at once fails for big files

2015-05-06 Thread leroy christophe


Le 06/05/2015 16:23, Jens Axboe a écrit :

On 05/05/2015 09:41 PM, Linus Torvalds wrote:

Jens, ping?

The test results should make this a no-brainer, but I hate how random
these flag ops.


Missed the original, apparently. I too am confused how this is a
correctness fix and not just an optimization.

+   if (read_len < len)
+   sd->flags |= SPLICE_F_MORE;
+   else if (!more)
+   sd->flags &= ~SPLICE_F_MORE;

Should that check be for 'more', not '!more'?


@@ -1204,6 +1204,7 @@ ssize_t splice_direct_to_actor(struct file *in, 
struct splice_desc *sd,

  * Don't block on output, we have to drain the direct pipe.
  */
 sd->flags &= ~SPLICE_F_NONBLOCK;
+more = sd->flags & SPLICE_F_MORE;

 while (len) {
 size_t read_len;
@@ -1216,6 +1217,10 @@ ssize_t splice_direct_to_actor(struct file *in, 
struct splice_desc *sd,

 read_len = ret;
 sd->total_len = read_len;

+if (read_len < len)
+sd->flags |= SPLICE_F_MORE;
+else if (!more)
+sd->flags &= ~SPLICE_F_MORE;



'more' contains whether sendfile() has been called with SPLICE_F_MORE or 
not.
Until all bytes are processed, we have to force SPLICE_F_MORE regardless 
of how sendfile() was called.
Once all bytes have been read, we have to reset the flags according to 
how sendfile() was called, so if 'more' is NOT set, we have to clear 
SPLICE_F_MORE from sd->flags (which was unconditionaly set for 
processing the first bytes)


Christophe
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] splice: sendfile() at once fails for big files

2015-05-06 Thread Jens Axboe

On 05/05/2015 09:41 PM, Linus Torvalds wrote:

Jens, ping?

The test results should make this a no-brainer, but I hate how random
these flag ops.


Missed the original, apparently. I too am confused how this is a 
correctness fix and not just an optimization.


+   if (read_len < len)
+   sd->flags |= SPLICE_F_MORE;
+   else if (!more)
+   sd->flags &= ~SPLICE_F_MORE;

Should that check be for 'more', not '!more'?


--
Jens Axboe

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] splice: sendfile() at once fails for big files

2015-05-05 Thread Christoph Hellwig
On Tue, May 05, 2015 at 08:41:05PM -0700, Linus Torvalds wrote:
> Jens, ping?
> 
> The test results should make this a no-brainer, but I hate how random
> these flag ops.

Not Jens here, but:

 (a) the patch looks correct, we do want to set the more flag if there
 is more data
 (b) I think  the AF_ALG model is totally broken if it relies on that
 for data integrity purposes.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] splice: sendfile() at once fails for big files

2015-05-05 Thread Linus Torvalds
Jens, ping?

The test results should make this a no-brainer, but I hate how random
these flag ops.

  Linus


On Mon, Apr 27, 2015 at 12:01 AM, Herbert Xu
 wrote:
> Christophe Leroy  wrote:
>> Using sendfile with below small program to get MD5 sums of some files,
>> it appear that big files (over 64kbytes with 4k pages system) get a
>> wrong MD5 sum while small files get the correct sum.
>> This program uses sendfile() to send a file to an AF_ALG socket
>> for hashing.
>
> Jens, any comments on this patch?
>
>> /* md5sum2.c */
>> #include 
>> #include 
>> #include 
>> #include 
>> #include 
>> #include 
>> #include 
>> #include 
>> #include 
>>
>> int main(int argc, char **argv)
>> {
>>int sk = socket(AF_ALG, SOCK_SEQPACKET, 0);
>>struct stat st;
>>struct sockaddr_alg sa = {
>>.salg_family = AF_ALG,
>>.salg_type = "hash",
>>.salg_name = "md5",
>>};
>>int n;
>>
>>bind(sk, (struct sockaddr*)&sa, sizeof(sa));
>>
>>for (n = 1; n < argc; n++) {
>>int size;
>>int offset = 0;
>>char buf[4096];
>>int fd;
>>int sko;
>>int i;
>>
>>fd = open(argv[n], O_RDONLY);
>>sko = accept(sk, NULL, 0);
>>fstat(fd, &st);
>>size = st.st_size;
>>sendfile(sko, fd, &offset, size);
>>size = read(sko, buf, sizeof(buf));
>>for (i = 0; i < size; i++)
>>printf("%2.2x", buf[i]);
>>printf("  %s\n", argv[n]);
>>close(fd);
>>close(sko);
>>}
>>exit(0);
>> }
>>
>> Test below is done using official linux patch files. First result is
>> with a software based md5sum. Second result is with the program above.
>>
>> root@vgoip:~# ls -l patch-3.6.*
>> -rw-r--r--1 root root 64011 Aug 24 12:01 patch-3.6.2.gz
>> -rw-r--r--1 root root 94131 Aug 24 12:01 patch-3.6.3.gz
>>
>> root@vgoip:~# md5sum patch-3.6.*
>> b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
>> c5e8f687878457db77cb7158c38a7e43  patch-3.6.3.gz
>>
>> root@vgoip:~# ./md5sum2 patch-3.6.*
>> b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
>> 5fd77b24e68bb24dcc72d6e57c64790e  patch-3.6.3.gz
>>
>>
>> After investivation, it appears that sendfile() sends the files by blocks
>> of 64kbytes (16 times PAGE_SIZE). The problem is that at the end of each
>> block, the SPLICE_F_MORE flag is missing, therefore the hashing operation
>> is reset as if it was the end of the file.
>>
>> This patch adds SPLICE_F_MORE to the flags when more data is pending.
>>
>> With the patch applied, we get the correct sums:
>>
>> root@vgoip:~# md5sum patch-3.6.*
>> b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
>> c5e8f687878457db77cb7158c38a7e43  patch-3.6.3.gz
>>
>> root@vgoip:~# ./md5sum2 patch-3.6.*
>> b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
>> c5e8f687878457db77cb7158c38a7e43  patch-3.6.3.gz
>>
>> Signed-off-by: Christophe Leroy 
>> ---
>> v2: no change, only new commit text
>>
>> fs/splice.c | 7 ++-
>> 1 file changed, 6 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/splice.c b/fs/splice.c
>> index 476024b..fe61723 100644
>> --- a/fs/splice.c
>> +++ b/fs/splice.c
>> @@ -1161,7 +1161,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct 
>> splice_desc *sd,
>>long ret, bytes;
>>umode_t i_mode;
>>size_t len;
>> -   int i, flags;
>> +   int i, flags, more;
>>
>>/*
>> * We require the input being a regular file, as we don't want to
>> @@ -1204,6 +1204,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct 
>> splice_desc *sd,
>> * Don't block on output, we have to drain the direct pipe.
>> */
>>sd->flags &= ~SPLICE_F_NONBLOCK;
>> +   more = sd->flags & SPLICE_F_MORE;
>>
>>while (len) {
>>size_t read_len;
>> @@ -1216,6 +1217,10 @@ ssize_t splice_direct_to_actor(struct file *in, 
>> struct splice_desc *sd,
>>read_len = ret;
>>sd->total_len = read_len;
>>
>> +   if (read_len < len)
>> +   sd->flags |= SPLICE_F_MORE;
>> +   else if (!more)
>> +   sd->flags &= ~SPLICE_F_MORE;
>>/*
>> * NOTE: nonblocking mode only applies to the input. We
>> * must not do the output in nonblocking mode as then we
>
> Thanks,
> --
> Email: Herbert Xu 
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
--
To unsubscribe from this

Re: [PATCH v2] splice: sendfile() at once fails for big files

2015-04-27 Thread Herbert Xu
Christophe Leroy  wrote:
> Using sendfile with below small program to get MD5 sums of some files,
> it appear that big files (over 64kbytes with 4k pages system) get a
> wrong MD5 sum while small files get the correct sum.
> This program uses sendfile() to send a file to an AF_ALG socket
> for hashing.

Jens, any comments on this patch?

> /* md5sum2.c */
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> 
> int main(int argc, char **argv)
> {
>int sk = socket(AF_ALG, SOCK_SEQPACKET, 0);
>struct stat st;
>struct sockaddr_alg sa = {
>.salg_family = AF_ALG,
>.salg_type = "hash",
>.salg_name = "md5",
>};
>int n;
> 
>bind(sk, (struct sockaddr*)&sa, sizeof(sa));
> 
>for (n = 1; n < argc; n++) {
>int size;
>int offset = 0;
>char buf[4096];
>int fd;
>int sko;
>int i;
> 
>fd = open(argv[n], O_RDONLY);
>sko = accept(sk, NULL, 0);
>fstat(fd, &st);
>size = st.st_size;
>sendfile(sko, fd, &offset, size);
>size = read(sko, buf, sizeof(buf));
>for (i = 0; i < size; i++)
>printf("%2.2x", buf[i]);
>printf("  %s\n", argv[n]);
>close(fd);
>close(sko);
>}
>exit(0);
> }
> 
> Test below is done using official linux patch files. First result is
> with a software based md5sum. Second result is with the program above.
> 
> root@vgoip:~# ls -l patch-3.6.*
> -rw-r--r--1 root root 64011 Aug 24 12:01 patch-3.6.2.gz
> -rw-r--r--1 root root 94131 Aug 24 12:01 patch-3.6.3.gz
> 
> root@vgoip:~# md5sum patch-3.6.*
> b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
> c5e8f687878457db77cb7158c38a7e43  patch-3.6.3.gz
> 
> root@vgoip:~# ./md5sum2 patch-3.6.*
> b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
> 5fd77b24e68bb24dcc72d6e57c64790e  patch-3.6.3.gz
> 
> 
> After investivation, it appears that sendfile() sends the files by blocks
> of 64kbytes (16 times PAGE_SIZE). The problem is that at the end of each
> block, the SPLICE_F_MORE flag is missing, therefore the hashing operation
> is reset as if it was the end of the file.
> 
> This patch adds SPLICE_F_MORE to the flags when more data is pending.
> 
> With the patch applied, we get the correct sums:
> 
> root@vgoip:~# md5sum patch-3.6.*
> b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
> c5e8f687878457db77cb7158c38a7e43  patch-3.6.3.gz
> 
> root@vgoip:~# ./md5sum2 patch-3.6.*
> b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
> c5e8f687878457db77cb7158c38a7e43  patch-3.6.3.gz
> 
> Signed-off-by: Christophe Leroy 
> ---
> v2: no change, only new commit text
> 
> fs/splice.c | 7 ++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/splice.c b/fs/splice.c
> index 476024b..fe61723 100644
> --- a/fs/splice.c
> +++ b/fs/splice.c
> @@ -1161,7 +1161,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct 
> splice_desc *sd,
>long ret, bytes;
>umode_t i_mode;
>size_t len;
> -   int i, flags;
> +   int i, flags, more;
> 
>/*
> * We require the input being a regular file, as we don't want to
> @@ -1204,6 +1204,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct 
> splice_desc *sd,
> * Don't block on output, we have to drain the direct pipe.
> */
>sd->flags &= ~SPLICE_F_NONBLOCK;
> +   more = sd->flags & SPLICE_F_MORE;
> 
>while (len) {
>size_t read_len;
> @@ -1216,6 +1217,10 @@ ssize_t splice_direct_to_actor(struct file *in, struct 
> splice_desc *sd,
>read_len = ret;
>sd->total_len = read_len;
> 
> +   if (read_len < len)
> +   sd->flags |= SPLICE_F_MORE;
> +   else if (!more)
> +   sd->flags &= ~SPLICE_F_MORE;
>/*
> * NOTE: nonblocking mode only applies to the input. We
> * must not do the output in nonblocking mode as then we

Thanks,
-- 
Email: Herbert Xu 
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2] splice: sendfile() at once fails for big files

2015-04-23 Thread Christophe Leroy
Using sendfile with below small program to get MD5 sums of some files,
it appear that big files (over 64kbytes with 4k pages system) get a
wrong MD5 sum while small files get the correct sum.
This program uses sendfile() to send a file to an AF_ALG socket
for hashing.


/* md5sum2.c */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char **argv)
{
int sk = socket(AF_ALG, SOCK_SEQPACKET, 0);
struct stat st;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
.salg_name = "md5",
};
int n;

bind(sk, (struct sockaddr*)&sa, sizeof(sa));

for (n = 1; n < argc; n++) {
int size;
int offset = 0;
char buf[4096];
int fd;
int sko;
int i;

fd = open(argv[n], O_RDONLY);
sko = accept(sk, NULL, 0);
fstat(fd, &st);
size = st.st_size;
sendfile(sko, fd, &offset, size);
size = read(sko, buf, sizeof(buf));
for (i = 0; i < size; i++)
printf("%2.2x", buf[i]);
printf("  %s\n", argv[n]);
close(fd);
close(sko);
}
exit(0);
}

Test below is done using official linux patch files. First result is
with a software based md5sum. Second result is with the program above.

root@vgoip:~# ls -l patch-3.6.*
-rw-r--r--1 root root 64011 Aug 24 12:01 patch-3.6.2.gz
-rw-r--r--1 root root 94131 Aug 24 12:01 patch-3.6.3.gz

root@vgoip:~# md5sum patch-3.6.*
b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
c5e8f687878457db77cb7158c38a7e43  patch-3.6.3.gz

root@vgoip:~# ./md5sum2 patch-3.6.*
b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
5fd77b24e68bb24dcc72d6e57c64790e  patch-3.6.3.gz


After investivation, it appears that sendfile() sends the files by blocks
of 64kbytes (16 times PAGE_SIZE). The problem is that at the end of each
block, the SPLICE_F_MORE flag is missing, therefore the hashing operation
is reset as if it was the end of the file.

This patch adds SPLICE_F_MORE to the flags when more data is pending.

With the patch applied, we get the correct sums:

root@vgoip:~# md5sum patch-3.6.*
b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
c5e8f687878457db77cb7158c38a7e43  patch-3.6.3.gz

root@vgoip:~# ./md5sum2 patch-3.6.*
b3ffb9848196846f31b2ff133d2d6443  patch-3.6.2.gz
c5e8f687878457db77cb7158c38a7e43  patch-3.6.3.gz

Signed-off-by: Christophe Leroy 
---
 v2: no change, only new commit text
 
 fs/splice.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/splice.c b/fs/splice.c
index 476024b..fe61723 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1161,7 +1161,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct 
splice_desc *sd,
long ret, bytes;
umode_t i_mode;
size_t len;
-   int i, flags;
+   int i, flags, more;
 
/*
 * We require the input being a regular file, as we don't want to
@@ -1204,6 +1204,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct 
splice_desc *sd,
 * Don't block on output, we have to drain the direct pipe.
 */
sd->flags &= ~SPLICE_F_NONBLOCK;
+   more = sd->flags & SPLICE_F_MORE;
 
while (len) {
size_t read_len;
@@ -1216,6 +1217,10 @@ ssize_t splice_direct_to_actor(struct file *in, struct 
splice_desc *sd,
read_len = ret;
sd->total_len = read_len;
 
+   if (read_len < len)
+   sd->flags |= SPLICE_F_MORE;
+   else if (!more)
+   sd->flags &= ~SPLICE_F_MORE;
/*
 * NOTE: nonblocking mode only applies to the input. We
 * must not do the output in nonblocking mode as then we
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/