All of lore.kernel.org
 help / color / mirror / Atom feed
* sendfile -EOVERFLOW on AMD64
@ 2004-05-19  8:44 Jan Kasprzak
  0 siblings, 0 replies; 11+ messages in thread
From: Jan Kasprzak @ 2004-05-19  8:44 UTC (permalink / raw)
  To: linux-kernel

	Hello,

today (after the Fedora Core 2 release) I have discovered that my FTP
server (running AMD64) cannot correctly send the >2GB files using sendfile().
The server is ProFTPd, and the strace looks like this:

[...]
alarm(288)                              = 0
sendfile(14, 11, [139377240], 4231263656) = 2008106407
alarm(0)                                = 117
alarm(117)                              = 0
alarm(0)                                = 117
alarm(117)                              = 0
sendfile(14, 11, [2147483647], 2223157249) = -1 EOVERFLOW (Value too large for defined data type)

The image (FC2-i386-DVD.iso) has 4370640896 bytes. The FTP server is native
x86_64 binary, not a 32-bit one.

Thanks for any hints.

-Yenya

-- 
| Jan "Yenya" Kasprzak  <kas at {fi.muni.cz - work | yenya.net - private}> |
| GPG: ID 1024/D3498839      Fingerprint 0D99A7FB206605D7 8B35FCDE05B18A5E |
| http://www.fi.muni.cz/~kas/   Czech Linux Homepage: http://www.linux.cz/ |
 Any compiler or language that likes to hide things like memory allocations
 behind your back just isn't a good choice for a kernel.   --Linus Torvalds

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

* Re: sendfile -EOVERFLOW on AMD64
       [not found] <1XuW9-3G0-23@gated-at.bofh.it>
@ 2004-05-19  9:29 ` Andi Kleen
  2004-05-19 10:38   ` Jan Kasprzak
  0 siblings, 1 reply; 11+ messages in thread
From: Andi Kleen @ 2004-05-19  9:29 UTC (permalink / raw)
  To: Jan Kasprzak; +Cc: linux-kernel

Jan Kasprzak <kas@informatics.muni.cz> writes:
>
> The image (FC2-i386-DVD.iso) has 4370640896 bytes. The FTP server is native
> x86_64 binary, not a 32-bit one.

sys_sendfile limits itself dumbly to 2GB even on 64bit architectures.
This patch should fix it on x86-64, although other 64bit ports may 
need a similar patch. Just removing the limit in read_write 
is not easy, because it would need fixes in all the 32bit emulation
layers.

-Andi

diff -u linux-2.6.6-amd64/include/asm-x86_64/unistd.h-o linux-2.6.6-amd64/include/asm-x86_64/unistd.h
--- linux-2.6.6-amd64/include/asm-x86_64/unistd.h-o	2004-05-09 14:30:09.000000000 +0200
+++ linux-2.6.6-amd64/include/asm-x86_64/unistd.h	2004-05-19 11:27:00.000000000 +0200
@@ -98,7 +98,7 @@
 __SYSCALL(__NR_getpid, sys_getpid)
 
 #define __NR_sendfile                           40
-__SYSCALL(__NR_sendfile, sys_sendfile)
+__SYSCALL(__NR_sendfile, sys_sendfile64)
 #define __NR_socket                             41
 __SYSCALL(__NR_socket, sys_socket)
 #define __NR_connect                            42


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

