Skip to content

Commit

Permalink
Merge tag 'f2fs-for-3.8-rc5' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/jaegeuk/f2fs

Pull f2fs fixes from Jaegeuk Kim:
 o Support swap file and link generic_file_remap_pages
 o Enhance the bio streaming flow and free section control
 o Major bug fix on recovery routine
 o Minor bug/warning fixes and code cleanups

* tag 'f2fs-for-3.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (22 commits)
  f2fs: use _safe() version of list_for_each
  f2fs: add comments of start_bidx_of_node
  f2fs: avoid issuing small bios due to several dirty node pages
  f2fs: support swapfile
  f2fs: add remap_pages as generic_file_remap_pages
  f2fs: add __init to functions in init_f2fs_fs
  f2fs: fix the debugfs entry creation path
  f2fs: add global mutex_lock to protect f2fs_stat_list
  f2fs: remove the blk_plug usage in f2fs_write_data_pages
  f2fs: avoid redundant time update for parent directory in f2fs_delete_entry
  f2fs: remove redundant call to set_blocksize in f2fs_fill_super
  f2fs: move f2fs_balance_fs to punch_hole
  f2fs: add f2fs_balance_fs in several interfaces
  f2fs: revisit the f2fs_gc flow
  f2fs: check return value during recovery
  f2fs: avoid null dereference in f2fs_acl_from_disk
  f2fs: initialize newly allocated dnode structure
  f2fs: update f2fs partition info about SIT/NAT layout
  f2fs: update f2fs document to reflect SIT/NAT layout correctly
  f2fs: remove unneeded INIT_LIST_HEAD at few places
  ...
  • Loading branch information
Linus Torvalds committed Jan 22, 2013
2 parents 3c2a9f8 + d8b79b2 commit 05c2cf3
Show file tree
Hide file tree
Showing 15 changed files with 198 additions and 140 deletions.
18 changes: 9 additions & 9 deletions Documentation/filesystems/f2fs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,9 @@ consists of multiple segments as described below.
align with the zone size <-|
|-> align with the segment size
_________________________________________________________________________
| | | Node | Segment | Segment | |
| Superblock | Checkpoint | Address | Info. | Summary | Main |
| (SB) | (CP) | Table (NAT) | Table (SIT) | Area (SSA) | |
| | | Segment | Node | Segment | |
| Superblock | Checkpoint | Info. | Address | Summary | Main |
| (SB) | (CP) | Table (SIT) | Table (NAT) | Area (SSA) | |
|____________|_____2______|______N______|______N______|______N_____|__N___|
. .
. .
Expand All @@ -200,14 +200,14 @@ consists of multiple segments as described below.
: It contains file system information, bitmaps for valid NAT/SIT sets, orphan
inode lists, and summary entries of current active segments.

- Node Address Table (NAT)
: It is composed of a block address table for all the node blocks stored in
Main area.

- Segment Information Table (SIT)
: It contains segment information such as valid block count and bitmap for the
validity of all the blocks.

- Node Address Table (NAT)
: It is composed of a block address table for all the node blocks stored in
Main area.

- Segment Summary Area (SSA)
: It contains summary entries which contains the owner information of all the
data and node blocks stored in Main area.
Expand Down Expand Up @@ -236,13 +236,13 @@ For file system consistency, each CP points to which NAT and SIT copies are
valid, as shown as below.

+--------+----------+---------+
| CP | NAT | SIT |
| CP | SIT | NAT |
+--------+----------+---------+
. . . .
. . . .
. . . .
+-------+-------+--------+--------+--------+--------+
| CP #0 | CP #1 | NAT #0 | NAT #1 | SIT #0 | SIT #1 |
| CP #0 | CP #1 | SIT #0 | SIT #1 | NAT #0 | NAT #1 |
+-------+-------+--------+--------+--------+--------+
| ^ ^
| | |
Expand Down
13 changes: 6 additions & 7 deletions fs/f2fs/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,14 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
retval = f2fs_getxattr(inode, name_index, "", value, retval);
}

if (retval < 0) {
if (retval == -ENODATA)
acl = NULL;
else
acl = ERR_PTR(retval);
} else {
if (retval > 0)
acl = f2fs_acl_from_disk(value, retval);
}
else if (retval == -ENODATA)
acl = NULL;
else
acl = ERR_PTR(retval);
kfree(value);

if (!IS_ERR(acl))
set_cached_acl(inode, type, acl);

Expand Down
3 changes: 1 addition & 2 deletions fs/f2fs/checkpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@ void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
goto retry;
}
new->ino = ino;
INIT_LIST_HEAD(&new->list);

/* add new_oentry into list which is sorted by inode number */
if (orphan) {
Expand Down Expand Up @@ -772,7 +771,7 @@ void init_orphan_info(struct f2fs_sb_info *sbi)
sbi->n_orphans = 0;
}

