lkml@looxix.net wrote:
>>Luc Van Oostenryck wrote:
>
>
> <snip>
>
>>Yes, there seems to be something missing.
>>
>>The others fs use something like a mix of calling vmtruncate() and/or
>>something like the code below,
>>either in setattr() or XXX_truncate() (to add in inode_operations and
>>called by vmtruncate if present)
>>
>> page = grab_cache_page(inode->i_mapping, inode->i_size >>
>>PAGE_CACHE_SHIFT) // or attrs->ia_size >> PAGE_CACHE_SHIFT
>> // if needed, fill with zeroes the partial page
>> // there is already a/some function to do this
>> flush_dcache_page(page);
>> unlock_page(page);
>> page_cache_release(page);
>>
>
>
> Forget about this for the moment.
> vmtruncate() is called via inode_settattr() which is done at the and of
> yaffs_setattr()
> And vmtruncate()can call a method "truncate" if implemented
> This method doesn't seems to be needed for the way we actually do the
> truncation/resizing.
>
>
>>I will need to investigate much further.
>>
>
>
> I hadn't enough time yesterday, but there is something that I don't
> understand: in yaffs_setattr() -> yaffs_SetAttributes() ->
> yaffs_ResizeFile(), how the object filesize is changed if newSize >
> oldFileSize ?
>>From what I understand, it this never changed.
OK, I found it.
It is changed by the yaffs_writepage() called by vmtruncate(),
but there is a bug there when we are extending the file.
The problem was detected whe traces in yaffs_writepage() reported the following:
yaffs_writepage at 0001d000, size 000001d8
writepag0: obj = 0e1d8, ino = 0e1d8
^^^^^
Chunk -1 not found zero instead
writepag1: obj = 1d1d8, ino = 0e1d8
^^^^^
I need to check if there is not similar corner case, but the attached patch
seems to indeed solve the problems, at least the test is runnig well now.
> Apart this, I think that in the case of a resizing down, the object header
> can be updated several times: once in yaffs_ResizeFile and once in
> yaffs_SetAttributes.
>
Luc
--- a/fs/yaffs2/yaffs_fs.c Tue Aug 2 20:43:50 2005
+++ b/fs/yaffs2/yaffs_fs.c Thu Aug 4 23:28:08 2005
@@ -479,64 +479,76 @@
}
// writepage inspired by/stolen from smbfs
//
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
#else
static int yaffs_writepage(struct page *page)
#endif
{
struct address_space *mapping = page->mapping;
+ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
struct inode *inode;
unsigned long end_index;
char *buffer;
yaffs_Object *obj;
int nWritten = 0;
unsigned nBytes;
if (!mapping)
BUG();
inode = mapping->host;
if (!inode)
BUG();
+ if (offset > inode->i_size)
+ {
+ T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_writepage at %08x, inode size = %08x!!!\n", (unsigned)(page->index << PAGE_CACHE_SHIFT), (unsigned) inode->i_size));
+ T(YAFFS_TRACE_OS,(KERN_DEBUG" -> don't care!!\n"));
+ return 0;
+ }
+
end_index = inode->i_size >> PAGE_CACHE_SHIFT;
/* easy case */
if (page->index < end_index)
{
nBytes = PAGE_CACHE_SIZE;
}
else
{
nBytes = inode->i_size & (PAGE_CACHE_SIZE-1);
}
// What's happening here?
///* OK, are we completely out? */
//if (page->index >= end_index+1 || !offset)
// return -EIO;
get_page(page);
buffer = kmap(page);
obj = yaffs_InodeToObject(inode);
yaffs_GrossLock(obj->myDev);
+ T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_writepage at %08x, size %08x\n", (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes));
+ T(YAFFS_TRACE_OS,(KERN_DEBUG"writepag0: obj = %05x, ino = %05x\n", (int) obj->variant.fileVariant.fileSize, (int) inode->i_size));
nWritten = yaffs_WriteDataToFile(obj,buffer,page->index << PAGE_CACHE_SHIFT,nBytes,0);
+ T(YAFFS_TRACE_OS,(KERN_DEBUG"writepag1: obj = %05x, ino = %05x\n", (int) obj->variant.fileVariant.fileSize, (int) inode->i_size));
+
yaffs_GrossUnlock(obj->myDev);
kunmap(page);
SetPageUptodate(page);
UnlockPage(page);
put_page(page);
return (nWritten == nBytes) ? 0 : -ENOSPC;
}