* Re: sendfile -EOVERFLOW on AMD64
  2004-05-19  9:29 ` sendfile -EOVERFLOW on AMD64 Andi Kleen
@ 2004-05-19 10:38   ` Jan Kasprzak
  2004-05-19 10:58     ` Jakub Jelinek
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Kasprzak @ 2004-05-19 10:38 UTC (permalink / raw)
  To: Andi Kleen; +Cc: linux-kernel

Andi Kleen wrote:
: Jan Kasprzak <kas@informatics.muni.cz> writes:
: >
: > The image (FC2-i386-DVD.iso) has 4370640896 bytes. The FTP server is native
: > x86_64 binary, not a 32-bit one.
: 
: sys_sendfile limits itself dumbly to 2GB even on 64bit architectures.
: This patch should fix it on x86-64, although other 64bit ports may 
: need a similar patch. Just removing the limit in read_write 
: is not easy, because it would need fixes in all the 32bit emulation
: layers.
: 
	It partly helped, thanks. But there is still one more problem
- it looks like sendfile() returns 32-bit value instead of 64-bit.
My debug info looks like this:

sendfile(offset=0, count=4370640896)
    = -767073160, offset=3527894136

where I do

	long val = sendfile(...); printf(...%ld..., val);

-Yenya


-- 
| Jan "Yenya" Kasprzak  <kas at {fi.muni.cz - work | yenya.net - private}> |
| GPG: ID 1024/D3498839      Fingerprint 0D99A7FB206605D7 8B35FCDE05B18A5E |
| http://www.fi.muni.cz/~kas/   Czech Linux Homepage: http://www.linux.cz/ |
 Any compiler or language that likes to hide things like memory allocations
 behind your back just isn't a good choice for a kernel.   --Linus Torvalds

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

* Re: sendfile -EOVERFLOW on AMD64
  2004-05-19 10:38   ` Jan Kasprzak
@ 2004-05-19 10:58     ` Jakub Jelinek
  2004-05-19 11:01       ` Jan Kasprzak
                         ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Jakub Jelinek @ 2004-05-19 10:58 UTC (permalink / raw)
  To: Jan Kasprzak; +Cc: Andi Kleen, linux-kernel

On Wed, May 19, 2004 at 12:38:56PM +0200, Jan Kasprzak wrote:
> Andi Kleen wrote:
> : Jan Kasprzak <kas@informatics.muni.cz> writes:
> : >
> : > The image (FC2-i386-DVD.iso) has 4370640896 bytes. The FTP server is native
> : > x86_64 binary, not a 32-bit one.
> : 
> : sys_sendfile limits itself dumbly to 2GB even on 64bit architectures.
> : This patch should fix it on x86-64, although other 64bit ports may 
> : need a similar patch. Just removing the limit in read_write 
> : is not easy, because it would need fixes in all the 32bit emulation
> : layers.
> : 
> 	It partly helped, thanks. But there is still one more problem
> - it looks like sendfile() returns 32-bit value instead of 64-bit.
> My debug info looks like this:
> 
> sendfile(offset=0, count=4370640896)
>     = -767073160, offset=3527894136
> 
> where I do
> 
> 	long val = sendfile(...); printf(...%ld..., val);

What filesystem you're using?
For XFS I'd expect this:
STATIC ssize_t
linvfs_sendfile(
        struct file             *filp,
        loff_t                  *ppos,
        size_t                  count,
        read_actor_t            actor,
        void                    *target)
{
        vnode_t                 *vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
        int                     error;

        VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, error);
        return error;
}

(note error is int, not ssize_t), but I don't see anything obvious
for other filesystems.

	Jakub

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

* Re: sendfile -EOVERFLOW on AMD64
  2004-05-19 10:58     ` Jakub Jelinek
@ 2004-05-19 11:01       ` Jan Kasprzak
  2004-05-19 11:22         ` Nathan Scott
  2004-05-19 11:13       ` Nathan Scott
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 11+ messages in thread
From: Jan Kasprzak @ 2004-05-19 11:01 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Andi Kleen, linux-kernel

Jakub Jelinek wrote:
: For XFS I'd expect this:
: STATIC ssize_t
: linvfs_sendfile(
:         struct file             *filp,
:         loff_t                  *ppos,
:         size_t                  count,
:         read_actor_t            actor,
:         void                    *target)
: {
:         vnode_t                 *vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
:         int                     error;
: 
:         VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, error);
:         return error;
: }
: 
: (note error is int, not ssize_t), but I don't see anything obvious
: for other filesystems.
: 
	Yes, XFS. I will look at it  in the evening.

Thanks,

-Yenya

-- 
| Jan "Yenya" Kasprzak  <kas at {fi.muni.cz - work | yenya.net - private}> |
| GPG: ID 1024/D3498839      Fingerprint 0D99A7FB206605D7 8B35FCDE05B18A5E |
| http://www.fi.muni.cz/~kas/   Czech Linux Homepage: http://www.linux.cz/ |
 Any compiler or language that likes to hide things like memory allocations
 behind your back just isn't a good choice for a kernel.   --Linus Torvalds

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