int create_checkpoint_caches(void)
int __init create_checkpoint_caches(void)
{
orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry",
sizeof(struct orphan_inode_entry), NULL);
Expand Down
17 changes: 16 additions & 1 deletion fs/f2fs/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,15 @@ static int f2fs_write_data_page(struct page *page,

#define MAX_DESIRED_PAGES_WP 4096

static int __f2fs_writepage(struct page *page, struct writeback_control *wbc,
void *data)
{
struct address_space *mapping = data;
int ret = mapping->a_ops->writepage(page, wbc);
mapping_set_error(mapping, ret);
return ret;
}

static int f2fs_write_data_pages(struct address_space *mapping,
struct writeback_control *wbc)
{
Expand All @@ -563,7 +572,7 @@ static int f2fs_write_data_pages(struct address_space *mapping,

if (!S_ISDIR(inode->i_mode))
mutex_lock(&sbi->writepages);
ret = generic_writepages(mapping, wbc);
ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping);
if (!S_ISDIR(inode->i_mode))
mutex_unlock(&sbi->writepages);
f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL));
Expand Down Expand Up @@ -689,6 +698,11 @@ static int f2fs_set_data_page_dirty(struct page *page)
return 0;
}

static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping, block, get_data_block_ro);
}

const struct address_space_operations f2fs_dblock_aops = {
.readpage = f2fs_read_data_page,
.readpages = f2fs_read_data_pages,
Expand All @@ -700,4 +714,5 @@ const struct address_space_operations f2fs_dblock_aops = {
.invalidatepage = f2fs_invalidate_data_page,
.releasepage = f2fs_release_data_page,
.direct_IO = f2fs_direct_IO,
.bmap = f2fs_bmap,
};
50 changes: 21 additions & 29 deletions fs/f2fs/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

static LIST_HEAD(f2fs_stat_list);
static struct dentry *debugfs_root;
static DEFINE_MUTEX(f2fs_stat_mutex);

static void update_general_status(struct f2fs_sb_info *sbi)
{
Expand Down Expand Up @@ -180,18 +181,14 @@ static int stat_show(struct seq_file *s, void *v)
int i = 0;
int j;

mutex_lock(&f2fs_stat_mutex);
list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) {

mutex_lock(&si->stat_lock);
if (!si->sbi) {
mutex_unlock(&si->stat_lock);
continue;
}
update_general_status(si->sbi);

seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++);
seq_printf(s, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
si->nat_area_segs, si->sit_area_segs);
seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ",
si->sit_area_segs, si->nat_area_segs);
seq_printf(s, "[SSA: %d] [MAIN: %d",
si->ssa_area_segs, si->main_area_segs);
seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",
Expand Down Expand Up @@ -286,8 +283,8 @@ static int stat_show(struct seq_file *s, void *v)
seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n",
(si->base_mem + si->cache_mem) >> 10,
si->base_mem >> 10, si->cache_mem >> 10);
mutex_unlock(&si->stat_lock);
}
mutex_unlock(&f2fs_stat_mutex);
return 0;
}

Expand All @@ -303,7 +300,7 @@ static const struct file_operations stat_fops = {
.release = single_release,
};

static int init_stats(struct f2fs_sb_info *sbi)
int f2fs_build_stats(struct f2fs_sb_info *sbi)
{
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
struct f2fs_stat_info *si;
Expand All @@ -313,9 +310,6 @@ static int init_stats(struct f2fs_sb_info *sbi)
return -ENOMEM;

si = sbi->stat_info;
mutex_init(&si->stat_lock);
list_add_tail(&si->stat_list, &f2fs_stat_list);

si->all_area_segs = le32_to_cpu(raw_super->segment_count);
si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
Expand All @@ -325,36 +319,34 @@ static int init_stats(struct f2fs_sb_info *sbi)
si->main_area_zones = si->main_area_sections /
le32_to_cpu(raw_super->secs_per_zone);
si->sbi = sbi;
return 0;
}

int f2fs_build_stats(struct f2fs_sb_info *sbi)
{
int retval;

retval = init_stats(sbi);
if (retval)
return retval;

if (!debugfs_root)
debugfs_root = debugfs_create_dir("f2fs", NULL);
mutex_lock(&f2fs_stat_mutex);
list_add_tail(&si->stat_list, &f2fs_stat_list);
mutex_unlock(&f2fs_stat_mutex);

debugfs_create_file("status", S_IRUGO, debugfs_root, NULL, &stat_fops);
return 0;
}

void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
{
struct f2fs_stat_info *si = sbi->stat_info;

mutex_lock(&f2fs_stat_mutex);
list_del(&si->stat_list);
mutex_lock(&si->stat_lock);
si->sbi = NULL;
mutex_unlock(&si->stat_lock);
mutex_unlock(&f2fs_stat_mutex);

kfree(sbi->stat_info);
}

void destroy_root_stats(void)
void __init f2fs_create_root_stats(void)
{
debugfs_root = debugfs_create_dir("f2fs", NULL);
if (debugfs_root)
debugfs_create_file("status", S_IRUGO, debugfs_root,
NULL, &stat_fops);
}

