[Yaffs] [PATCH RFC YAFFS] fix writepage when extending a file

Luc Van Oostenryck lkml at looxix.net
Thu Aug 4 22:37:12 BST 2005


lkml at 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
-------------- next part --------------
--- 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;
 }
 
 
 


More information about the yaffs mailing list