From ad7be67a1806ad1fc4105e36485b3fe8f7d1e297 Mon Sep 17 00:00:00 2001 From: Pranav Vashi Date: Tue, 24 Feb 2015 09:01:16 +0530 Subject: [PATCH] Revert "f2fs: update" This reverts commit 8addd866bae9b5bdff027f07e192c0995e126012. --- fs/f2fs/checkpoint.c | 48 ++++++++----------- fs/f2fs/data.c | 92 ++++++------------------------------- fs/f2fs/debug.c | 6 +-- fs/f2fs/f2fs.h | 66 +++++--------------------- fs/f2fs/file.c | 14 ++---- fs/f2fs/gc.c | 18 +++++--- fs/f2fs/gc.h | 30 ++++++------ fs/f2fs/inline.c | 25 ++++++---- fs/f2fs/namei.c | 2 +- fs/f2fs/node.c | 39 +++++++++------- fs/f2fs/recovery.c | 8 +--- fs/f2fs/segment.c | 52 ++++++++------------- fs/f2fs/segment.h | 29 ++++++------ fs/f2fs/super.c | 62 ++++--------------------- fs/f2fs/trace.c | 4 +- include/linux/f2fs_fs.h | 5 -- include/trace/events/f2fs.h | 14 +++--- 17 files changed, 170 insertions(+), 344 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index ae2ab5f79ab4..28c87e10c200 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -191,7 +191,7 @@ static int f2fs_write_meta_page(struct page *page, trace_f2fs_writepage(page, META); - if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) + if (unlikely(sbi->por_doing)) goto redirty_out; if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0)) goto redirty_out; @@ -303,7 +303,6 @@ static int f2fs_set_meta_page_dirty(struct page *page) if (!PageDirty(page)) { __set_page_dirty_nobuffers(page); inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META); - SetPagePrivate(page); f2fs_trace_pid(page); return 1; } @@ -314,8 +313,6 @@ const struct address_space_operations f2fs_meta_aops = { .writepage = f2fs_write_meta_page, .writepages = f2fs_write_meta_pages, .set_page_dirty = f2fs_set_meta_page_dirty, - .invalidatepage = f2fs_invalidate_page, - .releasepage = f2fs_release_page, }; static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) @@ -470,7 +467,7 @@ void recover_orphan_inodes(struct f2fs_sb_info *sbi) if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG)) return; - set_sbi_flag(sbi, SBI_POR_DOING); + sbi->por_doing = true; start_blk = __start_cp_addr(sbi) + 1 + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); @@ -491,7 +488,7 @@ void recover_orphan_inodes(struct f2fs_sb_info *sbi) } /* clear Orphan Flag */ clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG); - clear_sbi_flag(sbi, SBI_POR_DOING); + sbi->por_doing = false; return; } @@ -575,7 +572,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, if (crc_offset >= blk_size) goto invalid_cp1; - crc = le32_to_cpu(*((__le32 *)((unsigned char *)cp_block + crc_offset))); + crc = le32_to_cpu(*((__u32 *)((unsigned char *)cp_block + crc_offset))); if (!f2fs_crc_valid(crc, cp_block, crc_offset)) goto invalid_cp1; @@ -590,7 +587,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, if (crc_offset >= blk_size) goto invalid_cp2; - crc = le32_to_cpu(*((__le32 *)((unsigned char *)cp_block + crc_offset))); + crc = le32_to_cpu(*((__u32 *)((unsigned char *)cp_block + crc_offset))); if (!f2fs_crc_valid(crc, cp_block, crc_offset)) goto invalid_cp2; @@ -941,31 +938,24 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks + orphan_blocks); - if (__remain_node_summaries(cpc->reason)) + if (cpc->reason == CP_UMOUNT) { + set_ckpt_flags(ckpt, CP_UMOUNT_FLAG); ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS+ cp_payload_blks + data_sum_blocks + orphan_blocks + NR_CURSEG_NODE_TYPE); - else + } else { + clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG); ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS + cp_payload_blks + data_sum_blocks + orphan_blocks); - - if (cpc->reason == CP_UMOUNT) - set_ckpt_flags(ckpt, CP_UMOUNT_FLAG); - else - clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG); - - if (cpc->reason == CP_FASTBOOT) - set_ckpt_flags(ckpt, CP_FASTBOOT_FLAG); - else - clear_ckpt_flags(ckpt, CP_FASTBOOT_FLAG); + } if (orphan_num) set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG); else clear_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG); - if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) + if (sbi->need_fsck) set_ckpt_flags(ckpt, CP_FSCK_FLAG); /* update SIT/NAT bitmap */ @@ -982,14 +972,15 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) /* write out checkpoint buffer at block 0 */ cp_page = grab_meta_page(sbi, start_blk++); kaddr = page_address(cp_page); - memcpy(kaddr, ckpt, F2FS_BLKSIZE); + memcpy(kaddr, ckpt, (1 << sbi->log_blocksize)); set_page_dirty(cp_page); f2fs_put_page(cp_page, 1); for (i = 1; i < 1 + cp_payload_blks; i++) { cp_page = grab_meta_page(sbi, start_blk++); kaddr = page_address(cp_page); - memcpy(kaddr, (char *)ckpt + i * F2FS_BLKSIZE, F2FS_BLKSIZE); + memcpy(kaddr, (char *)ckpt + i * F2FS_BLKSIZE, + (1 << sbi->log_blocksize)); set_page_dirty(cp_page); f2fs_put_page(cp_page, 1); } @@ -1001,7 +992,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) write_data_summaries(sbi, start_blk); start_blk += data_sum_blocks; - if (__remain_node_summaries(cpc->reason)) { + if (cpc->reason == CP_UMOUNT) { write_node_summaries(sbi, start_blk); start_blk += NR_CURSEG_NODE_TYPE; } @@ -1009,7 +1000,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) /* writeout checkpoint block */ cp_page = grab_meta_page(sbi, start_blk); kaddr = page_address(cp_page); - memcpy(kaddr, ckpt, F2FS_BLKSIZE); + memcpy(kaddr, ckpt, (1 << sbi->log_blocksize)); set_page_dirty(cp_page); f2fs_put_page(cp_page, 1); @@ -1038,7 +1029,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) return; clear_prefree_segments(sbi); - clear_sbi_flag(sbi, SBI_IS_DIRTY); + F2FS_RESET_SB_DIRT(sbi); } /* @@ -1053,13 +1044,10 @@ void write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) mutex_lock(&sbi->cp_mutex); - if (!is_sbi_flag_set(sbi, SBI_IS_DIRTY) && - cpc->reason != CP_DISCARD && cpc->reason != CP_UMOUNT) + if (!sbi->s_dirty && cpc->reason != CP_DISCARD) goto out; if (unlikely(f2fs_cp_error(sbi))) goto out; - if (f2fs_readonly(sbi->sb)) - goto out; if (block_operations(sbi)) goto out; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 30b34dcf81f8..eb71e1949f36 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -274,7 +274,7 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs, unsigned int blkbits = inode->i_sb->s_blocksize_bits; size_t count; - set_buffer_new(bh_result); + clear_buffer_new(bh_result); map_bh(bh_result, inode->i_sb, start_blkaddr + pgofs - start_fofs); count = end_fofs - pgofs + 1; @@ -592,56 +592,6 @@ static int __allocate_data_block(struct dnode_of_data *dn) return 0; } -static void __allocate_data_blocks(struct inode *inode, loff_t offset, - size_t count) -{ - struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - struct dnode_of_data dn; - u64 start = F2FS_BYTES_TO_BLK(offset); - u64 len = F2FS_BYTES_TO_BLK(count); - bool allocated; - u64 end_offset; - - while (len) { - f2fs_balance_fs(sbi); - f2fs_lock_op(sbi); - - /* When reading holes, we need its node page */ - set_new_dnode(&dn, inode, NULL, NULL, 0); - if (get_dnode_of_data(&dn, start, ALLOC_NODE)) - goto out; - - allocated = false; - end_offset = ADDRS_PER_PAGE(dn.node_page, F2FS_I(inode)); - - while (dn.ofs_in_node < end_offset && len) { - if (dn.data_blkaddr == NULL_ADDR) { - if (__allocate_data_block(&dn)) - goto sync_out; - allocated = true; - } - len--; - start++; - dn.ofs_in_node++; - } - - if (allocated) - sync_inode_page(&dn); - - f2fs_put_dnode(&dn); - f2fs_unlock_op(sbi); - } - return; - -sync_out: - if (allocated) - sync_inode_page(&dn); - f2fs_put_dnode(&dn); -out: - f2fs_unlock_op(sbi); - return; -} - /* * get_data_block() now supported readahead/bmap/rw direct_IO with mapped bh. * If original data blocks are allocated, then give them to blockdev. @@ -667,8 +617,10 @@ static int __get_data_block(struct inode *inode, sector_t iblock, if (check_extent_cache(inode, pgofs, bh_result)) goto out; - if (create) + if (create) { + f2fs_balance_fs(F2FS_I_SB(inode)); f2fs_lock_op(F2FS_I_SB(inode)); + } /* When reading holes, we need its node page */ set_new_dnode(&dn, inode, NULL, NULL, 0); @@ -682,14 +634,12 @@ static int __get_data_block(struct inode *inode, sector_t iblock, goto put_out; if (dn.data_blkaddr != NULL_ADDR) { - set_buffer_new(bh_result); map_bh(bh_result, inode->i_sb, dn.data_blkaddr); } else if (create) { err = __allocate_data_block(&dn); if (err) goto put_out; allocated = true; - set_buffer_new(bh_result); map_bh(bh_result, inode->i_sb, dn.data_blkaddr); } else { goto put_out; @@ -868,7 +818,7 @@ static int f2fs_write_data_page(struct page *page, zero_user_segment(page, offset, PAGE_CACHE_SIZE); write: - if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) + if (unlikely(sbi->por_doing)) goto redirty_out; if (f2fs_is_drop_cache(inode)) goto out; @@ -1158,11 +1108,10 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, trace_f2fs_direct_IO_enter(inode, offset, count, rw); - if (rw & WRITE) - __allocate_data_blocks(inode, offset, count); + err = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs, + get_data_block); - err = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs, - get_data_block); + trace_f2fs_direct_IO_enter(inode, offset, count, rw); if (err < 0 && (rw & WRITE)) f2fs_write_failed(mapping, offset + count); @@ -1172,31 +1121,20 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, return err; } -void f2fs_invalidate_page(struct page *page, unsigned long offset) +static void f2fs_invalidate_data_page(struct page *page, unsigned long offset) { struct inode *inode = page->mapping->host; - struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - if (inode->i_ino >= F2FS_ROOT_INO(sbi) && (offset % PAGE_CACHE_SIZE)) + if (offset % PAGE_CACHE_SIZE) return; - if (PageDirty(page)) { - if (inode->i_ino == F2FS_META_INO(sbi)) - dec_page_count(sbi, F2FS_DIRTY_META); - else if (inode->i_ino == F2FS_NODE_INO(sbi)) - dec_page_count(sbi, F2FS_DIRTY_NODES); - else - inode_dec_dirty_pages(inode); - } + if (PageDirty(page)) + inode_dec_dirty_pages(inode); ClearPagePrivate(page); } -int f2fs_release_page(struct page *page, gfp_t wait) +static int f2fs_release_data_page(struct page *page, gfp_t wait) { - /* If this is dirty page, keep PagePrivate */ - if (PageDirty(page)) - return 0; - ClearPagePrivate(page); return 1; } @@ -1246,8 +1184,8 @@ const struct address_space_operations f2fs_dblock_aops = { .write_begin = f2fs_write_begin, .write_end = f2fs_write_end, .set_page_dirty = f2fs_set_data_page_dirty, - .invalidatepage = f2fs_invalidate_page, - .releasepage = f2fs_release_page, + .invalidatepage = f2fs_invalidate_data_page, + .releasepage = f2fs_release_data_page, .direct_IO = f2fs_direct_IO, .bmap = f2fs_bmap, }; diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index e671373cc8ab..0f721f6a1147 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -40,7 +40,6 @@ static void update_general_status(struct f2fs_sb_info *sbi) si->ndirty_dirs = sbi->n_dirty_dirs; si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META); si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES); - si->wb_pages = get_pages(sbi, F2FS_WRITEBACK); si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg; si->rsvd_segs = reserved_segments(sbi); si->overp_segs = overprovision_segments(sbi); @@ -142,7 +141,6 @@ static void update_mem_info(struct f2fs_sb_info *sbi) si->base_mem += MAIN_SEGS(sbi) * sizeof(struct seg_entry); si->base_mem += f2fs_bitmap_size(MAIN_SEGS(sbi)); si->base_mem += 2 * SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi); - si->base_mem += SIT_VBLOCK_MAP_SIZE; if (sbi->segs_per_sec > 1) si->base_mem += MAIN_SECS(sbi) * sizeof(struct sec_entry); si->base_mem += __bitmap_size(sbi, SIT_BITMAP); @@ -268,8 +266,8 @@ static int stat_show(struct seq_file *s, void *v) seq_printf(s, "\nExtent Hit Ratio: %d / %d\n", si->hit_ext, si->total_ext); seq_puts(s, "\nBalancing F2FS Async:\n"); - seq_printf(s, " - inmem: %4d, wb: %4d\n", - si->inmem_pages, si->wb_pages); + seq_printf(s, " - inmem: %4d\n", + si->inmem_pages); seq_printf(s, " - nodes: %4d in %4d\n", si->ndirty_node, si->node_pages); seq_printf(s, " - dents: %4d in dirs:%4d\n", diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 686aad1539d3..4381f5c3e186 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -28,7 +28,7 @@ do { \ if (unlikely(condition)) { \ WARN_ON(1); \ - set_sbi_flag(sbi, SBI_NEED_FSCK); \ + sbi->need_fsck = true; \ } \ } while (0) #define f2fs_down_write(x, y) down_write(x) @@ -101,15 +101,10 @@ enum { enum { CP_UMOUNT, - CP_FASTBOOT, CP_SYNC, CP_DISCARD, }; -#define DEF_BATCHED_TRIM_SECTIONS 32 -#define BATCHED_TRIM_SEGMENTS(sbi) \ - (SM_I(sbi)->trim_sections * (sbi)->segs_per_sec) - struct cp_control { int reason; __u64 trim_start; @@ -208,7 +203,6 @@ static inline bool __has_cursum_space(struct f2fs_summary_block *sum, int size, */ #define F2FS_IOC_GETFLAGS FS_IOC_GETFLAGS #define F2FS_IOC_SETFLAGS FS_IOC_SETFLAGS -#define F2FS_IOC_GETVERSION FS_IOC_GETVERSION #define F2FS_IOCTL_MAGIC 0xf5 #define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1) @@ -453,9 +447,6 @@ struct f2fs_sm_info { int nr_discards; /* # of discards in the list */ int max_discards; /* max. discards to be issued */ - /* for batched trimming */ - unsigned int trim_sections; /* # of sections to trim */ - struct list_head sit_entry_set; /* sit entry set list */ unsigned int ipu_policy; /* in-place-update policy */ @@ -528,20 +519,13 @@ struct inode_management { unsigned long ino_num; /* number of entries */ }; -/* For s_flag in struct f2fs_sb_info */ -enum { - SBI_IS_DIRTY, /* dirty flag for checkpoint */ - SBI_IS_CLOSE, /* specify unmounting */ - SBI_NEED_FSCK, /* need fsck.f2fs to fix */ - SBI_POR_DOING, /* recovery is doing or not */ -}; - struct f2fs_sb_info { struct super_block *sb; /* pointer to VFS super block */ struct proc_dir_entry *s_proc; /* proc entry */ struct buffer_head *raw_super_buf; /* buffer head of raw sb */ struct f2fs_super_block *raw_super; /* raw super block pointer */ - int s_flag; /* flags for sbi */ + int s_dirty; /* dirty flag for checkpoint */ + bool need_fsck; /* need fsck.f2fs to fix */ /* for node-related operations */ struct f2fs_nm_info *nm_info; /* node manager */ @@ -561,6 +545,7 @@ struct f2fs_sb_info { struct rw_semaphore cp_rwsem; /* blocking FS operations */ struct rw_semaphore node_write; /* locking node writes */ struct mutex writepages; /* mutex for writepages() */ + bool por_doing; /* recovery is doing or not */ wait_queue_head_t cp_wait; struct inode_management im[MAX_INO_ENTRY]; /* manage inode cache */ @@ -713,19 +698,14 @@ static inline struct address_space *NODE_MAPPING(struct f2fs_sb_info *sbi) return sbi->node_inode->i_mapping; } -static inline bool is_sbi_flag_set(struct f2fs_sb_info *sbi, unsigned int type) +static inline void F2FS_SET_SB_DIRT(struct f2fs_sb_info *sbi) { - return sbi->s_flag & (0x01 << type); + sbi->s_dirty = 1; } -static inline void set_sbi_flag(struct f2fs_sb_info *sbi, unsigned int type) +static inline void F2FS_RESET_SB_DIRT(struct f2fs_sb_info *sbi) { - sbi->s_flag |= (0x01 << type); -} - -static inline void clear_sbi_flag(struct f2fs_sb_info *sbi, unsigned int type) -{ - sbi->s_flag &= ~(0x01 << type); + sbi->s_dirty = 0; } static inline unsigned long long cur_cp_version(struct f2fs_checkpoint *cp) @@ -773,28 +753,6 @@ static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi) up_write(&sbi->cp_rwsem); } -static inline int __get_cp_reason(struct f2fs_sb_info *sbi) -{ - int reason = CP_SYNC; - - if (test_opt(sbi, FASTBOOT)) - reason = CP_FASTBOOT; - if (is_sbi_flag_set(sbi, SBI_IS_CLOSE)) - reason = CP_UMOUNT; - return reason; -} - -static inline bool __remain_node_summaries(int reason) -{ - return (reason == CP_UMOUNT || reason == CP_FASTBOOT); -} - -static inline bool __exist_node_summaries(struct f2fs_sb_info *sbi) -{ - return (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG) || - is_set_ckpt_flags(F2FS_CKPT(sbi), CP_FASTBOOT_FLAG)); -} - /* * Check whether the given nid is within node id range. */ @@ -859,7 +817,7 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi, static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type) { atomic_inc(&sbi->nr_pages[count_type]); - set_sbi_flag(sbi, SBI_IS_DIRTY); + F2FS_SET_SB_DIRT(sbi); } static inline void inode_inc_dirty_pages(struct inode *inode) @@ -1533,8 +1491,6 @@ struct page *get_lock_data_page(struct inode *, pgoff_t); struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool); int do_write_data_page(struct page *, struct f2fs_io_info *); int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *, u64, u64); -void f2fs_invalidate_page(struct page *, unsigned long); -int f2fs_release_page(struct page *, gfp_t); /* * gc.c @@ -1564,7 +1520,7 @@ struct f2fs_stat_info { int ndirty_node, ndirty_dent, ndirty_dirs, ndirty_meta; int nats, dirty_nats, sits, dirty_sits, fnids; int total_count, utilization; - int bg_gc, inline_inode, inline_dir, inmem_pages, wb_pages; + int bg_gc, inline_inode, inline_dir, inmem_pages; unsigned int valid_count, valid_node_count, valid_inode_count; unsigned int bimodal, avg_vblocks; int util_free, util_valid, util_invalid; @@ -1687,7 +1643,6 @@ extern const struct address_space_operations f2fs_meta_aops; extern const struct inode_operations f2fs_dir_inode_operations; extern const struct inode_operations f2fs_symlink_inode_operations; extern const struct inode_operations f2fs_special_inode_operations; -extern struct kmem_cache *inode_entry_slab; /* * inline.c @@ -1698,6 +1653,7 @@ int f2fs_read_inline_data(struct inode *, struct page *); int f2fs_convert_inline_page(struct dnode_of_data *, struct page *); int f2fs_convert_inline_inode(struct inode *); int f2fs_write_inline_data(struct inode *, struct page *); +void truncate_inline_data(struct page *, u64); bool recover_inline_data(struct inode *, struct page *); struct f2fs_dir_entry *find_in_inline_dir(struct inode *, struct qstr *, struct page **); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 590651cc4b7f..faf22291b000 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -373,7 +373,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence) /* find data/hole in dnode block */ for (; dn.ofs_in_node < end_offset; dn.ofs_in_node++, pgofs++, - data_ofs = (loff_t)pgofs << PAGE_CACHE_SHIFT) { + data_ofs = pgofs << PAGE_CACHE_SHIFT) { block_t blkaddr; blkaddr = datablock_addr(dn.node_page, dn.ofs_in_node); @@ -507,7 +507,8 @@ int truncate_blocks(struct inode *inode, u64 from, bool lock) trace_f2fs_truncate_blocks_enter(inode, from); - free_from = (pgoff_t)F2FS_BYTES_TO_BLK(from + blocksize - 1); + free_from = (pgoff_t) + ((from + blocksize - 1) >> (sbi->log_blocksize)); if (lock) f2fs_lock_op(sbi); @@ -940,13 +941,6 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg) return ret; } -static int f2fs_ioc_getversion(struct file *filp, unsigned long arg) -{ - struct inode *inode = file_inode(filp); - - return put_user(inode->i_generation, (int __user *)arg); -} - static int f2fs_ioc_start_atomic_write(struct file *filp) { struct inode *inode = file_inode(filp); @@ -1117,8 +1111,6 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return f2fs_ioc_getflags(filp, arg); case F2FS_IOC_SETFLAGS: return f2fs_ioc_setflags(filp, arg); - case F2FS_IOC_GETVERSION: - return f2fs_ioc_getversion(filp, arg); case F2FS_IOC_START_ATOMIC_WRITE: return f2fs_ioc_start_atomic_write(filp); case F2FS_IOC_COMMIT_ATOMIC_WRITE: diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 5d6af020a883..60215e1f407a 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -44,7 +44,7 @@ static int gc_thread_func(void *data) break; if (sbi->sb->s_frozen >= SB_FREEZE_WRITE) { - increase_sleep_time(gc_th, &wait_ms); + wait_ms = increase_sleep_time(gc_th, wait_ms); continue; } @@ -65,15 +65,15 @@ static int gc_thread_func(void *data) continue; if (!is_idle(sbi)) { - increase_sleep_time(gc_th, &wait_ms); + wait_ms = increase_sleep_time(gc_th, wait_ms); mutex_unlock(&sbi->gc_mutex); continue; } if (has_enough_invalid_blocks(sbi)) - decrease_sleep_time(gc_th, &wait_ms); + wait_ms = decrease_sleep_time(gc_th, wait_ms); else - increase_sleep_time(gc_th, &wait_ms); + wait_ms = increase_sleep_time(gc_th, wait_ms); stat_inc_bggc_count(sbi); @@ -356,8 +356,11 @@ static void add_gc_inode(struct gc_inode_list *gc_list, struct inode *inode) } new_ie = f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS); new_ie->inode = inode; - - f2fs_radix_tree_insert(&gc_list->iroot, inode->i_ino, new_ie); +retry: + if (radix_tree_insert(&gc_list->iroot, inode->i_ino, new_ie)) { + cond_resched(); + goto retry; + } list_add_tail(&new_ie->list, &gc_list->ilist); } @@ -698,7 +701,8 @@ int f2fs_gc(struct f2fs_sb_info *sbi) .iroot = RADIX_TREE_INIT(GFP_NOFS), }; - cpc.reason = __get_cp_reason(sbi); + cpc.reason = test_opt(sbi, FASTBOOT) ? CP_UMOUNT : CP_SYNC; + gc_more: if (unlikely(!(sbi->sb->s_flags & MS_ACTIVE))) goto stop; diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h index 9091e0c9ded6..3498b0a91f4d 100644 --- a/fs/f2fs/gc.h +++ b/fs/f2fs/gc.h @@ -40,6 +40,8 @@ struct gc_inode_list { struct radix_tree_root iroot; }; +extern struct kmem_cache *inode_entry_slab; + /* * inline functions */ @@ -64,26 +66,26 @@ static inline block_t limit_free_user_blocks(struct f2fs_sb_info *sbi) return (long)(reclaimable_user_blocks * LIMIT_FREE_BLOCK) / 100; } -static inline void increase_sleep_time(struct f2fs_gc_kthread *gc_th, - long *wait) +static inline long increase_sleep_time(struct f2fs_gc_kthread *gc_th, long wait) { - if (*wait == gc_th->no_gc_sleep_time) - return; + if (wait == gc_th->no_gc_sleep_time) + return wait; - *wait += gc_th->min_sleep_time; - if (*wait > gc_th->max_sleep_time) - *wait = gc_th->max_sleep_time; + wait += gc_th->min_sleep_time; + if (wait > gc_th->max_sleep_time) + wait = gc_th->max_sleep_time; + return wait; } -static inline void decrease_sleep_time(struct f2fs_gc_kthread *gc_th, - long *wait) +static inline long decrease_sleep_time(struct f2fs_gc_kthread *gc_th, long wait) { - if (*wait == gc_th->no_gc_sleep_time) - *wait = gc_th->max_sleep_time; + if (wait == gc_th->no_gc_sleep_time) + wait = gc_th->max_sleep_time; - *wait -= gc_th->min_sleep_time; - if (*wait <= gc_th->min_sleep_time) - *wait = gc_th->min_sleep_time; + wait -= gc_th->min_sleep_time; + if (wait <= gc_th->min_sleep_time) + wait = gc_th->min_sleep_time; + return wait; } static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi) diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 42da76b9bbfc..d46eccd63ec3 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -50,12 +50,6 @@ void read_inline_data(struct page *page, struct page *ipage) SetPageUptodate(page); } -static void truncate_inline_data(struct page *ipage) -{ - f2fs_wait_on_page_writeback(ipage, NODE); - memset(inline_data_addr(ipage), 0, MAX_INLINE_DATA); -} - int f2fs_read_inline_data(struct inode *inode, struct page *page) { struct page *ipage; @@ -131,7 +125,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page) set_inode_flag(F2FS_I(dn->inode), FI_APPEND_WRITE); /* clear inline data and flag after data writeback */ - truncate_inline_data(dn->inode_page); + truncate_inline_data(dn->inode_page, 0); clear_out: stat_dec_inline_inode(dn->inode); f2fs_clear_inline_inode(dn->inode); @@ -204,6 +198,19 @@ int f2fs_write_inline_data(struct inode *inode, struct page *page) return 0; } +void truncate_inline_data(struct page *ipage, u64 from) +{ + void *addr; + + if (from >= MAX_INLINE_DATA) + return; + + f2fs_wait_on_page_writeback(ipage, NODE); + + addr = inline_data_addr(ipage); + memset(addr + from, 0, MAX_INLINE_DATA - from); +} + bool recover_inline_data(struct inode *inode, struct page *npage) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); @@ -245,7 +252,7 @@ bool recover_inline_data(struct inode *inode, struct page *npage) if (f2fs_has_inline_data(inode)) { ipage = get_node_page(sbi, inode->i_ino); f2fs_bug_on(sbi, IS_ERR(ipage)); - truncate_inline_data(ipage); + truncate_inline_data(ipage, 0); f2fs_clear_inline_inode(inode); update_inode(inode, ipage); f2fs_put_page(ipage, 1); @@ -363,7 +370,7 @@ static int f2fs_convert_inline_dir(struct inode *dir, struct page *ipage, set_page_dirty(page); /* clear inline dir and flag after data writeback */ - truncate_inline_data(ipage); + truncate_inline_data(ipage, 0); stat_dec_inline_dir(dir); clear_inode_flag(F2FS_I(dir), FI_INLINE_DENTRY); diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 63094b30f519..1f01fdada64b 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -299,7 +299,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) inode->i_op = &f2fs_dir_inode_operations; inode->i_fop = &f2fs_dir_operations; inode->i_mapping->a_ops = &f2fs_dblock_aops; - mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_HIGH_ZERO); + mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); set_inode_flag(F2FS_I(inode), FI_INC_LINK); f2fs_lock_op(sbi); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 23c8fb51e7c4..b88ed2088318 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -474,7 +474,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) { struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); struct page *npage[4]; - struct page *parent = NULL; + struct page *parent; int offset[4]; unsigned int noffset[4]; nid_t nids[4]; @@ -491,14 +491,6 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) if (IS_ERR(npage[0])) return PTR_ERR(npage[0]); } - - /* if inline_data is set, should not report any block indices */ - if (f2fs_has_inline_data(dn->inode) && index) { - err = -EINVAL; - f2fs_put_page(npage[0], 1); - goto release_out; - } - parent = npage[0]; if (level != 0) nids[1] = get_nid(parent, offset[0], true); @@ -596,7 +588,7 @@ static void truncate_node(struct dnode_of_data *dn) } invalidate: clear_node_page_dirty(dn->node_page); - set_sbi_flag(sbi, SBI_IS_DIRTY); + F2FS_SET_SB_DIRT(sbi); f2fs_put_page(dn->node_page, 1); @@ -1044,11 +1036,11 @@ struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) err = read_node_page(page, READ_SYNC); if (err < 0) return ERR_PTR(err); - else if (err != LOCKED_PAGE) - lock_page(page); + else if (err == LOCKED_PAGE) + goto got_it; + lock_page(page); if (unlikely(!PageUptodate(page) || nid != nid_of_node(page))) { - ClearPageUptodate(page); f2fs_put_page(page, 1); return ERR_PTR(-EIO); } @@ -1056,6 +1048,7 @@ struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) f2fs_put_page(page, 1); goto repeat; } +got_it: mark_page_accessed(page); return page; } @@ -1293,7 +1286,7 @@ static int f2fs_write_node_page(struct page *page, trace_f2fs_writepage(page, NODE); - if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) + if (unlikely(sbi->por_doing)) goto redirty_out; if (unlikely(f2fs_cp_error(sbi))) goto redirty_out; @@ -1379,6 +1372,20 @@ static int f2fs_set_node_page_dirty(struct page *page) return 0; } +static void f2fs_invalidate_node_page(struct page *page, unsigned long offset) +{ + struct inode *inode = page->mapping->host; + if (PageDirty(page)) + dec_page_count(F2FS_I_SB(inode), F2FS_DIRTY_NODES); + ClearPagePrivate(page); +} + +static int f2fs_release_node_page(struct page *page, gfp_t wait) +{ + ClearPagePrivate(page); + return 1; +} + /* * Structure of the f2fs node operations */ @@ -1386,8 +1393,8 @@ const struct address_space_operations f2fs_node_aops = { .writepage = f2fs_write_node_page, .writepages = f2fs_write_node_pages, .set_page_dirty = f2fs_set_node_page_dirty, - .invalidatepage = f2fs_invalidate_page, - .releasepage = f2fs_release_page, + .invalidatepage = f2fs_invalidate_node_page, + .releasepage = f2fs_release_node_page, }; static struct free_nid *__lookup_free_nid_list(struct f2fs_nm_info *nm_i, diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 01a4e0b83133..a9482cd65171 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -346,10 +346,6 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, if (IS_INODE(page)) { recover_inline_xattr(inode, page); } else if (f2fs_has_xattr_block(ofs_of_node(page))) { - /* - * Deprecated; xattr blocks should be found from cold log. - * But, we should remain this for backward compatibility. - */ recover_xattr_data(inode, page, blkaddr); goto out; } @@ -508,7 +504,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi) INIT_LIST_HEAD(&inode_list); /* step #1: find fsynced inode numbers */ - set_sbi_flag(sbi, SBI_POR_DOING); + sbi->por_doing = true; /* prevent checkpoint */ mutex_lock(&sbi->cp_mutex); @@ -541,7 +537,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi) truncate_inode_pages(META_MAPPING(sbi), 0); } - clear_sbi_flag(sbi, SBI_POR_DOING); + sbi->por_doing = false; if (err) { discard_next_dnode(sbi, blkaddr); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 0dc8ee88b18b..50c97dbcedc0 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -591,7 +591,7 @@ static void add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc) struct seg_entry *se = get_seg_entry(sbi, cpc->trim_start); unsigned long *cur_map = (unsigned long *)se->cur_valid_map; unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map; - unsigned long *dmap = SIT_I(sbi)->tmp_map; + unsigned long dmap[entries]; unsigned int start = 0, end = -1; bool force = (cpc->reason == CP_DISCARD); int i; @@ -886,7 +886,7 @@ static void get_new_segment(struct f2fs_sb_info *sbi, int go_left = 0; int i; - spin_lock(&free_i->segmap_lock); + write_lock(&free_i->segmap_lock); if (!new_sec && ((*newseg + 1) % sbi->segs_per_sec)) { segno = find_next_zero_bit(free_i->free_segmap, @@ -959,7 +959,7 @@ static void get_new_segment(struct f2fs_sb_info *sbi, f2fs_bug_on(sbi, test_bit(segno, free_i->free_segmap)); __set_inuse(sbi, segno); *newseg = segno; - spin_unlock(&free_i->segmap_lock); + write_unlock(&free_i->segmap_lock); } static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified) @@ -1010,7 +1010,7 @@ static void __next_free_blkoff(struct f2fs_sb_info *sbi, { struct seg_entry *se = get_seg_entry(sbi, seg->segno); int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long); - unsigned long *target_map = SIT_I(sbi)->tmp_map; + unsigned long target_map[entries]; unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map; unsigned long *cur_map = (unsigned long *)se->cur_valid_map; int i, pos; @@ -1134,8 +1134,8 @@ static const struct segment_allocation default_salloc_ops = { int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) { - __u64 start = F2FS_BYTES_TO_BLK(range->start); - __u64 end = start + F2FS_BYTES_TO_BLK(range->len) - 1; + __u64 start = range->start >> sbi->log_blocksize; + __u64 end = start + (range->len >> sbi->log_blocksize) - 1; unsigned int start_segno, end_segno; struct cp_control cpc; @@ -1152,21 +1152,16 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) end_segno = (end >= MAX_BLKADDR(sbi)) ? MAIN_SEGS(sbi) - 1 : GET_SEGNO(sbi, end); cpc.reason = CP_DISCARD; - cpc.trim_minlen = F2FS_BYTES_TO_BLK(range->minlen); + cpc.trim_start = start_segno; + cpc.trim_end = end_segno; + cpc.trim_minlen = range->minlen >> sbi->log_blocksize; /* do checkpoint to issue discard commands safely */ - for (; start_segno <= end_segno; start_segno = cpc.trim_end + 1) { - cpc.trim_start = start_segno; - cpc.trim_end = min_t(unsigned int, rounddown(start_segno + - BATCHED_TRIM_SEGMENTS(sbi), - sbi->segs_per_sec) - 1, end_segno); - - mutex_lock(&sbi->gc_mutex); - write_checkpoint(sbi, &cpc); - mutex_unlock(&sbi->gc_mutex); - } + mutex_lock(&sbi->gc_mutex); + write_checkpoint(sbi, &cpc); + mutex_unlock(&sbi->gc_mutex); out: - range->len = F2FS_BLK_TO_BYTES(cpc.trimmed); + range->len = cpc.trimmed << sbi->log_blocksize; return 0; } @@ -1492,7 +1487,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type) segno = le32_to_cpu(ckpt->cur_data_segno[type]); blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type - CURSEG_HOT_DATA]); - if (__exist_node_summaries(sbi)) + if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type); else blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type); @@ -1501,7 +1496,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type) CURSEG_HOT_NODE]); blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type - CURSEG_HOT_NODE]); - if (__exist_node_summaries(sbi)) + if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE, type - CURSEG_HOT_NODE); else @@ -1512,7 +1507,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type) sum = (struct f2fs_summary_block *)page_address(new); if (IS_NODESEG(type)) { - if (__exist_node_summaries(sbi)) { + if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) { struct f2fs_summary *ns = &sum->entries[0]; int i; for (i = 0; i < sbi->blocks_per_seg; i++, ns++) { @@ -1561,7 +1556,7 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi) type = CURSEG_HOT_NODE; } - if (__exist_node_summaries(sbi)) + if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG)) ra_meta_pages(sbi, sum_blk_addr(sbi, NR_CURSEG_TYPE, type), NR_CURSEG_TYPE - type, META_CP); @@ -1658,7 +1653,8 @@ void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk) void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk) { - write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE); + if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG)) + write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE); } int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type, @@ -1941,10 +1937,6 @@ static int build_sit_info(struct f2fs_sb_info *sbi) return -ENOMEM; } - sit_i->tmp_map = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); - if (!sit_i->tmp_map) - return -ENOMEM; - if (sbi->segs_per_sec > 1) { sit_i->sec_entries = vzalloc(MAIN_SECS(sbi) * sizeof(struct sec_entry)); @@ -2009,7 +2001,7 @@ static int build_free_segmap(struct f2fs_sb_info *sbi) free_i->start_segno = GET_SEGNO_FROM_SEG0(sbi, MAIN_BLKADDR(sbi)); free_i->free_segments = 0; free_i->free_sections = 0; - spin_lock_init(&free_i->segmap_lock); + rwlock_init(&free_i->segmap_lock); return 0; } @@ -2222,8 +2214,6 @@ int build_segment_manager(struct f2fs_sb_info *sbi) sm_info->nr_discards = 0; sm_info->max_discards = 0; - sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS; - INIT_LIST_HEAD(&sm_info->sit_entry_set); if (test_opt(sbi, FLUSH_MERGE) && !f2fs_readonly(sbi->sb)) { @@ -2326,8 +2316,6 @@ static void destroy_sit_info(struct f2fs_sb_info *sbi) kfree(sit_i->sentries[start].ckpt_valid_map); } } - kfree(sit_i->tmp_map); - vfree(sit_i->sentries); vfree(sit_i->sec_entries); kfree(sit_i->dirty_sentries_bitmap); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 7fd35111cf62..7f327c0ba4e3 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -189,7 +189,6 @@ struct sit_info { char *sit_bitmap; /* SIT bitmap pointer */ unsigned int bitmap_size; /* SIT bitmap size */ - unsigned long *tmp_map; /* bitmap for temporal use */ unsigned long *dirty_sentries_bitmap; /* bitmap for dirty sentries */ unsigned int dirty_sentries; /* # of dirty sentries */ unsigned int sents_per_block; /* # of SIT entries per block */ @@ -208,7 +207,7 @@ struct free_segmap_info { unsigned int start_segno; /* start segment number logically */ unsigned int free_segments; /* # of free segments */ unsigned int free_sections; /* # of free sections */ - spinlock_t segmap_lock; /* free segmap lock */ + rwlock_t segmap_lock; /* free segmap lock */ unsigned long *free_segmap; /* free segment bitmap */ unsigned long *free_secmap; /* free section bitmap */ }; @@ -319,9 +318,9 @@ static inline unsigned int find_next_inuse(struct free_segmap_info *free_i, unsigned int max, unsigned int segno) { unsigned int ret; - spin_lock(&free_i->segmap_lock); + read_lock(&free_i->segmap_lock); ret = find_next_bit(free_i->free_segmap, max, segno); - spin_unlock(&free_i->segmap_lock); + read_unlock(&free_i->segmap_lock); return ret; } @@ -332,7 +331,7 @@ static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno) unsigned int start_segno = secno * sbi->segs_per_sec; unsigned int next; - spin_lock(&free_i->segmap_lock); + write_lock(&free_i->segmap_lock); clear_bit(segno, free_i->free_segmap); free_i->free_segments++; @@ -341,7 +340,7 @@ static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno) clear_bit(secno, free_i->free_secmap); free_i->free_sections++; } - spin_unlock(&free_i->segmap_lock); + write_unlock(&free_i->segmap_lock); } static inline void __set_inuse(struct f2fs_sb_info *sbi, @@ -363,7 +362,7 @@ static inline void __set_test_and_free(struct f2fs_sb_info *sbi, unsigned int start_segno = secno * sbi->segs_per_sec; unsigned int next; - spin_lock(&free_i->segmap_lock); + write_lock(&free_i->segmap_lock); if (test_and_clear_bit(segno, free_i->free_segmap)) { free_i->free_segments++; @@ -374,7 +373,7 @@ static inline void __set_test_and_free(struct f2fs_sb_info *sbi, free_i->free_sections++; } } - spin_unlock(&free_i->segmap_lock); + write_unlock(&free_i->segmap_lock); } static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi, @@ -382,13 +381,13 @@ static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi, { struct free_segmap_info *free_i = FREE_I(sbi); unsigned int secno = segno / sbi->segs_per_sec; - spin_lock(&free_i->segmap_lock); + write_lock(&free_i->segmap_lock); if (!test_and_set_bit(segno, free_i->free_segmap)) { free_i->free_segments--; if (!test_and_set_bit(secno, free_i->free_secmap)) free_i->free_sections--; } - spin_unlock(&free_i->segmap_lock); + write_unlock(&free_i->segmap_lock); } static inline void get_sit_bitmap(struct f2fs_sb_info *sbi, @@ -461,7 +460,7 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed) int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES); int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS); - if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) + if (unlikely(sbi->por_doing)) return false; return (free_sections(sbi) + freed) <= (node_secs + 2 * dent_secs + @@ -600,13 +599,13 @@ static inline void check_block_count(struct f2fs_sb_info *sbi, static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) { if (segno > TOTAL_SEGS(sbi) - 1) - set_sbi_flag(sbi, SBI_NEED_FSCK); + sbi->need_fsck = true; } static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr) { if (blk_addr < SEG0_BLKADDR(sbi) || blk_addr >= MAX_BLKADDR(sbi)) - set_sbi_flag(sbi, SBI_NEED_FSCK); + sbi->need_fsck = true; } /* @@ -617,11 +616,11 @@ static inline void check_block_count(struct f2fs_sb_info *sbi, { /* check segment usage */ if (GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg) - set_sbi_flag(sbi, SBI_NEED_FSCK); + sbi->need_fsck = true; /* check boundary of a given segment number */ if (segno > TOTAL_SEGS(sbi) - 1) - set_sbi_flag(sbi, SBI_NEED_FSCK); + sbi->need_fsck = true; } #endif diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 4ab9c76e7159..a320b41d2182 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -42,7 +42,6 @@ static struct kset *f2fs_kset; enum { Opt_gc_background, Opt_disable_roll_forward, - Opt_norecovery, Opt_discard, Opt_noheap, Opt_user_xattr, @@ -63,7 +62,6 @@ enum { static match_table_t f2fs_tokens = { {Opt_gc_background, "background_gc=%s"}, {Opt_disable_roll_forward, "disable_roll_forward"}, - {Opt_norecovery, "norecovery"}, {Opt_discard, "discard"}, {Opt_noheap, "no_heap"}, {Opt_user_xattr, "user_xattr"}, @@ -195,7 +193,6 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time); F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards); -F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, batched_trim_sections, trim_sections); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_fsync_blocks, min_fsync_blocks); @@ -211,7 +208,6 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(gc_idle), ATTR_LIST(reclaim_segments), ATTR_LIST(max_small_discards), - ATTR_LIST(batched_trim_sections), ATTR_LIST(ipu_policy), ATTR_LIST(min_ipu_util), ATTR_LIST(min_fsync_blocks), @@ -291,12 +287,6 @@ static int parse_options(struct super_block *sb, char *options) case Opt_disable_roll_forward: set_opt(sbi, DISABLE_ROLL_FORWARD); break; - case Opt_norecovery: - /* this option mounts f2fs with ro */ - set_opt(sbi, DISABLE_ROLL_FORWARD); - if (!f2fs_readonly(sb)) - return -EINVAL; - break; case Opt_discard: set_opt(sbi, DISCARD); break; @@ -457,13 +447,8 @@ static void f2fs_put_super(struct super_block *sb) f2fs_destroy_stats(sbi); stop_gc_thread(sbi); - /* - * We don't need to do checkpoint when superblock is clean. - * But, the previous checkpoint was not done by umount, it needs to do - * clean checkpoint again. - */ - if (is_sbi_flag_set(sbi, SBI_IS_DIRTY) || - !is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG)) { + /* We don't need to do checkpoint when it's clean */ + if (sbi->s_dirty) { struct cp_control cpc = { .reason = CP_UMOUNT, }; @@ -502,8 +487,7 @@ int f2fs_sync_fs(struct super_block *sb, int sync) if (sync) { struct cp_control cpc; - cpc.reason = __get_cp_reason(sbi); - + cpc.reason = test_opt(sbi, FASTBOOT) ? CP_UMOUNT : CP_SYNC; mutex_lock(&sbi->gc_mutex); write_checkpoint(sbi, &cpc); mutex_unlock(&sbi->gc_mutex); @@ -905,7 +889,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi) atomic_set(&sbi->nr_pages[i], 0); sbi->dir_level = DEF_DIR_LEVEL; - clear_sbi_flag(sbi, SBI_NEED_FSCK); + sbi->need_fsck = false; } /* @@ -960,7 +944,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) struct inode *root; long err = -EINVAL; bool retry = true; - char *options = NULL; int i; try_onemore: @@ -992,15 +975,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) set_opt(sbi, POSIX_ACL); #endif /* parse mount options */ - options = kstrdup((const char *)data, GFP_KERNEL); - if (data && !options) { - err = -ENOMEM; - goto free_sb_buf; - } - - err = parse_options(sb, options); + err = parse_options(sb, (char *)data); if (err) - goto free_options; + goto free_sb_buf; sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize)); sb->s_max_links = F2FS_LINK_MAX; @@ -1023,7 +1000,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) mutex_init(&sbi->writepages); mutex_init(&sbi->cp_mutex); init_rwsem(&sbi->node_write); - clear_sbi_flag(sbi, SBI_POR_DOING); + sbi->por_doing = false; spin_lock_init(&sbi->stat_lock); init_rwsem(&sbi->read_io.io_rwsem); @@ -1044,7 +1021,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) if (IS_ERR(sbi->meta_inode)) { f2fs_msg(sb, KERN_ERR, "Failed to read F2FS meta data inode"); err = PTR_ERR(sbi->meta_inode); - goto free_options; + goto free_sb_buf; } err = get_valid_checkpoint(sbi); @@ -1147,19 +1124,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) goto free_proc; if (!retry) - set_sbi_flag(sbi, SBI_NEED_FSCK); + sbi->need_fsck = true; /* recover fsynced data */ if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) { - /* - * mount should be failed, when device has readonly mode, and - * previous checkpoint was not done by clean system shutdown. - */ - if (bdev_read_only(sb->s_bdev) && - !is_set_ckpt_flags(sbi->ckpt, CP_UMOUNT_FLAG)) { - err = -EROFS; - goto free_kobj; - } err = recover_fsync_data(sbi); if (err) { f2fs_msg(sb, KERN_ERR, @@ -1178,7 +1146,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) if (err) goto free_kobj; } - kfree(options); return 0; free_kobj: @@ -1203,8 +1170,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) free_meta_inode: make_bad_inode(sbi->meta_inode); iput(sbi->meta_inode); -free_options: - kfree(options); free_sb_buf: brelse(raw_super_buf); free_sbi: @@ -1225,18 +1190,11 @@ static struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags, return mount_bdev(fs_type, flags, dev_name, data, f2fs_fill_super); } -static void kill_f2fs_super(struct super_block *sb) -{ - if (sb->s_root) - set_sbi_flag(F2FS_SB(sb), SBI_IS_CLOSE); - kill_block_super(sb); -} - static struct file_system_type f2fs_fs_type = { .owner = THIS_MODULE, .name = "f2fs", .mount = f2fs_mount, - .kill_sb = kill_f2fs_super, + .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; diff --git a/fs/f2fs/trace.c b/fs/f2fs/trace.c index 875aa8179bc1..ce01a2c903bd 100644 --- a/fs/f2fs/trace.c +++ b/fs/f2fs/trace.c @@ -16,9 +16,9 @@ #include "f2fs.h" #include "trace.h" -static RADIX_TREE(pids, GFP_ATOMIC); +RADIX_TREE(pids, GFP_ATOMIC); static spinlock_t pids_lock; -static struct last_io_info last_io; +struct last_io_info last_io; static inline void __print_last_io(void) { diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index a23556c32703..e993b0bc9abf 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -19,16 +19,12 @@ #define F2FS_MAX_LOG_SECTOR_SIZE 12 /* 12 bits for 4096 bytes */ #define F2FS_LOG_SECTORS_PER_BLOCK 3 /* log number for sector/blk */ #define F2FS_BLKSIZE 4096 /* support only 4KB block */ -#define F2FS_BLKSIZE_BITS 12 /* bits for F2FS_BLKSIZE */ #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ #define F2FS_BLK_ALIGN(x) (((x) + F2FS_BLKSIZE - 1) / F2FS_BLKSIZE) #define NULL_ADDR ((block_t)0) /* used as block_t addresses */ #define NEW_ADDR ((block_t)-1) /* used as block_t addresses */ -#define F2FS_BYTES_TO_BLK(bytes) ((bytes) >> F2FS_BLKSIZE_BITS) -#define F2FS_BLK_TO_BYTES(blk) ((blk) << F2FS_BLKSIZE_BITS) - /* 0, 1(node nid), 2(meta nid) are reserved node id */ #define F2FS_RESERVED_NODE_NUM 3 @@ -91,7 +87,6 @@ struct f2fs_super_block { /* * For checkpoint */ -#define CP_FASTBOOT_FLAG 0x00000020 #define CP_FSCK_FLAG 0x00000010 #define CP_ERROR_FLAG 0x00000008 #define CP_COMPACT_SUM_FLAG 0x00000004 diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index b83cc022b559..a3e6dd4b5d77 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -72,7 +72,6 @@ #define show_cpreason(type) \ __print_symbolic(type, \ { CP_UMOUNT, "Umount" }, \ - { CP_FASTBOOT, "Fastboot" }, \ { CP_SYNC, "Sync" }, \ { CP_DISCARD, "Discard" }) @@ -149,14 +148,14 @@ DEFINE_EVENT(f2fs__inode, f2fs_sync_file_enter, TRACE_EVENT(f2fs_sync_file_exit, - TP_PROTO(struct inode *inode, int need_cp, int datasync, int ret), + TP_PROTO(struct inode *inode, bool need_cp, int datasync, int ret), TP_ARGS(inode, need_cp, datasync, ret), TP_STRUCT__entry( __field(dev_t, dev) __field(ino_t, ino) - __field(int, need_cp) + __field(bool, need_cp) __field(int, datasync) __field(int, ret) ), @@ -191,7 +190,7 @@ TRACE_EVENT(f2fs_sync_fs, TP_fast_assign( __entry->dev = sb->s_dev; - __entry->dirty = is_sbi_flag_set(F2FS_SB(sb), SBI_IS_DIRTY); + __entry->dirty = F2FS_SB(sb)->s_dirty; __entry->wait = wait; ), @@ -986,15 +985,14 @@ TRACE_EVENT(f2fs_issue_discard, TRACE_EVENT(f2fs_issue_flush, - TP_PROTO(struct super_block *sb, unsigned int nobarrier, - unsigned int flush_merge), + TP_PROTO(struct super_block *sb, bool nobarrier, bool flush_merge), TP_ARGS(sb, nobarrier, flush_merge), TP_STRUCT__entry( __field(dev_t, dev) - __field(unsigned int, nobarrier) - __field(unsigned int, flush_merge) + __field(bool, nobarrier) + __field(bool, flush_merge) ), TP_fast_assign(