[PATCH] ufs: truncate should allocate block for last byte
This patch fixes buggy behaviour of UFS in such kind of scenario: open(, O_TRUNC...) ftruncate(, 1024) ftruncate(, 0) Such a scenario causes ufs_panic and remount read-only. This happen because of according to specification UFS should always allocate block for last byte, and many parts of our implementation rely on this, but `ufs_truncate' doesn't care about this. To make possible return error code and to know about old size, this patch removes `truncate' from ufs inode_operations and uses `setattr' method to call ufs_truncate. Signed-off-by: Evgeniy Dushistov <dushistov@mail.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:

committed by
Linus Torvalds

parent
eb28931e4a
commit
10e5dce07e
@@ -233,3 +233,57 @@ ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev
|
||||
else
|
||||
ufsi->i_u1.i_data[0] = fs32;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufs_get_locked_page() - locate, pin and lock a pagecache page, if not exist
|
||||
* read it from disk.
|
||||
* @mapping: the address_space to search
|
||||
* @index: the page index
|
||||
*
|
||||
* Locates the desired pagecache page, if not exist we'll read it,
|
||||
* locks it, increments its reference
|
||||
* count and returns its address.
|
||||
*
|
||||
*/
|
||||
|
||||
struct page *ufs_get_locked_page(struct address_space *mapping,
|
||||
pgoff_t index)
|
||||
{
|
||||
struct page *page;
|
||||
|
||||
try_again:
|
||||
page = find_lock_page(mapping, index);
|
||||
if (!page) {
|
||||
page = read_cache_page(mapping, index,
|
||||
(filler_t*)mapping->a_ops->readpage,
|
||||
NULL);
|
||||
if (IS_ERR(page)) {
|
||||
printk(KERN_ERR "ufs_change_blocknr: "
|
||||
"read_cache_page error: ino %lu, index: %lu\n",
|
||||
mapping->host->i_ino, index);
|
||||
goto out;
|
||||
}
|
||||
|
||||
lock_page(page);
|
||||
|
||||
if (!PageUptodate(page) || PageError(page)) {
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
|
||||
printk(KERN_ERR "ufs_change_blocknr: "
|
||||
"can not read page: ino %lu, index: %lu\n",
|
||||
mapping->host->i_ino, index);
|
||||
|
||||
page = ERR_PTR(-EIO);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(!page->mapping || !page_has_buffers(page))) {
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
goto try_again;/*we really need these buffers*/
|
||||
}
|
||||
out:
|
||||
return page;
|
||||
}
|
||||
|
Reference in New Issue
Block a user