diff options
Diffstat (limited to 'fs/logfs/readwrite.c')
| -rw-r--r-- | fs/logfs/readwrite.c | 89 | 
1 files changed, 53 insertions, 36 deletions
| diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 2ac4217b7901..e3ab5e5a904c 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);  	} @@ -519,9 +517,9 @@ static int indirect_write_alias(struct super_block *sb,  		ino = page->mapping->host->i_ino;  		logfs_unpack_index(page->index, &bix, &level); -		child = kmap_atomic(page, KM_USER0); +		child = kmap_atomic(page);  		val = child[pos]; -		kunmap_atomic(child, KM_USER0); +		kunmap_atomic(child);  		err = write_one_alias(sb, ino, bix, level, pos, val);  		if (err)  			return err; @@ -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;  } @@ -667,9 +673,9 @@ static void alloc_indirect_block(struct inode *inode, struct page *page,  	alloc_data_block(inode, page);  	block = logfs_block(page); -	array = kmap_atomic(page, KM_USER0); +	array = kmap_atomic(page);  	initialize_block_counters(page, block, array, page_is_empty); -	kunmap_atomic(array, KM_USER0); +	kunmap_atomic(array);  }  static void block_set_pointer(struct page *page, int index, u64 ptr) @@ -679,10 +685,10 @@ static void block_set_pointer(struct page *page, int index, u64 ptr)  	u64 oldptr;  	BUG_ON(!block); -	array = kmap_atomic(page, KM_USER0); +	array = kmap_atomic(page);  	oldptr = be64_to_cpu(array[index]);  	array[index] = cpu_to_be64(ptr); -	kunmap_atomic(array, KM_USER0); +	kunmap_atomic(array);  	SetPageUptodate(page);  	block->full += !!(ptr & LOGFS_FULLY_POPULATED) @@ -695,9 +701,9 @@ static u64 block_get_pointer(struct page *page, int index)  	__be64 *block;  	u64 ptr; -	block = kmap_atomic(page, KM_USER0); +	block = kmap_atomic(page);  	ptr = be64_to_cpu(block[index]); -	kunmap_atomic(block, KM_USER0); +	kunmap_atomic(block);  	return ptr;  } @@ -844,7 +850,7 @@ static u64 seek_holedata_loop(struct inode *inode, u64 bix, int data)  		}  		slot = get_bits(bix, SUBLEVEL(level)); -		rblock = kmap_atomic(page, KM_USER0); +		rblock = kmap_atomic(page);  		while (slot < LOGFS_BLOCK_FACTOR) {  			if (data && (rblock[slot] != 0))  				break; @@ -855,12 +861,12 @@ static u64 seek_holedata_loop(struct inode *inode, u64 bix, int data)  			bix &= ~(increment - 1);  		}  		if (slot >= LOGFS_BLOCK_FACTOR) { -			kunmap_atomic(rblock, KM_USER0); +			kunmap_atomic(rblock);  			logfs_put_read_page(page);  			return bix;  		}  		bofs = be64_to_cpu(rblock[slot]); -		kunmap_atomic(rblock, KM_USER0); +		kunmap_atomic(rblock);  		logfs_put_read_page(page);  		if (!bofs) {  			BUG_ON(data); @@ -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; @@ -1944,9 +1961,9 @@ int logfs_read_inode(struct inode *inode)  	if (IS_ERR(page))  		return PTR_ERR(page); -	di = kmap_atomic(page, KM_USER0); +	di = kmap_atomic(page);  	logfs_disk_to_inode(di, inode); -	kunmap_atomic(di, KM_USER0); +	kunmap_atomic(di);  	move_page_to_inode(inode, page);  	page_cache_release(page);  	return 0; @@ -1965,9 +1982,9 @@ static struct page *inode_to_page(struct inode *inode)  	if (!page)  		return NULL; -	di = kmap_atomic(page, KM_USER0); +	di = kmap_atomic(page);  	logfs_inode_to_disk(inode, di); -	kunmap_atomic(di, KM_USER0); +	kunmap_atomic(di);  	move_inode_to_page(page, inode);  	return page;  } @@ -2024,13 +2041,13 @@ static void logfs_mod_segment_entry(struct super_block *sb, u32 segno,  	if (write)  		alloc_indirect_block(inode, page, 0); -	se = kmap_atomic(page, KM_USER0); +	se = kmap_atomic(page);  	change_se(se + child_no, arg);  	if (write) {  		logfs_set_alias(sb, logfs_block(page), child_no);  		BUG_ON((int)be32_to_cpu(se[child_no].valid) > super->s_segsize);  	} -	kunmap_atomic(se, KM_USER0); +	kunmap_atomic(se);  	logfs_put_write_page(page);  } @@ -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;  } @@ -2228,10 +2245,10 @@ int logfs_inode_write(struct inode *inode, const void *buf, size_t count,  	if (!page)  		return -ENOMEM; -	pagebuf = kmap_atomic(page, KM_USER0); +	pagebuf = kmap_atomic(page);  	memcpy(pagebuf, buf, count);  	flush_dcache_page(page); -	kunmap_atomic(pagebuf, KM_USER0); +	kunmap_atomic(pagebuf);  	if (i_size_read(inode) < pos + LOGFS_BLOCKSIZE)  		i_size_write(inode, pos + LOGFS_BLOCKSIZE); | 
