Commit f1a15652 authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[PATCH] Write with buffer>2GB returns broken errno (2)

[ Acked by AKPM --RR ]
From:  Kazuto MIYOSHI <miyoshi@hpc.bs1.fc.nec.co.jp>

  On 64-bit platforms, issuing write(2) with buffer larger than
  2GB will return -1 and broken errno (such as 2147483640)
  Requested data itself is written correctly.

  That is because generic_file_write() and other relating functions
  store 'ssize_t written' into 'int err'. Written byte is trimmed to
  int and then sign-extended to a negative ssize_t value, which
  wrongly indicates an error.

  (On 64bit platform, current glibc defines SSIZE_MAX as 'LONG_MAX')
parent e88bb0c4
...@@ -1557,7 +1557,7 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov, ...@@ -1557,7 +1557,7 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
struct page *page; struct page *page;
struct page *cached_page = NULL; struct page *cached_page = NULL;
ssize_t written; ssize_t written;
int err; ssize_t err;
size_t bytes; size_t bytes;
struct pagevec lru_pvec; struct pagevec lru_pvec;
const struct iovec *cur_iov = iov; /* current iovec */ const struct iovec *cur_iov = iov; /* current iovec */
...@@ -1817,7 +1817,7 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const char *buf, ...@@ -1817,7 +1817,7 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const char *buf,
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct inode *inode = file->f_dentry->d_inode->i_mapping->host; struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
int err; ssize_t err;
struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count }; struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count };
BUG_ON(iocb->ki_pos != pos); BUG_ON(iocb->ki_pos != pos);
...@@ -1836,7 +1836,7 @@ ssize_t generic_file_write(struct file *file, const char *buf, ...@@ -1836,7 +1836,7 @@ ssize_t generic_file_write(struct file *file, const char *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct inode *inode = file->f_dentry->d_inode->i_mapping->host; struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
int err; ssize_t err;
struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count }; struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count };
down(&inode->i_sem); down(&inode->i_sem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment