diff options
Diffstat (limited to 'fs/logfs/readwrite.c')
| -rw-r--r-- | fs/logfs/readwrite.c | 51 | 
1 files changed, 34 insertions, 17 deletions
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 2ac4217b790..4153e65b014 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -244,8 +244,7 @@ static void preunlock_page(struct super_block *sb, struct page *page, int lock)   * is waiting for s_write_mutex.  We annotate this fact by setting PG_pre_locked   * in addition to PG_locked.   */ -static void logfs_get_wblocks(struct super_block *sb, struct page *page, -		int lock) +void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock)  {  	struct logfs_super *super = logfs_super(sb); @@ -260,8 +259,7 @@ static void logfs_get_wblocks(struct super_block *sb, struct page *page,  	}  } -static void logfs_put_wblocks(struct super_block *sb, struct page *page, -		int lock) +void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock)  {  	struct logfs_super *super = logfs_super(sb); @@ -424,7 +422,7 @@ static void inode_write_block(struct logfs_block *block)  	if (inode->i_ino == LOGFS_INO_MASTER)  		logfs_write_anchor(inode->i_sb);  	else { -		ret = __logfs_write_inode(inode, 0); +		ret = __logfs_write_inode(inode, NULL, 0);  		/* see indirect_write_block comment */  		BUG_ON(ret);  	} @@ -560,8 +558,13 @@ static void inode_free_block(struct super_block *sb, struct logfs_block *block)  static void indirect_free_block(struct super_block *sb,  		struct logfs_block *block)  { -	ClearPagePrivate(block->page); -	block->page->private = 0; +	struct page *page = block->page; + +	if (PagePrivate(page)) { +		ClearPagePrivate(page); +		page_cache_release(page); +		set_page_private(page, 0); +	}  	__free_block(sb, block);  } @@ -650,8 +653,11 @@ static void alloc_data_block(struct inode *inode, struct page *page)  	logfs_unpack_index(page->index, &bix, &level);  	block = __alloc_block(inode->i_sb, inode->i_ino, bix, level);  	block->page = page; +  	SetPagePrivate(page); -	page->private = (unsigned long)block; +	page_cache_get(page); +	set_page_private(page, (unsigned long) block); +  	block->ops = &indirect_block_ops;  } @@ -1570,11 +1576,15 @@ int logfs_write_buf(struct inode *inode, struct page *page, long flags)  static int __logfs_delete(struct inode *inode, struct page *page)  {  	long flags = WF_DELETE; +	int err;  	inode->i_ctime = inode->i_mtime = CURRENT_TIME;  	if (page->index < I0_BLOCKS)  		return logfs_write_direct(inode, page, flags); +	err = grow_inode(inode, page->index, 0); +	if (err) +		return err;  	return logfs_write_rec(inode, page, page->index, 0, flags);  } @@ -1623,7 +1633,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,  			if (inode->i_ino == LOGFS_INO_MASTER)  				logfs_write_anchor(inode->i_sb);  			else { -				err = __logfs_write_inode(inode, flags); +				err = __logfs_write_inode(inode, page, flags);  			}  		}  	} @@ -1873,7 +1883,7 @@ int logfs_truncate(struct inode *inode, u64 target)  		logfs_get_wblocks(sb, NULL, 1);  		err = __logfs_truncate(inode, size);  		if (!err) -			err = __logfs_write_inode(inode, 0); +			err = __logfs_write_inode(inode, NULL, 0);  		logfs_put_wblocks(sb, NULL, 1);  	} @@ -1901,8 +1911,11 @@ static void move_page_to_inode(struct inode *inode, struct page *page)  	li->li_block = block;  	block->page = NULL; -	page->private = 0; -	ClearPagePrivate(page); +	if (PagePrivate(page)) { +		ClearPagePrivate(page); +		page_cache_release(page); +		set_page_private(page, 0); +	}  }  static void move_inode_to_page(struct page *page, struct inode *inode) @@ -1918,8 +1931,12 @@ static void move_inode_to_page(struct page *page, struct inode *inode)  	BUG_ON(PagePrivate(page));  	block->ops = &indirect_block_ops;  	block->page = page; -	page->private = (unsigned long)block; -	SetPagePrivate(page); + +	if (!PagePrivate(page)) { +		SetPagePrivate(page); +		page_cache_get(page); +		set_page_private(page, (unsigned long) block); +	}  	block->inode = NULL;  	li->li_block = NULL; @@ -2106,14 +2123,14 @@ void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec)  			ec_level);  } -int __logfs_write_inode(struct inode *inode, long flags) +int __logfs_write_inode(struct inode *inode, struct page *page, long flags)  {  	struct super_block *sb = inode->i_sb;  	int ret; -	logfs_get_wblocks(sb, NULL, flags & WF_LOCK); +	logfs_get_wblocks(sb, page, flags & WF_LOCK);  	ret = do_write_inode(inode); -	logfs_put_wblocks(sb, NULL, flags & WF_LOCK); +	logfs_put_wblocks(sb, page, flags & WF_LOCK);  	return ret;  }  |