Commit 10794d14 authored by Linus Torvalds's avatar Linus Torvalds

- pre4:

    - truncate really fixed this time. Everybody agrees.
parent 3db9dee5
...@@ -1467,7 +1467,7 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) ...@@ -1467,7 +1467,7 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
break; break;
case SNDCTL_DSP_SETFMT: case SNDCTL_DSP_SETFMT:
if (get_user(ret, (int *) arg) if (get_user(ret, (int *) arg))
return -EFAULT; return -EFAULT;
if (ret != 0) { if (ret != 0) {
......
...@@ -1514,6 +1514,9 @@ static int __block_commit_write(struct inode *inode, struct page *page, ...@@ -1514,6 +1514,9 @@ static int __block_commit_write(struct inode *inode, struct page *page,
bh != head || !block_start; bh != head || !block_start;
block_start=block_end, bh = bh->b_this_page) { block_start=block_end, bh = bh->b_this_page) {
block_end = block_start + blocksize; block_end = block_start + blocksize;
/* This can happen for the truncate case */
if (!buffer_mapped(bh))
continue;
if (block_end <= from || block_start >= to) { if (block_end <= from || block_start >= to) {
if (!buffer_uptodate(bh)) if (!buffer_uptodate(bh))
partial = 1; partial = 1;
...@@ -1721,24 +1724,12 @@ int generic_commit_write(struct file *file, struct page *page, ...@@ -1721,24 +1724,12 @@ int generic_commit_write(struct file *file, struct page *page,
return 0; return 0;
} }
/*
* If it would be '74 that would go into libc...
*/
int mem_is_zero(char *p, unsigned len)
{
while (len--)
if (*p++)
return 0;
return 1;
}
int block_zero_page(struct address_space *mapping, loff_t from, unsigned length) int block_zero_page(struct address_space *mapping, loff_t from, unsigned length)
{ {
unsigned long index = from >> PAGE_CACHE_SHIFT; unsigned long index = from >> PAGE_CACHE_SHIFT;
unsigned offset = from & (PAGE_CACHE_SIZE-1); unsigned offset = from & (PAGE_CACHE_SIZE-1);
struct inode *inode = (struct inode *)mapping->host; struct inode *inode = (struct inode *)mapping->host;
struct page *page; struct page *page;
char *kaddr;
int err; int err;
if (!length) if (!length)
...@@ -1747,21 +1738,19 @@ int block_zero_page(struct address_space *mapping, loff_t from, unsigned length) ...@@ -1747,21 +1738,19 @@ int block_zero_page(struct address_space *mapping, loff_t from, unsigned length)
page = read_cache_page(mapping, index, page = read_cache_page(mapping, index,
(filler_t *)mapping->a_ops->readpage, NULL); (filler_t *)mapping->a_ops->readpage, NULL);
err = PTR_ERR(page); err = PTR_ERR(page);
if (ERR_PTR(page)) if (IS_ERR(page))
goto out; goto out;
lock_page(page); lock_page(page);
err = -EIO; err = -EIO;
if (!Page_Uptodate(page)) if (!Page_Uptodate(page))
goto unlock; goto unlock;
kaddr = (char*)kmap(page);
err = 0; memset((char *) kmap(page) + offset, 0, length);
if (mem_is_zero(kaddr+offset, length))
goto unmap;
memset(kaddr+offset, 0, length);
flush_dcache_page(page); flush_dcache_page(page);
__block_commit_write(inode, page, offset, offset+length); __block_commit_write(inode, page, offset, offset+length);
unmap:
kunmap(page); kunmap(page);
err = 0;
unlock: unlock:
UnlockPage(page); UnlockPage(page);
page_cache_release(page); page_cache_release(page);
......
...@@ -919,8 +919,7 @@ void ext2_truncate (struct inode * inode) ...@@ -919,8 +919,7 @@ void ext2_truncate (struct inode * inode)
>> EXT2_BLOCK_SIZE_BITS(inode->i_sb); >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
tail = (iblock << EXT2_BLOCK_SIZE_BITS(inode->i_sb)) - inode->i_size; tail = (iblock << EXT2_BLOCK_SIZE_BITS(inode->i_sb)) - inode->i_size;
if (block_zero_page(inode->i_mapping, inode->i_size, tail) != 0) block_zero_page(inode->i_mapping, inode->i_size, tail);
return;
n = ext2_block_to_path(inode, iblock, offsets); n = ext2_block_to_path(inode, iblock, offsets);
if (n == 0) if (n == 0)
......
...@@ -1050,9 +1050,20 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *); ...@@ -1050,9 +1050,20 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *);
* This should be a per-architecture thing, to allow different * This should be a per-architecture thing, to allow different
* error and pointer decisions. * error and pointer decisions.
*/ */
#define ERR_PTR(err) ((void *)((long)(err))) static inline void *ERR_PTR(long error)
#define PTR_ERR(ptr) ((long)(ptr)) {
#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) return (void *) error;
}
static inline long PTR_ERR(const void *ptr)
{
return (long) ptr;
}
static inline long IS_ERR(const void *ptr)
{
return (unsigned long)ptr > (unsigned long)-1000L;
}
/* /*
* The bitmask for a lookup event: * The bitmask for a lookup event:
...@@ -1162,7 +1173,7 @@ extern int block_sync_page(struct page *); ...@@ -1162,7 +1173,7 @@ extern int block_sync_page(struct page *);
int generic_block_bmap(struct address_space *, long, get_block_t *); int generic_block_bmap(struct address_space *, long, get_block_t *);
int generic_commit_write(struct file *, struct page *, unsigned, unsigned); int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
int block_zero_page(struct address_space *mapping, loff_t, unsigned); int block_zero_page(struct address_space *, loff_t, unsigned);
extern int generic_file_mmap(struct file *, struct vm_area_struct *); extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *); extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
......
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