diff options
Diffstat (limited to 'fs/jffs2/file.c')
| -rw-r--r-- | fs/jffs2/file.c | 39 | 
1 files changed, 21 insertions, 18 deletions
| diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 60ef3fb707ff..1506673c087e 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,  	struct page *pg;  	struct inode *inode = mapping->host;  	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); +	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); +	struct jffs2_raw_inode ri; +	uint32_t alloc_len = 0;  	pgoff_t index = pos >> PAGE_CACHE_SHIFT;  	uint32_t pageofs = index << PAGE_CACHE_SHIFT;  	int ret = 0; +	jffs2_dbg(1, "%s()\n", __func__); + +	if (pageofs > inode->i_size) { +		ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, +					  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); +		if (ret) +			return ret; +	} + +	mutex_lock(&f->sem);  	pg = grab_cache_page_write_begin(mapping, index, flags); -	if (!pg) +	if (!pg) { +		if (alloc_len) +			jffs2_complete_reservation(c); +		mutex_unlock(&f->sem);  		return -ENOMEM; +	}  	*pagep = pg; -	jffs2_dbg(1, "%s()\n", __func__); - -	if (pageofs > inode->i_size) { +	if (alloc_len) {  		/* Make new hole frag from old EOF to new page */ -		struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -		struct jffs2_raw_inode ri;  		struct jffs2_full_dnode *fn; -		uint32_t alloc_len;  		jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",  			  (unsigned int)inode->i_size, pageofs); -		ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, -					  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); -		if (ret) -			goto out_page; - -		mutex_lock(&f->sem);  		memset(&ri, 0, sizeof(ri));  		ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,  		if (IS_ERR(fn)) {  			ret = PTR_ERR(fn);  			jffs2_complete_reservation(c); -			mutex_unlock(&f->sem);  			goto out_page;  		}  		ret = jffs2_add_full_dnode_to_inode(c, f, fn); @@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,  			jffs2_mark_node_obsolete(c, fn->raw);  			jffs2_free_full_dnode(fn);  			jffs2_complete_reservation(c); -			mutex_unlock(&f->sem);  			goto out_page;  		}  		jffs2_complete_reservation(c);  		inode->i_size = pageofs; -		mutex_unlock(&f->sem);  	}  	/* @@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,  	 * case of a short-copy.  	 */  	if (!PageUptodate(pg)) { -		mutex_lock(&f->sem);  		ret = jffs2_do_readpage_nolock(inode, pg); -		mutex_unlock(&f->sem);  		if (ret)  			goto out_page;  	} +	mutex_unlock(&f->sem);  	jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);  	return ret;  out_page:  	unlock_page(pg);  	page_cache_release(pg); +	mutex_unlock(&f->sem);  	return ret;  } | 