void f2fs_destroy_root_stats(void)
{
debugfs_remove_recursive(debugfs_root);
debugfs_root = NULL;
Expand Down
2 changes: 1 addition & 1 deletion fs/f2fs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
}

if (inode) {
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
inode->i_ctime = CURRENT_TIME;
drop_nlink(inode);
if (S_ISDIR(inode->i_mode)) {
drop_nlink(inode);
Expand Down
18 changes: 11 additions & 7 deletions fs/f2fs/f2fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,11 @@ struct dnode_of_data {
static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
struct page *ipage, struct page *npage, nid_t nid)
{
memset(dn, 0, sizeof(*dn));
dn->inode = inode;
dn->inode_page = ipage;
dn->node_page = npage;
dn->nid = nid;
dn->inode_page_locked = 0;
}

/*
Expand Down Expand Up @@ -877,6 +877,8 @@ bool f2fs_empty_dir(struct inode *);
* super.c
*/
int f2fs_sync_fs(struct super_block *, int);
extern __printf(3, 4)
void f2fs_msg(struct super_block *, const char *, const char *, ...);

/*
* hash.c
Expand Down Expand Up @@ -912,7 +914,7 @@ int restore_node_summary(struct f2fs_sb_info *, unsigned int,
void flush_nat_entries(struct f2fs_sb_info *);
int build_node_manager(struct f2fs_sb_info *);
void destroy_node_manager(struct f2fs_sb_info *);
int create_node_manager_caches(void);
int __init create_node_manager_caches(void);
void destroy_node_manager_caches(void);

/*
Expand Down Expand Up @@ -964,7 +966,7 @@ void sync_dirty_dir_inodes(struct f2fs_sb_info *);
void block_operations(struct f2fs_sb_info *);
void write_checkpoint(struct f2fs_sb_info *, bool, bool);
void init_orphan_info(struct f2fs_sb_info *);
int create_checkpoint_caches(void);
int __init create_checkpoint_caches(void);
void destroy_checkpoint_caches(void);

/*
Expand All @@ -984,9 +986,9 @@ int do_write_data_page(struct page *);
int start_gc_thread(struct f2fs_sb_info *);
void stop_gc_thread(struct f2fs_sb_info *);
block_t start_bidx_of_node(unsigned int);
int f2fs_gc(struct f2fs_sb_info *, int);
int f2fs_gc(struct f2fs_sb_info *);
void build_gc_manager(struct f2fs_sb_info *);
int create_gc_caches(void);
int __init create_gc_caches(void);
void destroy_gc_caches(void);

/*
Expand Down Expand Up @@ -1058,7 +1060,8 @@ struct f2fs_stat_info {

int f2fs_build_stats(struct f2fs_sb_info *);
void f2fs_destroy_stats(struct f2fs_sb_info *);
void destroy_root_stats(void);
void __init f2fs_create_root_stats(void);
void f2fs_destroy_root_stats(void);
#else
#define stat_inc_call_count(si)
#define stat_inc_seg_count(si, type)
Expand All @@ -1068,7 +1071,8 @@ void destroy_root_stats(void);

static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; }
static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { }
static inline void destroy_root_stats(void) { }
static inline void __init f2fs_create_root_stats(void) { }
static inline void f2fs_destroy_root_stats(void) { }
#endif

extern const struct file_operations f2fs_dir_operations;
Expand Down
16 changes: 12 additions & 4 deletions fs/f2fs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
}

static const struct vm_operations_struct f2fs_file_vm_ops = {
.fault = filemap_fault,
.page_mkwrite = f2fs_vm_page_mkwrite,
.fault = filemap_fault,
.page_mkwrite = f2fs_vm_page_mkwrite,
.remap_pages = generic_file_remap_pages,
};

static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode)
Expand Down Expand Up @@ -137,6 +138,9 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
if (ret)
return ret;

/* guarantee free sections for fsync */
f2fs_balance_fs(sbi);

mutex_lock(&inode->i_mutex);

if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
Expand Down Expand Up @@ -407,6 +411,8 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
struct dnode_of_data dn;
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);

f2fs_balance_fs(sbi);

mutex_lock_op(sbi, DATA_TRUNC);
set_new_dnode(&dn, inode, NULL, NULL, 0);
err = get_dnode_of_data(&dn, index, RDONLY_NODE);
Expand Down Expand Up @@ -534,7 +540,6 @@ static long f2fs_fallocate(struct file *file, int mode,
loff_t offset, loff_t len)
{
struct inode *inode = file->f_path.dentry->d_inode;
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
long ret;

if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
Expand All @@ -545,7 +550,10 @@ static long f2fs_fallocate(struct file *file, int mode,
else
ret = expand_inode_data(inode, offset, len, mode);

f2fs_balance_fs(sbi);
if (!ret) {
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
}
return ret;
}

Expand Down
Loading

0 comments on commit 05c2cf3

Please sign in to comment.