f2fs: introduce macros for proc entries
Subsystems (2)
Jaegeuk Kim
maintainerPATCH 1/11 f2fs: introduce macros for proc entries
This adds macros to be used multiple proc entries.
--- fs/f2fs/super.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-)
fs/f2fs/super.c +14 -11
@@ -745,19 +745,22 @@ static int segment_info_seq_show(struct seq_file *seq, void *offset)return 0 ; } -static int segment_info_open_fs (struct inode *inode,struct file *file) -{ -return single_open (file, segment_info_seq_show,PDE_DATA (inode)); -} - -static const struct file_operations f2fs_seq_segment_info_fops = { - .owner =THIS_MODULE , - .open = segment_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, +#define F2FS_PROC_FILE_DEF (_name) \ +static int _name##_open_fs(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, _name##_seq_show, PDE_DATA(inode)); \ +} \ + \ +static const struct file_operations f2fs_seq_##_name##_fops = { \ + .owner = THIS_MODULE, \ + .open = _name##_open_fs, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ }; +F2FS_PROC_FILE_DEF (segment_info); +static void default_options (struct f2fs_sb_info *sbi) {/* init some FS parameters */
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 2/11 f2fs: add proc entry to show valid block bitmap
This patch adds a new proc entry to show segment information in more detail.
--- fs/f2fs/super.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-)
fs/f2fs/super.c +31 -1
@@ -539,6 +539,7 @@ static void f2fs_put_super(struct super_block *sb)if (sbi->s_proc) {remove_proc_entry ("segment_info" , sbi->s_proc); +remove_proc_entry ("segment_bits" , sbi->s_proc);remove_proc_entry (sb->s_id, f2fs_proc_root); }kobject_del (&sbi->s_kobj);
@@ -745,6 +746,30 @@ static int segment_info_seq_show(struct seq_file *seq, void *offset)return 0 ; } +static int segment_bits_seq_show (struct seq_file *seq,void *offset) +{ +struct super_block *sb = seq->private; +struct f2fs_sb_info *sbi =F2FS_SB (sb); +unsigned int total_segs = +le32_to_cpu (sbi->raw_super->segment_count_main); +int i, j; + +seq_puts (seq,"format: segment_type|valid_blocks|bitmaps\n" +"segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n" ); + +for (i =0 ; i < total_segs; i++) { +struct seg_entry *se =get_seg_entry (sbi, i); + +seq_printf (seq,"%-10d" , i); +seq_printf (seq,"%d|%-3u|" , se->type, +get_valid_blocks (sbi, i,1 )); +for (j =0 ; j <SIT_VBLOCK_MAP_SIZE ; j++) +seq_printf (seq,"%x " , se->cur_valid_map[j]); +seq_putc (seq,'\n' ); + } +return 0 ; +} +#define F2FS_PROC_FILE_DEF (_name) \ static int _name##_open_fs(struct inode *inode, struct file *file) \ { \
@@ -760,6 +785,7 @@ static const struct file_operations f2fs_seq_##_name##_fops = { \ };F2FS_PROC_FILE_DEF (segment_info); +F2FS_PROC_FILE_DEF (segment_bits);static void default_options (struct f2fs_sb_info *sbi) {
@@ -1541,9 +1567,12 @@ try_onemore:if (f2fs_proc_root) sbi->s_proc =proc_mkdir (sb->s_id, f2fs_proc_root); -if (sbi->s_proc) +if (sbi->s_proc) {proc_create_data ("segment_info" ,S_IRUGO , sbi->s_proc, &f2fs_seq_segment_info_fops, sb); +proc_create_data ("segment_bits" ,S_IRUGO , sbi->s_proc, + &f2fs_seq_segment_bits_fops, sb); + } sbi->s_kobj.kset = f2fs_kset;init_completion (&sbi->s_kobj_unregister);
@@ -1619,6 +1648,7 @@ free_kobj: free_proc:if (sbi->s_proc) {remove_proc_entry ("segment_info" , sbi->s_proc); +remove_proc_entry ("segment_bits" , sbi->s_proc);remove_proc_entry (sb->s_id, f2fs_proc_root); }f2fs_destroy_stats (sbi);
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 3/11 f2fs: introduce f2fs_kmalloc to wrap kmalloc
In reply to Jaegeuk KimThis patch adds f2fs_kmalloc.
--- fs/f2fs/acl.c | 4 ++-- fs/f2fs/dir.c | 2 +- fs/f2fs/f2fs.h | 5 +++++ fs/f2fs/gc.c | 2 +- fs/f2fs/inline.c | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-)
fs/f2fs/acl.c +2 -2
@@ -115,7 +115,7 @@ static void *f2fs_acl_to_disk(const struct posix_acl *acl, size_t *size)struct f2fs_acl_entry *entry;int i; - f2fs_acl =kmalloc (sizeof (struct f2fs_acl_header ) + acl->a_count * + f2fs_acl =f2fs_kmalloc (sizeof (struct f2fs_acl_header ) + acl->a_count *sizeof (struct f2fs_acl_entry ),GFP_NOFS );if (!f2fs_acl)return ERR_PTR (-ENOMEM );
@@ -175,7 +175,7 @@ static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type, retval =f2fs_getxattr (inode, name_index,"" ,NULL ,0 , dpage);if (retval >0 ) { - value =kmalloc (retval,GFP_F2FS_ZERO ); + value =f2fs_kmalloc (retval,GFP_F2FS_ZERO );if (!value)return ERR_PTR (-ENOMEM ); retval = f2fs_getxattr(inode, name_index, "", value,
fs/f2fs/dir.c +1 -1
@@ -805,7 +805,7 @@ bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,int save_len = fstr->len;int ret; - de_name.name =kmalloc (de_name.len,GFP_NOFS ); + de_name.name =f2fs_kmalloc (de_name.len,GFP_NOFS );if (!de_name.name)return false;
fs/f2fs/f2fs.h +5 -0
@@ -1643,6 +1643,11 @@ static inline bool f2fs_may_extent_tree(struct inode *inode)return S_ISREG (inode->i_mode); } +static inline void *f2fs_kmalloc (size_t size,gfp_t flags) +{ +return kmalloc (size, flags); +} +static inline void *f2fs_kvmalloc (size_t size,gfp_t flags) {void *ret;
fs/f2fs/gc.c +1 -1
@@ -96,7 +96,7 @@ int start_gc_thread(struct f2fs_sb_info *sbi)dev_t dev = sbi->sb->s_bdev->bd_dev;int err =0 ; - gc_th =kmalloc (sizeof (struct f2fs_gc_kthread ),GFP_KERNEL ); + gc_th =f2fs_kmalloc (sizeof (struct f2fs_gc_kthread ),GFP_KERNEL );if (!gc_th) { err = -ENOMEM ; goto out;
fs/f2fs/inline.c +1 -1
@@ -465,7 +465,7 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage,struct f2fs_inline_dentry *backup_dentry;int err; - backup_dentry =kmalloc (sizeof (struct f2fs_inline_dentry ), + backup_dentry =f2fs_kmalloc (sizeof (struct f2fs_inline_dentry ),GFP_F2FS_ZERO );if (!backup_dentry)return -ENOMEM ;
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 4/11 f2fs: use f2fs_grab_cache_page instead of grab_cache_page
In reply to Jaegeuk KimThis patch converts grab_cache_page to f2fs_grab_cache_page.
--- fs/f2fs/checkpoint.c | 7 ++++--- fs/f2fs/inline.c | 4 ++-- fs/f2fs/node.c | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-)
fs/f2fs/checkpoint.c +4 -3
@@ -34,7 +34,7 @@ struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)struct address_space *mapping =META_MAPPING (sbi);struct page *page =NULL ; repeat: - page =grab_cache_page (mapping, index); + page =f2fs_grab_cache_page (mapping, index, false);if (!page) {cond_resched (); goto repeat;
@@ -64,7 +64,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,if (unlikely (!is_meta)) fio.rw &= ~REQ_META ; repeat: - page =grab_cache_page (mapping, index); + page =f2fs_grab_cache_page (mapping, index, false);if (!page) {cond_resched (); goto repeat;
@@ -186,7 +186,8 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,BUG (); } - page =grab_cache_page (META_MAPPING (sbi), fio.new_blkaddr); + page =f2fs_grab_cache_page (META_MAPPING (sbi), + fio.new_blkaddr, false);if (!page)continue ;if (PageUptodate (page)) {
fs/f2fs/inline.c +2 -2
@@ -161,7 +161,7 @@ int f2fs_convert_inline_inode(struct inode *inode)if (!f2fs_has_inline_data (inode))return 0 ; - page =grab_cache_page (inode->i_mapping,0 ); + page =f2fs_grab_cache_page (inode->i_mapping,0 , false);if (!page)return -ENOMEM ;
@@ -358,7 +358,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,struct f2fs_dentry_block *dentry_blk;int err; - page =grab_cache_page (dir->i_mapping,0 ); + page =f2fs_grab_cache_page (dir->i_mapping,0 , false);if (!page) {f2fs_put_page (ipage,1 );return -ENOMEM ;
fs/f2fs/node.c +4 -4
@@ -995,7 +995,7 @@ struct page *new_node_page(struct dnode_of_data *dn,if (unlikely (is_inode_flag_set (F2FS_I (dn->inode),FI_NO_ALLOC )))return ERR_PTR (-EPERM ); - page =grab_cache_page (NODE_MAPPING (sbi), dn->nid); + page =f2fs_grab_cache_page (NODE_MAPPING (sbi), dn->nid, false);if (!page)return ERR_PTR (-ENOMEM );
@@ -1087,7 +1087,7 @@ void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)if (apage)return ; - apage =grab_cache_page (NODE_MAPPING (sbi), nid); + apage =f2fs_grab_cache_page (NODE_MAPPING (sbi), nid, false);if (!apage)return ;
@@ -1128,7 +1128,7 @@ static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid,return ERR_PTR (-ENOENT );f2fs_bug_on (sbi,check_nid_range (sbi, nid)); repeat: - page =grab_cache_page (NODE_MAPPING (sbi), nid); + page =f2fs_grab_cache_page (NODE_MAPPING (sbi), nid, false);if (!page)return ERR_PTR (-ENOMEM );
@@ -2012,7 +2012,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)if (unlikely (old_ni.blk_addr !=NULL_ADDR ))return -EINVAL ; - ipage =grab_cache_page (NODE_MAPPING (sbi), ino); + ipage =f2fs_grab_cache_page (NODE_MAPPING (sbi), ino, false);if (!ipage)return -ENOMEM ;
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 5/11 f2fs: add mount option to select fault injection ratio
In reply to Jaegeuk KimThis patch adds a mount option to select fault ratio.
--- fs/f2fs/Kconfig | 8 ++++++++ fs/f2fs/f2fs.h | 1 + fs/f2fs/super.c | 16 ++++++++++++++++ 3 files changed, 25 insertions(+)
fs/f2fs/Kconfig +8 -0
@@ -94,3 +94,11 @@ config F2FS_IO_TRACE information and block IO patterns in the filesystem level. If unsure, say N. + +config F2FS_FAULT_INJECTION + bool "F2FS fault injection facility" + depends on F2FS_FS + help + Test F2FS to inject faults such as ENOMEM, ENOSPC, and so on. + + If unsure, say N.
fs/f2fs/f2fs.h +1 -0
@@ -56,6 +56,7 @@#define F2FS_MOUNT_EXTENT_CACHE 0x00002000#define F2FS_MOUNT_FORCE_FG_GC 0x00004000#define F2FS_MOUNT_DATA_FLUSH 0x00008000 +#define F2FS_MOUNT_FAULT_INJECTION 0x00010000#define clear_opt (sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
fs/f2fs/super.c +16 -0
@@ -39,6 +39,10 @@ static struct proc_dir_entry *f2fs_proc_root;static struct kmem_cache *f2fs_inode_cachep;static struct kset *f2fs_kset; +#ifdef CONFIG_F2FS_FAULT_INJECTION +u32 f2fs_fault_rate =0 ; +#endif +/* f2fs-wide shrinker description */ static struct shrinker f2fs_shrinker_info = { .scan_objects = f2fs_shrink_scan,
@@ -68,6 +72,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_fault_injection, Opt_err, };
@@ -93,6 +98,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_fault_injection, "fault_injection=%u"}, {Opt_err, NULL}, };
@@ -433,6 +439,16 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_fault_injection: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; +#ifdef CONFIG_F2FS_FAULT_INJECTION + f2fs_fault_rate = arg; +#else +f2fs_msg (sb,KERN_INFO , +"FAULT_INJECTION was not selected" ); +#endif +break ;default : f2fs_msg(sb, KERN_ERR, "Unrecognized mount option \"%s\" or missing value",
Signature · 9 lines
2.6.3 ------------------------------------------------------------------------------ Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z
Re: [f2fs-dev] [PATCH 05/11] f2fs: add mount option to select fault injection ratio
Hi Jaegeuk,
Quoted 1 line · Jaegeuk Kim
This patch adds a mount option to select fault ratio.
It's better to add description in documentation for this new mount option.
Anyway, this patchset looks good to me, please add:
Jaegeuk Kim
maintainerPATCH 6/11 f2fs: inject kmalloc failure
In reply to Jaegeuk KimThis patch injects kmalloc failure given a fault injection rate.
--- fs/f2fs/f2fs.h | 29 +++++++++++++++++++++++++++++ fs/f2fs/super.c | 6 ++++++ 2 files changed, 35 insertions(+)
fs/f2fs/f2fs.h +29 -0
@@ -37,6 +37,31 @@ } while (0)#endif +#ifdef CONFIG_F2FS_FAULT_INJECTION +enum { +FAULT_KMALLOC , +FAULT_MAX , +}; + +extern u32 f2fs_fault_rate; +extern atomic_t f2fs_ops; +extern char *fault_name[FAULT_MAX ]; + +static inline bool time_to_inject (int type) +{ +atomic_inc (&f2fs_ops); +if (f2fs_fault_rate && (atomic_read (&f2fs_ops) >= f2fs_fault_rate)) { +atomic_set (&f2fs_ops,0 ); +printk ("%sF2FS-fs : inject %s in %pF\n" , +KERN_INFO , + fault_name[type], +__builtin_return_address (0 )); +return true; + } +return false; +} +#endif +/* * For mount options */
@@ -1646,6 +1671,10 @@ static inline bool f2fs_may_extent_tree(struct inode *inode)static inline void *f2fs_kmalloc (size_t size,gfp_t flags) { +#ifdef CONFIG_F2FS_FAULT_INJECTION +if (time_to_inject (FAULT_KMALLOC )) +return NULL ; +#endif return kmalloc (size, flags); }
fs/f2fs/super.c +6 -0
@@ -41,6 +41,11 @@ static struct kset *f2fs_kset;#ifdef CONFIG_F2FS_FAULT_INJECTION u32 f2fs_fault_rate =0 ; +atomic_t f2fs_ops; + +char *fault_name[FAULT_MAX ] = { + [FAULT_KMALLOC ] ="kmalloc" , +};#endif /* f2fs-wide shrinker description */
@@ -444,6 +449,7 @@ static int parse_options(struct super_block *sb, char *options)return -EINVAL ;#ifdef CONFIG_F2FS_FAULT_INJECTION f2fs_fault_rate = arg; +atomic_set (&f2fs_ops,0 );#else f2fs_msg (sb,KERN_INFO ,"FAULT_INJECTION was not selected" );
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 7/11 f2fs: inject page allocation failures
In reply to Jaegeuk KimThis patch adds page allocation failures.
--- fs/f2fs/f2fs.h | 9 +++++++++ fs/f2fs/super.c | 1 + 2 files changed, 10 insertions(+)
fs/f2fs/f2fs.h +9 -0
@@ -40,6 +40,7 @@#ifdef CONFIG_F2FS_FAULT_INJECTION enum {FAULT_KMALLOC , +FAULT_PAGE_ALLOC ,FAULT_MAX , };
@@ -1296,6 +1297,14 @@ static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)static inline struct page *f2fs_grab_cache_page (struct address_space *mapping,pgoff_t index,bool for_write) { +#ifdef CONFIG_F2FS_FAULT_INJECTION +struct page *page =find_lock_page (mapping, index); +if (page) +return page; + +if (time_to_inject (FAULT_PAGE_ALLOC )) +return NULL ; +#endif if (!for_write)return grab_cache_page (mapping, index);return grab_cache_page_write_begin (mapping, index,AOP_FLAG_NOFS );
fs/f2fs/super.c +1 -0
@@ -45,6 +45,7 @@ atomic_t f2fs_ops;char *fault_name[FAULT_MAX ] = { [FAULT_KMALLOC ] ="kmalloc" , + [FAULT_PAGE_ALLOC ] ="page alloc" , };#endif
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 8/11 f2fs: inject ENOSPC failures
In reply to Jaegeuk KimThis patch injects ENOSPC failures.
--- fs/f2fs/checkpoint.c | 7 +++++++ fs/f2fs/dir.c | 4 ++++ fs/f2fs/f2fs.h | 10 ++++++++++ fs/f2fs/node.c | 4 ++++ fs/f2fs/super.c | 4 ++++ 5 files changed, 29 insertions(+)
fs/f2fs/checkpoint.c +7 -0
@@ -474,6 +474,13 @@ int acquire_orphan_inode(struct f2fs_sb_info *sbi)int err =0 ;spin_lock (&im->ino_lock); + +#ifdef CONFIG_F2FS_FAULT_INJECTION +if (time_to_inject (FAULT_ORPHAN )) { +spin_unlock (&im->ino_lock); +return -ENOSPC ; + } +#endif if (unlikely (im->ino_num >= sbi->max_orphans)) err = -ENOSPC ;else
fs/f2fs/dir.c +4 -0
@@ -537,6 +537,10 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, } start: +#ifdef CONFIG_F2FS_FAULT_INJECTION +if (time_to_inject (FAULT_DIR_DEPTH )) +return -ENOSPC ; +#endif if (unlikely (current_depth ==MAX_DIR_HASH_DEPTH ))return -ENOSPC ;
fs/f2fs/f2fs.h +10 -0
@@ -41,6 +41,10 @@enum {FAULT_KMALLOC ,FAULT_PAGE_ALLOC , +FAULT_ALLOC_NID , +FAULT_ORPHAN , +FAULT_BLOCK , +FAULT_DIR_DEPTH ,FAULT_MAX , };
@@ -1087,6 +1091,12 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,block_t valid_block_count;spin_lock (&sbi->stat_lock); +#ifdef CONFIG_F2FS_FAULT_INJECTION +if (time_to_inject (FAULT_BLOCK )) { +spin_unlock (&sbi->stat_lock); +return false; + } +#endif valid_block_count = sbi->total_valid_block_count + (block_t )count;if (unlikely (valid_block_count > sbi->user_block_count)) {
fs/f2fs/node.c +4 -0
@@ -1838,6 +1838,10 @@ bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)struct f2fs_nm_info *nm_i =NM_I (sbi);struct free_nid *i =NULL ; retry: +#ifdef CONFIG_F2FS_FAULT_INJECTION +if (time_to_inject (FAULT_ALLOC_NID )) +return false; +#endif if (unlikely (sbi->total_valid_node_count +1 > nm_i->available_nids))return false;
fs/f2fs/super.c +4 -0
@@ -46,6 +46,10 @@ atomic_t f2fs_ops;char *fault_name[FAULT_MAX ] = { [FAULT_KMALLOC ] ="kmalloc" , [FAULT_PAGE_ALLOC ] ="page alloc" , + [FAULT_ALLOC_NID ] ="alloc nid" , + [FAULT_ORPHAN ] ="orphan" , + [FAULT_BLOCK ] ="no more block" , + [FAULT_DIR_DEPTH ] ="too big dir depth" , };#endif
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 9/11 f2fs: revisit error handling flows
In reply to Jaegeuk KimThis patch fixes a couple of bugs regarding to orphan inodes when handling errors.
This tries to
- call alloc_nid_done with add_orphan_inode in handle_failed_inode
- let truncate blocks in f2fs_evict_inode
- not make a bad inode due to i_mode change
--- fs/f2fs/dir.c | 20 ++++++++++++-------- fs/f2fs/inode.c | 40 ++++++++++++++++------------------------ 2 files changed, 28 insertions(+), 32 deletions(-)
fs/f2fs/dir.c +12 -8
@@ -391,9 +391,14 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir,return page;if (S_ISDIR (inode->i_mode)) { +/* in order to handle error case */ +get_page (page); err =make_empty_dir (inode, dir, page); -if (err) - goto error; +if (err) { +lock_page (page); + goto put_error; + } +put_page (page); } err =f2fs_init_acl (inode, dir, page, dpage);
@@ -437,13 +442,12 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir,return page; put_error: -f2fs_put_page (page,1 ); -error: -/* once the failed inode becomes a bad inode, i_mode is S_IFREG */ +/* truncate empty dir pages */ truncate_inode_pages (&inode->i_data,0 ); -truncate_blocks (inode,0 , false); -remove_dirty_inode (inode); -remove_inode_page (inode); + +clear_nlink (inode); +update_inode (inode, page); +f2fs_put_page (page,1 );return ERR_PTR (err); }
fs/f2fs/inode.c +16 -24
@@ -368,10 +368,7 @@ no_delete:if (is_inode_flag_set (fi,FI_UPDATE_WRITE ))add_ino_entry (sbi, inode->i_ino,UPDATE_INO );if (is_inode_flag_set (fi,FI_FREE_NID )) { -if (err && err != -ENOENT ) -alloc_nid_done (sbi, inode->i_ino); -else -alloc_nid_failed (sbi, inode->i_ino); +alloc_nid_failed (sbi, inode->i_ino);clear_inode_flag (fi,FI_FREE_NID ); }
@@ -397,37 +394,32 @@ out_clear:void handle_failed_inode (struct inode *inode) {struct f2fs_sb_info *sbi =F2FS_I_SB (inode); -int err =0 ; +struct node_info ni; -clear_nlink (inode); -make_bad_inode (inode); +/* don't make bad inode, since it becomes a regular file. */ unlock_new_inode (inode); -i_size_write (inode,0 ); -if (F2FS_HAS_BLOCKS (inode)) - err =f2fs_truncate (inode, false); - -if (!err) - err =remove_inode_page (inode); -/* -* if we skip truncate_node in remove_inode_page bacause we failed -* before, it's better to find another way to release resource of -* this inode (e.g. valid block count, node block or nid). Here we -* choose to add this inode to orphan list, so that we can call iput -* for releasing in orphan recovery flow. -* * Note: we should add inode to orphan list before f2fs_unlock_op() * so we can prevent losing this orphan when encoutering checkpoint * and following suddenly power-off. */ -if (err && err != -ENOENT ) { - err =acquire_orphan_inode (sbi); -if (!err) +get_node_info (sbi, inode->i_ino, &ni); + +if (ni.blk_addr !=NULL_ADDR ) { +int err =acquire_orphan_inode (sbi); +if (err) { +set_sbi_flag (sbi,SBI_NEED_FSCK ); +f2fs_msg (sbi->sb,KERN_WARNING , +"Too many orphan inodes, run fsck to fix." ); + }else {add_orphan_inode (sbi, inode->i_ino); + } +alloc_nid_done (sbi, inode->i_ino); + }else { +set_inode_flag (F2FS_I (inode),FI_FREE_NID ); } -set_inode_flag (F2FS_I (inode),FI_FREE_NID );f2fs_unlock_op (sbi);/* iput will drop the inode object */
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 10/11 f2fs: fix leak of orphan inode objects
In reply to Jaegeuk KimWhen unmounting filesystem, we should release all the ino entries.
--- fs/f2fs/checkpoint.c | 6 +++--- fs/f2fs/f2fs.h | 2 +- fs/f2fs/super.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-)
fs/f2fs/checkpoint.c +3 -3
@@ -449,12 +449,12 @@ bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)return e ? true : false; } -void release_ino_entry (struct f2fs_sb_info *sbi) +void release_ino_entry (struct f2fs_sb_info *sbi,bool all) {struct ino_entry *e, *tmp;int i; -for (i =APPEND_INO ; i <=UPDATE_INO ; i++) { +for (i = all ?ORPHAN_INO :APPEND_INO ; i <=UPDATE_INO ; i++) {struct inode_management *im = &sbi->im[i];spin_lock (&im->ino_lock);
@@ -1090,7 +1090,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)invalidate_mapping_pages (META_MAPPING (sbi), discard_blk, discard_blk); -release_ino_entry (sbi); +release_ino_entry (sbi, false);if (unlikely (f2fs_cp_error (sbi)))return -EIO ;
fs/f2fs/f2fs.h +1 -1
@@ -1910,7 +1910,7 @@ void ra_meta_pages_cond(struct f2fs_sb_info *, pgoff_t);long sync_meta_pages (struct f2fs_sb_info *,enum page_type ,long );void add_ino_entry (struct f2fs_sb_info *,nid_t ,int type);void remove_ino_entry (struct f2fs_sb_info *,nid_t ,int type); -void release_ino_entry (struct f2fs_sb_info *); +void release_ino_entry (struct f2fs_sb_info *,bool );bool exist_written_data (struct f2fs_sb_info *,nid_t ,int );int acquire_orphan_inode (struct f2fs_sb_info *);void release_orphan_inode (struct f2fs_sb_info *);
fs/f2fs/super.c +1 -1
@@ -596,7 +596,7 @@ static void f2fs_put_super(struct super_block *sb)* normally superblock is clean, so we need to release this. * In addition, EIO will skip do checkpoint, we need this as well. */ -release_ino_entry (sbi); +release_ino_entry (sbi, true);release_discard_addrs (sbi);f2fs_leave_shrinker (sbi);
Signature · 9 lines
2.6.3 ------------------------------------------------------------------------------ Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z
Jaegeuk Kim
maintainerPATCH 11/11 f2fs: retry to truncate blocks in -ENOMEM case
In reply to Jaegeuk KimThis patch modifies to retry truncating node blocks in -ENOMEM case.
--- fs/f2fs/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/f2fs/inode.c +6 -1
@@ -344,7 +344,7 @@ void f2fs_evict_inode(struct inode *inode)sb_start_intwrite (inode->i_sb);set_inode_flag (fi,FI_NO_ALLOC );i_size_write (inode,0 ); - +retry:if (F2FS_HAS_BLOCKS (inode)) err =f2fs_truncate (inode, true);
@@ -374,6 +374,11 @@ no_delete:if (err && err != -ENOENT ) {if (!exist_written_data (sbi, inode->i_ino,ORPHAN_INO )) { +/* give more chances, if ENOMEM case */ +if (err == -ENOMEM ) { + err =0 ; + goto retry; + }/* * get here because we failed to release resource * of inode previously, reminder our user to run fsck
Signature · 1 line
2.6.3
Re: [f2fs-dev] [PATCH 11/11] f2fs: retry to truncate blocks in -ENOMEM case
Quoted 2 lines · Jaegeuk Kim
This patch modifies to retry truncating node blocks in
-ENOMEMcase.
Hi, Kim. in this patch, I think there is NO chance to retry for -ENOMEM.
This is because if exist_written_data returns false, we can confirm that this inode has been released from orphan radix-tree:f2fs_evict_inode
---> remove_inode_page
---> truncate_node
---> remove_orphan_inode
On this condition, err is 0, So it won't enter:
if (err && err != -ENOENT)
{
...
}sequentially, there is no chance to truncate node blocks again. I miss something else?
How about this patch?
fs/f2fs/inode.c +6 -0
@@ -345,6 +345,7 @@ void f2fs_evict_inode(struct inode *inode)set_inode_flag (fi,FI_NO_ALLOC );i_size_write (inode,0 ); +retry:if (F2FS_HAS_BLOCKS (inode)) err =f2fs_truncate (inode, true);
@@ -354,6 +355,11 @@ void f2fs_evict_inode(struct inode *inode)f2fs_unlock_op (sbi); } +if (err == -ENOMEM ) { + err =0 ; + goto retry; + } +sb_end_intwrite (inode->i_sb); no_delete:stat_dec_inline_xattr (inode);
Quoted 31 lines
Signed-off-by Jaegeuk Kim <[email protected]>--- fs/f2fs/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)fs/f2fs/inode.c +6
-1@@ -344,7 +344,7 @@ void f2fs_evict_inode(struct inode *inode)sb_start_intwrite (inode->i_sb);set_inode_flag (fi,FI_NO_ALLOC );i_size_write (inode,0 ); - +retry:if (F2FS_HAS_BLOCKS (inode)) err =f2fs_truncate (inode, true);@@ -374,6 +374,11 @@ no_delete:if (err && err != -ENOENT ) {if (!exist_written_data (sbi, inode->i_ino,ORPHAN_INO )) { +/* give more chances, if ENOMEM case */ +if (err == -ENOMEM ) { + err =0 ; + goto retry; + }/* * get here because we failed to release resource * of inode previously, reminder our user to run fsck
Jaegeuk Kim
maintainerRe: [f2fs-dev] [PATCH 11/11] f2fs: retry to truncate blocks in -ENOMEM case
Hi,
Quoted 16 lines · Hou Pengyang
Quoted 2 lines · Jaegeuk Kim
This patch modifies to retry truncating node blocks in
-ENOMEMcase.Hi, Kim. in this patch, I think there is NO chance to retry for
-ENOMEM.This is because if
exist_written_datareturns false, we can confirm that this inode has been released from orphan radix-tree:f2fs_evict_inode
--->remove_inode_page---> truncate_node ---> remove_orphan_inode On this condition, err is 0, So it won't enter: if (err && err != -ENOENT) { ... }
Quoted 2 lines
sequentially, there is no chance to truncate node blocks again. I miss something else?
When I initially tested fault injection, I could hit that before. But, now I can't hit this again. :(
It seems it was gone while I updated the error flow before. Agreed with you, and let me take your change.
BTW, I even suspect whether this leaking condition happens or not. If f2fs_evict_inode deals with inode deletion, that inode should be an orphan one. So, we don't need to consider that condition actually.
So, I wrote this patch as well.
I started stress tests again. :)
Thanks,
Quoted 1 line
From
8c1e4e5ca23410b8f55bbc75d64f75416d486739Mon Sep 17 00:00:00 2001
From: Jaegeuk Kim <[email protected]>
Date: Wed, 4 May 2016 19:48:53 -0700
Subject: [PATCH] f2fs: don't worry about inode leak in evict_inode
Even if an inode failed to release its blocks, it should be kept in an orphan inode list, so it will be released later.
--- fs/f2fs/inode.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-)
fs/f2fs/inode.c +2 -14
@@ -377,20 +377,8 @@ no_delete:alloc_nid_failed (sbi, inode->i_ino);clear_inode_flag (fi,FI_FREE_NID ); } - -if (err && err != -ENOENT ) { -if (!exist_written_data (sbi, inode->i_ino,ORPHAN_INO )) { -/* -* get here because we failed to release resource -* of inode previously, reminder our user to run fsck -* for fixing. -*/ -set_sbi_flag (sbi,SBI_NEED_FSCK ); -f2fs_msg (sbi->sb,KERN_WARNING , -"inode (ino:%lu) resource leak, run fsck " -"to fix this issue!" , inode->i_ino); - } - } +f2fs_bug_on (sbi, err && + !exist_written_data (sbi, inode->i_ino,ORPHAN_INO )); out_clear:fscrypt_put_encryption_info (inode,NULL );clear_inode (inode);
Signature · 1 line
2.6.3
Quoted 57 lines
How about this patch?
fs/f2fs/inode.c +6
-0@@ -345,6 +345,7 @@ void f2fs_evict_inode(struct inode *inode)set_inode_flag (fi,FI_NO_ALLOC );i_size_write (inode,0 ); +retry:if (F2FS_HAS_BLOCKS (inode)) err =f2fs_truncate (inode, true);@@ -354,6 +355,11 @@ void f2fs_evict_inode(struct inode *inode)f2fs_unlock_op (sbi); } +if (err == -ENOMEM ) { + err =0 ; + goto retry; + } +sb_end_intwrite (inode->i_sb); no_delete:stat_dec_inline_xattr (inode);Quoted 31 lines
Signed-off-by Jaegeuk Kim <[email protected]>--- fs/f2fs/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)fs/f2fs/inode.c +6
-1@@ -344,7 +344,7 @@ void f2fs_evict_inode(struct inode *inode)sb_start_intwrite (inode->i_sb);set_inode_flag (fi,FI_NO_ALLOC );i_size_write (inode,0 ); - +retry:if (F2FS_HAS_BLOCKS (inode)) err =f2fs_truncate (inode, true);@@ -374,6 +374,11 @@ no_delete:if (err && err != -ENOENT ) {if (!exist_written_data (sbi, inode->i_ino,ORPHAN_INO )) { +/* give more chances, if ENOMEM case */ +if (err == -ENOMEM ) { + err =0 ; + goto retry; + }/* * get here because we failed to release resource * of inode previously, reminder our user to run fsck