* Re: sendfile -EOVERFLOW on AMD64
  2004-05-19 10:58     ` Jakub Jelinek
  2004-05-19 11:01       ` Jan Kasprzak
@ 2004-05-19 11:13       ` Nathan Scott
  2004-05-19 12:44       ` Andi Kleen
  2004-05-19 19:48       ` Jan Kasprzak
  3 siblings, 0 replies; 11+ messages in thread
From: Nathan Scott @ 2004-05-19 11:13 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jan Kasprzak, Andi Kleen, linux-kernel

On Wed, May 19, 2004 at 06:58:06AM -0400, Jakub Jelinek wrote:
> ...
> (note error is int, not ssize_t), but I don't see anything obvious
> for other filesystems.

Thanks, I'll fix that up.

cheers.

-- 
Nathan

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

* Re: sendfile -EOVERFLOW on AMD64
  2004-05-19 11:01       ` Jan Kasprzak
@ 2004-05-19 11:22         ` Nathan Scott
  0 siblings, 0 replies; 11+ messages in thread
From: Nathan Scott @ 2004-05-19 11:22 UTC (permalink / raw)
  To: Jan Kasprzak; +Cc: Jakub Jelinek, Andi Kleen, linux-kernel

On Wed, May 19, 2004 at 01:01:05PM +0200, Jan Kasprzak wrote:
> ...
> 	Yes, XFS. I will look at it  in the evening.
> 
> Thanks,

The only spot needing fixing is that one pointed out above; from
a quick look ssize_t seems to be used correctly in the rest of
the XFS sendfile code.

cheers.

-- 
Nathan

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

* Re: sendfile -EOVERFLOW on AMD64
  2004-05-19 10:58     ` Jakub Jelinek
  2004-05-19 11:01       ` Jan Kasprzak
  2004-05-19 11:13       ` Nathan Scott
@ 2004-05-19 12:44       ` Andi Kleen
  2004-05-19 12:50         ` Jakub Jelinek
  2004-05-19 19:48       ` Jan Kasprzak
  3 siblings, 1 reply; 11+ messages in thread
From: Andi Kleen @ 2004-05-19 12:44 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jan Kasprzak, Andi Kleen, linux-kernel, akpm

> (note error is int, not ssize_t), but I don't see anything obvious
> for other filesystems.

sendfile64 on 32bit hosts seems to be quite fishy too.

It works with ssize_t, which is 32bit only, but there are no checks
that the transfered file is not >4GB.  It would just wrap in this case.
It would be better to add such checks for 32bit hosts to sendfile64.

Or am I missing something?

-Andi

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

* Re: sendfile -EOVERFLOW on AMD64
  2004-05-19 12:44       ` Andi Kleen
@ 2004-05-19 12:50         ` Jakub Jelinek
  2004-05-19 12:57           ` Andi Kleen
  0 siblings, 1 reply; 11+ messages in thread
From: Jakub Jelinek @ 2004-05-19 12:50 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Jan Kasprzak, linux-kernel, akpm

On Wed, May 19, 2004 at 02:44:27PM +0200, Andi Kleen wrote:
> > (note error is int, not ssize_t), but I don't see anything obvious
> > for other filesystems.
> 
> sendfile64 on 32bit hosts seems to be quite fishy too.
> 
> It works with ssize_t, which is 32bit only, but there are no checks
> that the transfered file is not >4GB.  It would just wrap in this case.
> It would be better to add such checks for 32bit hosts to sendfile64.
> 
> Or am I missing something?

The userland prototypes are:
extern ssize_t sendfile (int __out_fd, int __in_fd, off_t *__offset,
                         size_t __count) __THROW;
extern ssize_t sendfile64 (int __out_fd, int __in_fd, __off64_t *__offset,
                           size_t __count) __THROW;
Thus you really cannot transfer more than 4G-1 bytes in one call on 32-bit
arches.
Actually, already any counts >= 2GB-1 might be problematic, but we are
there on the same boat as with e.g. read(2).  For read, POSIX says:
"If the value of nbyte is greater than {SSIZE_MAX}, the result is
implementation-defined."
so portable programs really shouldn't try to transfer more than that
in one go but the kernel certainly should try to handle sizes up to
SIZE_MAX-4096 or something like that.

	Jakub

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

