diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-03 11:41:43 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-03 11:41:43 -0800 | 
| commit | 2318aa272072f6906de8e00a332da1485506b3c5 (patch) | |
| tree | a305711c90dab041e1c53a00403c90f06989b56b /fs | |
| parent | ed4e6a94d3053b9900b4a1338b8056d532a564c4 (diff) | |
| parent | 9836b8b9499cb25ea32cad9fff640eef874c5431 (diff) | |
| download | linux-2318aa272072f6906de8e00a332da1485506b3c5.tar.bz2 | |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
Pull f2fs bug fixes from Jaegeuk Kim:
 "This patch-set includes two major bug fixes:
   - incorrect IUsed provided by *df -i*, and
   - lookup failure of parent inodes in corner cases.
  [Other Bug Fixes]
   - Fix error handling routines
   - Trigger recovery process correctly
   - Resolve build failures due to missing header files
  [Etc]
   - Add a MAINTAINERS entry for f2fs
   - Fix and clean up variables, functions, and equations
   - Avoid warnings during compilation"
* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs:
  f2fs: unify string length declarations and usage
  f2fs: clean up unused variables and return values
  f2fs: clean up the start_bidx_of_node function
  f2fs: remove unneeded variable from f2fs_sync_fs
  f2fs: fix fsync_inode list addition logic and avoid invalid access to memory
  f2fs: remove unneeded initialization of nr_dirty in dirty_seglist_info
  f2fs: handle error from f2fs_iget_nowait
  f2fs: fix equation of has_not_enough_free_secs()
  f2fs: add MAINTAINERS entry
  f2fs: return a default value for non-void function
  f2fs: invalidate the node page if allocation is failed
  f2fs: add missing #include <linux/prefetch.h>
  f2fs: do f2fs_balance_fs in front of dir operations
  f2fs: should recover orphan and fsync data
  f2fs: fix handling errors got by f2fs_write_inode
  f2fs: fix up f2fs_get_parent issue to retrieve correct parent inode number
  f2fs: fix wrong calculation on f_files in statfs
  f2fs: remove set_page_dirty for atomic f2fs_end_io_write
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/f2fs/data.c | 1 | ||||
| -rw-r--r-- | fs/f2fs/dir.c | 16 | ||||
| -rw-r--r-- | fs/f2fs/f2fs.h | 2 | ||||
| -rw-r--r-- | fs/f2fs/file.c | 10 | ||||
| -rw-r--r-- | fs/f2fs/gc.c | 34 | ||||
| -rw-r--r-- | fs/f2fs/hash.c | 18 | ||||
| -rw-r--r-- | fs/f2fs/inode.c | 1 | ||||
| -rw-r--r-- | fs/f2fs/namei.c | 34 | ||||
| -rw-r--r-- | fs/f2fs/node.c | 37 | ||||
| -rw-r--r-- | fs/f2fs/recovery.c | 10 | ||||
| -rw-r--r-- | fs/f2fs/segment.c | 46 | ||||
| -rw-r--r-- | fs/f2fs/segment.h | 15 | ||||
| -rw-r--r-- | fs/f2fs/super.c | 15 | ||||
| -rw-r--r-- | fs/f2fs/xattr.c | 5 | 
14 files changed, 107 insertions, 137 deletions
| diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 655aeabc1dd4..3aa5ce7cab83 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -16,6 +16,7 @@  #include <linux/backing-dev.h>  #include <linux/blkdev.h>  #include <linux/bio.h> +#include <linux/prefetch.h>  #include "f2fs.h"  #include "node.h" diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index b4e24f32b54e..951ed52748f6 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -11,6 +11,7 @@  #include <linux/fs.h>  #include <linux/f2fs_fs.h>  #include "f2fs.h" +#include "node.h"  #include "acl.h"  static unsigned long dir_blocks(struct inode *inode) @@ -74,7 +75,7 @@ static unsigned long dir_block_index(unsigned int level, unsigned int idx)  	return bidx;  } -static bool early_match_name(const char *name, int namelen, +static bool early_match_name(const char *name, size_t namelen,  			f2fs_hash_t namehash, struct f2fs_dir_entry *de)  {  	if (le16_to_cpu(de->name_len) != namelen) @@ -87,7 +88,7 @@ static bool early_match_name(const char *name, int namelen,  }  static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, -			const char *name, int namelen, int *max_slots, +			const char *name, size_t namelen, int *max_slots,  			f2fs_hash_t namehash, struct page **res_page)  {  	struct f2fs_dir_entry *de; @@ -126,7 +127,7 @@ found:  }  static struct f2fs_dir_entry *find_in_level(struct inode *dir, -		unsigned int level, const char *name, int namelen, +		unsigned int level, const char *name, size_t namelen,  			f2fs_hash_t namehash, struct page **res_page)  {  	int s = GET_DENTRY_SLOTS(namelen); @@ -181,7 +182,7 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,  			struct qstr *child, struct page **res_page)  {  	const char *name = child->name; -	int namelen = child->len; +	size_t namelen = child->len;  	unsigned long npages = dir_blocks(dir);  	struct f2fs_dir_entry *de = NULL;  	f2fs_hash_t name_hash; @@ -308,6 +309,7 @@ static int init_inode_metadata(struct inode *inode, struct dentry *dentry)  		ipage = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino);  		if (IS_ERR(ipage))  			return PTR_ERR(ipage); +		set_cold_node(inode, ipage);  		init_dent_inode(dentry, ipage);  		f2fs_put_page(ipage, 1);  	} @@ -381,7 +383,7 @@ int f2fs_add_link(struct dentry *dentry, struct inode *inode)  	struct inode *dir = dentry->d_parent->d_inode;  	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);  	const char *name = dentry->d_name.name; -	int namelen = dentry->d_name.len; +	size_t namelen = dentry->d_name.len;  	struct page *dentry_page = NULL;  	struct f2fs_dentry_block *dentry_blk = NULL;  	int slots = GET_DENTRY_SLOTS(namelen); @@ -540,13 +542,13 @@ int f2fs_make_empty(struct inode *inode, struct inode *parent)  	de = &dentry_blk->dentry[0];  	de->name_len = cpu_to_le16(1); -	de->hash_code = 0; +	de->hash_code = f2fs_dentry_hash(".", 1);  	de->ino = cpu_to_le32(inode->i_ino);  	memcpy(dentry_blk->filename[0], ".", 1);  	set_de_type(de, inode);  	de = &dentry_blk->dentry[1]; -	de->hash_code = 0; +	de->hash_code = f2fs_dentry_hash("..", 2);  	de->name_len = cpu_to_le16(2);  	de->ino = cpu_to_le32(parent->i_ino);  	memcpy(dentry_blk->filename[1], "..", 2); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index a18d63db2fb6..13c6dfbb7183 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -881,7 +881,7 @@ int f2fs_sync_fs(struct super_block *, int);  /*   * hash.c   */ -f2fs_hash_t f2fs_dentry_hash(const char *, int); +f2fs_hash_t f2fs_dentry_hash(const char *, size_t);  /*   * node.c diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index f9e085dfb1f0..7f9ea9271ebe 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -160,15 +160,17 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)  	if (need_to_sync_dir(sbi, inode))  		need_cp = true; -	f2fs_write_inode(inode, NULL); -  	if (need_cp) {  		/* all the dirty node pages should be flushed for POR */  		ret = f2fs_sync_fs(inode->i_sb, 1);  		clear_inode_flag(F2FS_I(inode), FI_NEED_CP);  	} else { -		while (sync_node_pages(sbi, inode->i_ino, &wbc) == 0) -			f2fs_write_inode(inode, NULL); +		/* if there is no written node page, write its inode page */ +		while (!sync_node_pages(sbi, inode->i_ino, &wbc)) { +			ret = f2fs_write_inode(inode, NULL); +			if (ret) +				goto out; +		}  		filemap_fdatawait_range(sbi->node_inode->i_mapping,  							0, LONG_MAX);  	} diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 644aa3808273..b0ec721e984a 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -390,9 +390,7 @@ next_step:  		}  		err = check_valid_map(sbi, segno, off); -		if (err == GC_ERROR) -			return err; -		else if (err == GC_NEXT) +		if (err == GC_NEXT)  			continue;  		if (initial) { @@ -430,28 +428,22 @@ next_step:   */  block_t start_bidx_of_node(unsigned int node_ofs)  { -	block_t start_bidx; -	unsigned int bidx, indirect_blks; -	int dec; +	unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4; +	unsigned int bidx; -	indirect_blks = 2 * NIDS_PER_BLOCK + 4; +	if (node_ofs == 0) +		return 0; -	start_bidx = 1; -	if (node_ofs == 0) { -		start_bidx = 0; -	} else if (node_ofs <= 2) { +	if (node_ofs <= 2) {  		bidx = node_ofs - 1;  	} else if (node_ofs <= indirect_blks) { -		dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1); +		int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);  		bidx = node_ofs - 2 - dec;  	} else { -		dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1); +		int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);  		bidx = node_ofs - 5 - dec;  	} - -	if (start_bidx) -		start_bidx = bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE; -	return start_bidx; +	return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE;  }  static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, @@ -556,9 +548,7 @@ next_step:  		}  		err = check_valid_map(sbi, segno, off); -		if (err == GC_ERROR) -			goto stop; -		else if (err == GC_NEXT) +		if (err == GC_NEXT)  			continue;  		if (phase == 0) { @@ -568,9 +558,7 @@ next_step:  		/* Get an inode by ino with checking validity */  		err = check_dnode(sbi, entry, &dni, start_addr + off, &nofs); -		if (err == GC_ERROR) -			goto stop; -		else if (err == GC_NEXT) +		if (err == GC_NEXT)  			continue;  		if (phase == 1) { diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c index a60f04200f8b..6eb8d269b53b 100644 --- a/fs/f2fs/hash.c +++ b/fs/f2fs/hash.c @@ -42,7 +42,7 @@ static void TEA_transform(unsigned int buf[4], unsigned int const in[])  	buf[1] += b1;  } -static void str2hashbuf(const char *msg, int len, unsigned int *buf, int num) +static void str2hashbuf(const char *msg, size_t len, unsigned int *buf, int num)  {  	unsigned pad, val;  	int i; @@ -69,13 +69,17 @@ static void str2hashbuf(const char *msg, int len, unsigned int *buf, int num)  		*buf++ = pad;  } -f2fs_hash_t f2fs_dentry_hash(const char *name, int len) +f2fs_hash_t f2fs_dentry_hash(const char *name, size_t len)  { -	__u32 hash, minor_hash; +	__u32 hash;  	f2fs_hash_t f2fs_hash;  	const char *p;  	__u32 in[8], buf[4]; +	if ((len <= 2) && (name[0] == '.') && +		(name[1] == '.' || name[1] == '\0')) +		return 0; +  	/* Initialize the default seed for the hash checksum functions */  	buf[0] = 0x67452301;  	buf[1] = 0xefcdab89; @@ -83,15 +87,15 @@ f2fs_hash_t f2fs_dentry_hash(const char *name, int len)  	buf[3] = 0x10325476;  	p = name; -	while (len > 0) { +	while (1) {  		str2hashbuf(p, len, in, 4);  		TEA_transform(buf, in); -		len -= 16;  		p += 16; +		if (len <= 16) +			break; +		len -= 16;  	}  	hash = buf[0]; -	minor_hash = buf[1]; -  	f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);  	return f2fs_hash;  } diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index df5fb381ebf1..bf20b4d03214 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -203,6 +203,7 @@ void update_inode(struct inode *inode, struct page *node_page)  	ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);  	ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);  	ri->i_generation = cpu_to_le32(inode->i_generation); +	set_cold_node(inode, node_page);  	set_page_dirty(node_page);  } diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 89b7675dc377..1a49b881bac0 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -77,8 +77,8 @@ fail:  static int is_multimedia_file(const unsigned char *s, const char *sub)  { -	int slen = strlen(s); -	int sublen = strlen(sub); +	size_t slen = strlen(s); +	size_t sublen = strlen(sub);  	int ret;  	if (sublen > slen) @@ -123,6 +123,8 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,  	nid_t ino = 0;  	int err; +	f2fs_balance_fs(sbi); +  	inode = f2fs_new_inode(dir, mode);  	if (IS_ERR(inode))  		return PTR_ERR(inode); @@ -144,8 +146,6 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,  	if (!sbi->por_doing)  		d_instantiate(dentry, inode);  	unlock_new_inode(inode); - -	f2fs_balance_fs(sbi);  	return 0;  out:  	clear_nlink(inode); @@ -163,6 +163,8 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir,  	struct f2fs_sb_info *sbi = F2FS_SB(sb);  	int err; +	f2fs_balance_fs(sbi); +  	inode->i_ctime = CURRENT_TIME;  	atomic_inc(&inode->i_count); @@ -172,8 +174,6 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir,  		goto out;  	d_instantiate(dentry, inode); - -	f2fs_balance_fs(sbi);  	return 0;  out:  	clear_inode_flag(F2FS_I(inode), FI_INC_LINK); @@ -223,6 +223,8 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)  	struct page *page;  	int err = -ENOENT; +	f2fs_balance_fs(sbi); +  	de = f2fs_find_entry(dir, &dentry->d_name, &page);  	if (!de)  		goto fail; @@ -238,7 +240,6 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)  	/* In order to evict this inode,  we set it dirty */  	mark_inode_dirty(inode); -	f2fs_balance_fs(sbi);  fail:  	return err;  } @@ -249,9 +250,11 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,  	struct super_block *sb = dir->i_sb;  	struct f2fs_sb_info *sbi = F2FS_SB(sb);  	struct inode *inode; -	unsigned symlen = strlen(symname) + 1; +	size_t symlen = strlen(symname) + 1;  	int err; +	f2fs_balance_fs(sbi); +  	inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);  	if (IS_ERR(inode))  		return PTR_ERR(inode); @@ -268,9 +271,6 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,  	d_instantiate(dentry, inode);  	unlock_new_inode(inode); - -	f2fs_balance_fs(sbi); -  	return err;  out:  	clear_nlink(inode); @@ -286,6 +286,8 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)  	struct inode *inode;  	int err; +	f2fs_balance_fs(sbi); +  	inode = f2fs_new_inode(dir, S_IFDIR | mode);  	if (IS_ERR(inode))  		return PTR_ERR(inode); @@ -305,7 +307,6 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)  	d_instantiate(dentry, inode);  	unlock_new_inode(inode); -	f2fs_balance_fs(sbi);  	return 0;  out_fail: @@ -336,6 +337,8 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry,  	if (!new_valid_dev(rdev))  		return -EINVAL; +	f2fs_balance_fs(sbi); +  	inode = f2fs_new_inode(dir, mode);  	if (IS_ERR(inode))  		return PTR_ERR(inode); @@ -350,9 +353,6 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry,  	alloc_nid_done(sbi, inode->i_ino);  	d_instantiate(dentry, inode);  	unlock_new_inode(inode); - -	f2fs_balance_fs(sbi); -  	return 0;  out:  	clear_nlink(inode); @@ -376,6 +376,8 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,  	struct f2fs_dir_entry *new_entry;  	int err = -ENOENT; +	f2fs_balance_fs(sbi); +  	old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);  	if (!old_entry)  		goto out; @@ -441,8 +443,6 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,  	}  	mutex_unlock_op(sbi, RENAME); - -	f2fs_balance_fs(sbi);  	return 0;  out_dir: diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 19870361497e..5066bfd256c9 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -484,12 +484,14 @@ static void truncate_node(struct dnode_of_data *dn)  	struct node_info ni;  	get_node_info(sbi, dn->nid, &ni); +	if (dn->inode->i_blocks == 0) { +		BUG_ON(ni.blk_addr != NULL_ADDR); +		goto invalidate; +	}  	BUG_ON(ni.blk_addr == NULL_ADDR); -	if (ni.blk_addr != NULL_ADDR) -		invalidate_blocks(sbi, ni.blk_addr); -  	/* Deallocate node address */ +	invalidate_blocks(sbi, ni.blk_addr);  	dec_valid_node_count(sbi, dn->inode, 1);  	set_node_addr(sbi, &ni, NULL_ADDR); @@ -499,7 +501,7 @@ static void truncate_node(struct dnode_of_data *dn)  	} else {  		sync_inode_page(dn);  	} - +invalidate:  	clear_node_page_dirty(dn->node_page);  	F2FS_SET_SB_DIRT(sbi); @@ -768,20 +770,12 @@ int remove_inode_page(struct inode *inode)  		dn.inode_page_locked = 1;  		truncate_node(&dn);  	} -	if (inode->i_blocks == 1) { -		/* inernally call f2fs_put_page() */ -		set_new_dnode(&dn, inode, page, page, ino); -		truncate_node(&dn); -	} else if (inode->i_blocks == 0) { -		struct node_info ni; -		get_node_info(sbi, inode->i_ino, &ni); -		/* called after f2fs_new_inode() is failed */ -		BUG_ON(ni.blk_addr != NULL_ADDR); -		f2fs_put_page(page, 1); -	} else { -		BUG(); -	} +	/* 0 is possible, after f2fs_new_inode() is failed */ +	BUG_ON(inode->i_blocks != 0 && inode->i_blocks != 1); +	set_new_dnode(&dn, inode, page, page, ino); +	truncate_node(&dn); +  	mutex_unlock_op(sbi, NODE_TRUNC);  	return 0;  } @@ -834,17 +828,18 @@ struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)  		goto fail;  	}  	set_node_addr(sbi, &new_ni, NEW_ADDR); +	set_cold_node(dn->inode, page);  	dn->node_page = page;  	sync_inode_page(dn);  	set_page_dirty(page); -	set_cold_node(dn->inode, page);  	if (ofs == 0)  		inc_valid_inode_count(sbi);  	return page;  fail: +	clear_node_page_dirty(page);  	f2fs_put_page(page, 1);  	return ERR_PTR(err);  } @@ -1093,7 +1088,6 @@ static int f2fs_write_node_page(struct page *page,  {  	struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);  	nid_t nid; -	unsigned int nofs;  	block_t new_addr;  	struct node_info ni; @@ -1110,7 +1104,6 @@ static int f2fs_write_node_page(struct page *page,  	/* get old block addr of this node page */  	nid = nid_of_node(page); -	nofs = ofs_of_node(page);  	BUG_ON(page->index != nid);  	get_node_info(sbi, nid, &ni); @@ -1571,7 +1564,7 @@ void flush_nat_entries(struct f2fs_sb_info *sbi)  		nid_t nid;  		struct f2fs_nat_entry raw_ne;  		int offset = -1; -		block_t old_blkaddr, new_blkaddr; +		block_t new_blkaddr;  		ne = list_entry(cur, struct nat_entry, list);  		nid = nat_get_nid(ne); @@ -1585,7 +1578,6 @@ void flush_nat_entries(struct f2fs_sb_info *sbi)  		offset = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 1);  		if (offset >= 0) {  			raw_ne = nat_in_journal(sum, offset); -			old_blkaddr = le32_to_cpu(raw_ne.block_addr);  			goto flush_now;  		}  to_nat_page: @@ -1607,7 +1599,6 @@ to_nat_page:  		BUG_ON(!nat_blk);  		raw_ne = nat_blk->entries[nid - start_nid]; -		old_blkaddr = le32_to_cpu(raw_ne.block_addr);  flush_now:  		new_blkaddr = nat_get_blkaddr(ne); diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index b07e9b6ef376..b571fee677d5 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -144,14 +144,15 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)  				goto out;  			} -			INIT_LIST_HEAD(&entry->list); -			list_add_tail(&entry->list, head); -  			entry->inode = f2fs_iget(sbi->sb, ino_of_node(page));  			if (IS_ERR(entry->inode)) {  				err = PTR_ERR(entry->inode); +				kmem_cache_free(fsync_entry_slab, entry);  				goto out;  			} + +			INIT_LIST_HEAD(&entry->list); +			list_add_tail(&entry->list, head);  			entry->blkaddr = blkaddr;  		}  		if (IS_INODE(page)) { @@ -228,6 +229,9 @@ static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi,  	/* Deallocate previous index in the node page */  	inode = f2fs_iget_nowait(sbi->sb, ino); +	if (IS_ERR(inode)) +		return; +  	truncate_hole(inode, bidx, bidx + 1);  	iput(inode);  } diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 1b26e4ea1016..de6240922b0a 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -12,54 +12,23 @@  #include <linux/f2fs_fs.h>  #include <linux/bio.h>  #include <linux/blkdev.h> +#include <linux/prefetch.h>  #include <linux/vmalloc.h>  #include "f2fs.h"  #include "segment.h"  #include "node.h" -static int need_to_flush(struct f2fs_sb_info *sbi) -{ -	unsigned int pages_per_sec = (1 << sbi->log_blocks_per_seg) * -			sbi->segs_per_sec; -	int node_secs = ((get_pages(sbi, F2FS_DIRTY_NODES) + pages_per_sec - 1) -		>> sbi->log_blocks_per_seg) / sbi->segs_per_sec; -	int dent_secs = ((get_pages(sbi, F2FS_DIRTY_DENTS) + pages_per_sec - 1) -		>> sbi->log_blocks_per_seg) / sbi->segs_per_sec; - -	if (sbi->por_doing) -		return 0; - -	if (free_sections(sbi) <= (node_secs + 2 * dent_secs + -						reserved_sections(sbi))) -		return 1; -	return 0; -} -  /*   * This function balances dirty node and dentry pages.   * In addition, it controls garbage collection.   */  void f2fs_balance_fs(struct f2fs_sb_info *sbi)  { -	struct writeback_control wbc = { -		.sync_mode = WB_SYNC_ALL, -		.nr_to_write = LONG_MAX, -		.for_reclaim = 0, -	}; - -	if (sbi->por_doing) -		return; -  	/* -	 * We should do checkpoint when there are so many dirty node pages -	 * with enough free segments. After then, we should do GC. +	 * We should do GC or end up with checkpoint, if there are so many dirty +	 * dir/node pages without enough free segments.  	 */ -	if (need_to_flush(sbi)) { -		sync_dirty_dir_inodes(sbi); -		sync_node_pages(sbi, 0, &wbc); -	} -  	if (has_not_enough_free_secs(sbi)) {  		mutex_lock(&sbi->gc_mutex);  		f2fs_gc(sbi, 1); @@ -631,7 +600,6 @@ static void f2fs_end_io_write(struct bio *bio, int err)  			if (page->mapping)  				set_bit(AS_EIO, &page->mapping->flags);  			set_ckpt_flags(p->sbi->ckpt, CP_ERROR_FLAG); -			set_page_dirty(page);  		}  		end_page_writeback(page);  		dec_page_count(p->sbi, F2FS_WRITEBACK); @@ -791,11 +759,10 @@ static int __get_segment_type(struct page *page, enum page_type p_type)  		return __get_segment_type_2(page, p_type);  	case 4:  		return __get_segment_type_4(page, p_type); -	case 6: -		return __get_segment_type_6(page, p_type); -	default: -		BUG();  	} +	/* NR_CURSEG_TYPE(6) logs by default */ +	BUG_ON(sbi->active_logs != NR_CURSEG_TYPE); +	return __get_segment_type_6(page, p_type);  }  static void do_write_page(struct f2fs_sb_info *sbi, struct page *page, @@ -1608,7 +1575,6 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi)  	for (i = 0; i < NR_DIRTY_TYPE; i++) {  		dirty_i->dirty_segmap[i] = kzalloc(bitmap_size, GFP_KERNEL); -		dirty_i->nr_dirty[i] = 0;  		if (!dirty_i->dirty_segmap[i])  			return -ENOMEM;  	} diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 0948405af6f5..66a288a52fd3 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -459,7 +459,20 @@ static inline int get_ssr_segment(struct f2fs_sb_info *sbi, int type)  static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi)  { -	return free_sections(sbi) <= reserved_sections(sbi); +	unsigned int pages_per_sec = (1 << sbi->log_blocks_per_seg) * +			sbi->segs_per_sec; +	int node_secs = ((get_pages(sbi, F2FS_DIRTY_NODES) + pages_per_sec - 1) +			>> sbi->log_blocks_per_seg) / sbi->segs_per_sec; +	int dent_secs = ((get_pages(sbi, F2FS_DIRTY_DENTS) + pages_per_sec - 1) +			>> sbi->log_blocks_per_seg) / sbi->segs_per_sec; + +	if (sbi->por_doing) +		return false; + +	if (free_sections(sbi) <= (node_secs + 2 * dent_secs + +						reserved_sections(sbi))) +		return true; +	return false;  }  static inline int utilization(struct f2fs_sb_info *sbi) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 13867322cf5a..08a94c814bdc 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -119,7 +119,6 @@ static void f2fs_put_super(struct super_block *sb)  int f2fs_sync_fs(struct super_block *sb, int sync)  {  	struct f2fs_sb_info *sbi = F2FS_SB(sb); -	int ret = 0;  	if (!sbi->s_dirty && !get_pages(sbi, F2FS_DIRTY_NODES))  		return 0; @@ -127,7 +126,7 @@ int f2fs_sync_fs(struct super_block *sb, int sync)  	if (sync)  		write_checkpoint(sbi, false, false); -	return ret; +	return 0;  }  static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) @@ -148,8 +147,8 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)  	buf->f_bfree = buf->f_blocks - valid_user_blocks(sbi) - ovp_count;  	buf->f_bavail = user_block_count - valid_user_blocks(sbi); -	buf->f_files = valid_inode_count(sbi); -	buf->f_ffree = sbi->total_node_count - valid_node_count(sbi); +	buf->f_files = sbi->total_node_count; +	buf->f_ffree = sbi->total_node_count - valid_inode_count(sbi);  	buf->f_namelen = F2FS_MAX_NAME_LEN;  	buf->f_fsid.val[0] = (u32)id; @@ -302,7 +301,7 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options)  		case Opt_active_logs:  			if (args->from && match_int(args, &arg))  				return -EINVAL; -			if (arg != 2 && arg != 4 && arg != 6) +			if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE)  				return -EINVAL;  			sbi->active_logs = arg;  			break; @@ -528,8 +527,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)  	/* if there are nt orphan nodes free them */  	err = -EINVAL; -	if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG) && -				recover_orphan_inodes(sbi)) +	if (recover_orphan_inodes(sbi))  		goto free_node_inode;  	/* read root inode and dentry */ @@ -548,8 +546,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)  	}  	/* recover fsynced data */ -	if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG) && -				!test_opt(sbi, DISABLE_ROLL_FORWARD)) +	if (!test_opt(sbi, DISABLE_ROLL_FORWARD))  		recover_fsync_data(sbi);  	/* After POR, we can run background GC thread */ diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 7d52e8dc0c59..940136a3d3a6 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -208,7 +208,7 @@ int f2fs_getxattr(struct inode *inode, int name_index, const char *name,  	struct page *page;  	void *base_addr;  	int error = 0, found = 0; -	int value_len, name_len; +	size_t value_len, name_len;  	if (name == NULL)  		return -EINVAL; @@ -304,7 +304,8 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,  	struct f2fs_xattr_entry *here, *last;  	struct page *page;  	void *base_addr; -	int error, found, free, name_len, newsize; +	int error, found, free, newsize; +	size_t name_len;  	char *pval;  	if (name == NULL) |