* Re: sendfile -EOVERFLOW on AMD64
  2004-05-19 12:50         ` Jakub Jelinek
@ 2004-05-19 12:57           ` Andi Kleen
  0 siblings, 0 replies; 11+ messages in thread
From: Andi Kleen @ 2004-05-19 12:57 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Andi Kleen, Jan Kasprzak, linux-kernel, akpm

> The userland prototypes are:
> extern ssize_t sendfile (int __out_fd, int __in_fd, off_t *__offset,
>                          size_t __count) __THROW;
> extern ssize_t sendfile64 (int __out_fd, int __in_fd, __off64_t *__offset,
>                            size_t __count) __THROW;
> Thus you really cannot transfer more than 4G-1 bytes in one call on 32-bit
> arches.

True.

> Actually, already any counts >= 2GB-1 might be problematic, but we are
> there on the same boat as with e.g. read(2).  For read, POSIX says:
> "If the value of nbyte is greater than {SSIZE_MAX}, the result is
> implementation-defined."
> so portable programs really shouldn't try to transfer more than that
> in one go but the kernel certainly should try to handle sizes up to
> SIZE_MAX-4096 or something like that.

Hmm, ssize_t is signed. If there are any if (ret < 0) checks in the
kernel it will fail too. So the real limit would be 0x7fffffff

Perhaps that should be enforced like this?


diff -u linux/fs/read_write.c-o linux/fs/read_write.c
--- linux/fs/read_write.c-o	2004-05-18 10:55:54.000000000 +0200
+++ linux/fs/read_write.c	2004-05-19 14:57:06.000000000 +0200
@@ -700,6 +700,9 @@
 	off_t off;
 	ssize_t ret;
 
+	if (sizeof(size_t) == 4 && (int)count < 0)
+		return -EOVERFLOW;
+
 	if (offset) {
 		if (unlikely(get_user(off, offset)))
 			return -EFAULT;
@@ -718,6 +721,9 @@
 	loff_t pos;
 	ssize_t ret;
 
+	if (sizeof(size_t) == 4 && (int)count < 0)
+		return -EOVERFLOW;
+		
 	if (offset) {
 		if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
 			return -EFAULT;

-Andi

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

* Re: sendfile -EOVERFLOW on AMD64
  2004-05-19 10:58     ` Jakub Jelinek
                         ` (2 preceding siblings ...)
  2004-05-19 12:44       ` Andi Kleen
@ 2004-05-19 19:48       ` Jan Kasprzak
  3 siblings, 0 replies; 11+ messages in thread
From: Jan Kasprzak @ 2004-05-19 19:48 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Andi Kleen, linux-kernel

Jakub Jelinek wrote:
:         int                     error;
: 
:         VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, error);
:         return error;
: }
: 
: (note error is int, not ssize_t), but I don't see anything obvious
: for other filesystems.
: 
	Yes, this fixed the problem - now I can sendfile() the whole
DVD image without problem. Thanks, and send both these fixes to Linus.

-Yenya

-- 
| Jan "Yenya" Kasprzak  <kas at {fi.muni.cz - work | yenya.net - private}> |
| GPG: ID 1024/D3498839      Fingerprint 0D99A7FB206605D7 8B35FCDE05B18A5E |
| http://www.fi.muni.cz/~kas/   Czech Linux Homepage: http://www.linux.cz/ |
 Any compiler or language that likes to hide things like memory allocations
 behind your back just isn't a good choice for a kernel.   --Linus Torvalds

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

end of thread, other threads:[~2004-05-19 19:48 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1XuW9-3G0-23@gated-at.bofh.it>
2004-05-19  9:29 ` sendfile -EOVERFLOW on AMD64 Andi Kleen
2004-05-19 10:38   ` Jan Kasprzak
2004-05-19 10:58     ` Jakub Jelinek
2004-05-19 11:01       ` Jan Kasprzak
2004-05-19 11:22         ` Nathan Scott
2004-05-19 11:13       ` Nathan Scott
2004-05-19 12:44       ` Andi Kleen
2004-05-19 12:50         ` Jakub Jelinek
2004-05-19 12:57           ` Andi Kleen
2004-05-19 19:48       ` Jan Kasprzak
2004-05-19  8:44 Jan Kasprzak

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.