Skip to content

Commit

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

Pull f2fs update from Jaegeuk Kim:
 "[Major bug fixes]
   o Store device file information correctly
   o Fix -EIO handling with respect to power-off-recovery
   o Allocate blocks with global locks
   o Fix wrong calculation of the SSR cost

  [Cleanups]
   o Get rid of fake on-stack dentries

  [Enhancement]
   o Support (un)freeze_fs
   o Enhance the f2fs_gc flow
   o Support 32-bit binary execution on 64-bit kernel"

* tag 'f2fs-for-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (29 commits)
  f2fs: avoid build warning
  f2fs: add compat_ioctl to provide backward compatability
  f2fs: fix calculation of max. gc cost in the SSR case
  f2fs: clarify and enhance the f2fs_gc flow
  f2fs: optimize the return condition for has_not_enough_free_secs
  f2fs: make an accessor to get sections for particular block type
  f2fs: mark gc_thread as NULL when thread creation is failed
  f2fs: name gc task as per the block device
  f2fs: remove unnecessary gc option check and balance_fs
  f2fs: remove repeated F2FS_SET_SB_DIRT call
  f2fs: when check superblock failed, try to check another superblock
  f2fs: use F2FS_BLKSIZE to judge bloksize and page_cache_size
  f2fs: add device name in debugfs
  f2fs: stop repeated checking if cp is needed
  f2fs: avoid balanc_fs during evict_inode
  f2fs: remove the use of page_cache_release
  f2fs: fix typo mistake for data_version description
  f2fs: reorganize code for ra_node_page
  f2fs: avoid redundant call to has_not_enough_free_secs in f2fs_gc
  f2fs: add un/freeze_fs into super_operations
  ...
  • Loading branch information
Linus Torvalds committed Feb 26, 2013
2 parents 3c834b6 + 7dd690c commit 1085db4
Show file tree
Hide file tree
Showing 13 changed files with 292 additions and 261 deletions.
63 changes: 27 additions & 36 deletions fs/f2fs/checkpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,22 @@ static int f2fs_write_meta_page(struct page *page,
{
struct inode *inode = page->mapping->host;
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
int err;

wait_on_page_writeback(page);

err = write_meta_page(sbi, page, wbc);
if (err) {
/* Should not write any meta pages, if any IO error was occurred */
if (wbc->for_reclaim ||
is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)) {
dec_page_count(sbi, F2FS_DIRTY_META);
wbc->pages_skipped++;
set_page_dirty(page);
return AOP_WRITEPAGE_ACTIVATE;
}

dec_page_count(sbi, F2FS_DIRTY_META);
wait_on_page_writeback(page);

/* In this case, we should not unlock this page */
if (err != AOP_WRITEPAGE_ACTIVATE)
unlock_page(page);
return err;
write_meta_page(sbi, page);
dec_page_count(sbi, F2FS_DIRTY_META);
unlock_page(page);
return 0;
}

static int f2fs_write_meta_pages(struct address_space *mapping,
Expand Down Expand Up @@ -138,7 +138,10 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
BUG_ON(page->mapping != mapping);
BUG_ON(!PageDirty(page));
clear_page_dirty_for_io(page);
f2fs_write_meta_page(page, &wbc);
if (f2fs_write_meta_page(page, &wbc)) {
unlock_page(page);
break;
}
if (nwritten++ >= nr_to_write)
break;
}
Expand All @@ -161,7 +164,6 @@ static int f2fs_set_meta_page_dirty(struct page *page)
if (!PageDirty(page)) {
__set_page_dirty_nobuffers(page);
inc_page_count(sbi, F2FS_DIRTY_META);
F2FS_SET_SB_DIRT(sbi);
return 1;
}
return 0;
Expand Down Expand Up @@ -216,19 +218,11 @@ void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
new->ino = ino;

/* add new_oentry into list which is sorted by inode number */
if (orphan) {
struct orphan_inode_entry *prev;

/* get previous entry */
prev = list_entry(orphan->list.prev, typeof(*prev), list);
if (&prev->list != head)
/* insert new orphan inode entry */
list_add(&new->list, &prev->list);
else
list_add(&new->list, head);
} else {
if (orphan)
list_add(&new->list, this->prev);
else
list_add_tail(&new->list, head);
}

sbi->n_orphans++;
out:
mutex_unlock(&sbi->orphan_inode_mutex);
Expand Down Expand Up @@ -545,7 +539,7 @@ void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
/*
* Freeze all the FS-operations for checkpoint.
*/
void block_operations(struct f2fs_sb_info *sbi)
static void block_operations(struct f2fs_sb_info *sbi)
{
int t;
struct writeback_control wbc = {
Expand Down Expand Up @@ -717,27 +711,24 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
sbi->alloc_valid_block_count = 0;

/* Here, we only have one bio having CP pack */
if (is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))
sbi->sb->s_flags |= MS_RDONLY;
else
sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
sync_meta_pages(sbi, META_FLUSH, LONG_MAX);

clear_prefree_segments(sbi);
F2FS_RESET_SB_DIRT(sbi);
if (!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) {
clear_prefree_segments(sbi);
F2FS_RESET_SB_DIRT(sbi);
}
}

/*
* We guarantee that this checkpoint procedure should not fail.
*/
void write_checkpoint(struct f2fs_sb_info *sbi, bool blocked, bool is_umount)
void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
{
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
unsigned long long ckpt_ver;

if (!blocked) {
mutex_lock(&sbi->cp_mutex);
block_operations(sbi);
}
mutex_lock(&sbi->cp_mutex);
block_operations(sbi);

f2fs_submit_bio(sbi, DATA, true);
f2fs_submit_bio(sbi, NODE, true);
Expand Down
4 changes: 3 additions & 1 deletion fs/f2fs/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,12 @@ static int stat_show(struct seq_file *s, void *v)

mutex_lock(&f2fs_stat_mutex);
list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) {
char devname[BDEVNAME_SIZE];

update_general_status(si->sbi);

seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++);
seq_printf(s, "\n=====[ partition info(%s). #%d ]=====\n",
bdevname(si->sbi->sb->s_bdev, devname), i++);
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",
Expand Down
29 changes: 13 additions & 16 deletions fs/f2fs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
mutex_unlock_op(sbi, DENTRY_OPS);
}

void init_dent_inode(struct dentry *dentry, struct page *ipage)
void init_dent_inode(const struct qstr *name, struct page *ipage)
{
struct f2fs_node *rn;

Expand All @@ -274,20 +274,19 @@ void init_dent_inode(struct dentry *dentry, struct page *ipage)

wait_on_page_writeback(ipage);

/* copy dentry info. to this inode page */
/* copy name info. to this inode page */
rn = (struct f2fs_node *)page_address(ipage);
rn->i.i_namelen = cpu_to_le32(dentry->d_name.len);
memcpy(rn->i.i_name, dentry->d_name.name, dentry->d_name.len);
rn->i.i_namelen = cpu_to_le32(name->len);
memcpy(rn->i.i_name, name->name, name->len);
set_page_dirty(ipage);
}

static int init_inode_metadata(struct inode *inode, struct dentry *dentry)
static int init_inode_metadata(struct inode *inode,
struct inode *dir, const struct qstr *name)
{
struct inode *dir = dentry->d_parent->d_inode;

if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
int err;
err = new_inode_page(inode, dentry);
err = new_inode_page(inode, name);
if (err)
return err;

Expand All @@ -310,7 +309,7 @@ static int init_inode_metadata(struct inode *inode, struct dentry *dentry)
if (IS_ERR(ipage))
return PTR_ERR(ipage);
set_cold_node(inode, ipage);
init_dent_inode(dentry, ipage);
init_dent_inode(name, ipage);
f2fs_put_page(ipage, 1);
}
if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) {
Expand Down Expand Up @@ -371,7 +370,7 @@ static int room_for_filename(struct f2fs_dentry_block *dentry_blk, int slots)
goto next;
}

int f2fs_add_link(struct dentry *dentry, struct inode *inode)
int __f2fs_add_link(struct inode *dir, const struct qstr *name, struct inode *inode)
{
unsigned int bit_pos;
unsigned int level;
Expand All @@ -380,17 +379,15 @@ int f2fs_add_link(struct dentry *dentry, struct inode *inode)
f2fs_hash_t dentry_hash;
struct f2fs_dir_entry *de;
unsigned int nbucket, nblock;
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;
size_t namelen = dentry->d_name.len;
size_t namelen = name->len;
struct page *dentry_page = NULL;
struct f2fs_dentry_block *dentry_blk = NULL;
int slots = GET_DENTRY_SLOTS(namelen);
int err = 0;
int i;

dentry_hash = f2fs_dentry_hash(name, dentry->d_name.len);
dentry_hash = f2fs_dentry_hash(name->name, name->len);
level = 0;
current_depth = F2FS_I(dir)->i_current_depth;
if (F2FS_I(dir)->chash == dentry_hash) {
Expand Down Expand Up @@ -433,7 +430,7 @@ int f2fs_add_link(struct dentry *dentry, struct inode *inode)
++level;
goto start;
add_dentry:
err = init_inode_metadata(inode, dentry);
err = init_inode_metadata(inode, dir, name);
if (err)
goto fail;

Expand All @@ -442,7 +439,7 @@ int f2fs_add_link(struct dentry *dentry, struct inode *inode)
de = &dentry_blk->dentry[bit_pos];
de->hash_code = dentry_hash;
de->name_len = cpu_to_le16(namelen);
memcpy(dentry_blk->filename[bit_pos], name, namelen);
memcpy(dentry_blk->filename[bit_pos], name->name, name->len);
de->ino = cpu_to_le32(inode->i_ino);
set_de_type(de, inode);
for (i = 0; i < slots; i++)
Expand Down
44 changes: 35 additions & 9 deletions fs/f2fs/f2fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,20 @@ static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i)
return before;
}

/*
* ioctl commands
*/
#define F2FS_IOC_GETFLAGS FS_IOC_GETFLAGS
#define F2FS_IOC_SETFLAGS FS_IOC_SETFLAGS

#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
/*
* ioctl commands in 32 bit emulation
*/
#define F2FS_IOC32_GETFLAGS FS_IOC32_GETFLAGS
#define F2FS_IOC32_SETFLAGS FS_IOC32_SETFLAGS
#endif

/*
* For INODE and NODE manager
*/
Expand Down Expand Up @@ -141,7 +155,7 @@ struct f2fs_inode_info {

/* Use below internally in f2fs*/
unsigned long flags; /* use to pass per-file flags */
unsigned long long data_version;/* lastes version of data for fsync */
unsigned long long data_version;/* latest version of data for fsync */
atomic_t dirty_dents; /* # of dirty dentry pages */
f2fs_hash_t chash; /* hash value of given file name */
unsigned int clevel; /* maximum level of given file name */
Expand Down Expand Up @@ -573,6 +587,14 @@ static inline int get_pages(struct f2fs_sb_info *sbi, int count_type)
return atomic_read(&sbi->nr_pages[count_type]);
}

static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
{
unsigned int pages_per_sec = sbi->segs_per_sec *
(1 << sbi->log_blocks_per_seg);
return ((get_pages(sbi, block_type) + pages_per_sec - 1)
>> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
}

static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
{
block_t ret;
Expand Down Expand Up @@ -842,12 +864,12 @@ void f2fs_truncate(struct inode *);
int f2fs_setattr(struct dentry *, struct iattr *);
int truncate_hole(struct inode *, pgoff_t, pgoff_t);
long f2fs_ioctl(struct file *, unsigned int, unsigned long);
long f2fs_compat_ioctl(struct file *, unsigned int, unsigned long);

/*
* inode.c
*/
void f2fs_set_inode_flags(struct inode *);
struct inode *f2fs_iget_nowait(struct super_block *, unsigned long);
struct inode *f2fs_iget(struct super_block *, unsigned long);
void update_inode(struct inode *, struct page *);
int f2fs_write_inode(struct inode *, struct writeback_control *);
Expand All @@ -867,12 +889,18 @@ struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
ino_t f2fs_inode_by_name(struct inode *, struct qstr *);
void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
struct page *, struct inode *);
void init_dent_inode(struct dentry *, struct page *);
int f2fs_add_link(struct dentry *, struct inode *);
void init_dent_inode(const struct qstr *, struct page *);
int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *);
void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *);
int f2fs_make_empty(struct inode *, struct inode *);
bool f2fs_empty_dir(struct inode *);

static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
{
return __f2fs_add_link(dentry->d_parent->d_inode, &dentry->d_name,
inode);
}

/*
* super.c
*/
Expand All @@ -896,7 +924,7 @@ void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
int truncate_inode_blocks(struct inode *, pgoff_t);
int remove_inode_page(struct inode *);
int new_inode_page(struct inode *, struct dentry *);
int new_inode_page(struct inode *, const struct qstr *);
struct page *new_node_page(struct dnode_of_data *, unsigned int);
void ra_node_page(struct f2fs_sb_info *, nid_t);
struct page *get_node_page(struct f2fs_sb_info *, pgoff_t);
Expand Down Expand Up @@ -929,8 +957,7 @@ void allocate_new_segments(struct f2fs_sb_info *);
struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
struct bio *f2fs_bio_alloc(struct block_device *, int);
void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool sync);
int write_meta_page(struct f2fs_sb_info *, struct page *,
struct writeback_control *);
void write_meta_page(struct f2fs_sb_info *, struct page *);
void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
block_t, block_t *);
void write_data_page(struct inode *, struct page *, struct dnode_of_data*,
Expand Down Expand Up @@ -963,8 +990,7 @@ int get_valid_checkpoint(struct f2fs_sb_info *);
void set_dirty_dir_page(struct inode *, struct page *);
void remove_dirty_dir_inode(struct inode *);
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 write_checkpoint(struct f2fs_sb_info *, bool);
void init_orphan_info(struct f2fs_sb_info *);
int __init create_checkpoint_caches(void);
void destroy_checkpoint_caches(void);
Expand Down
Loading

0 comments on commit 1085db4

Please sign in to comment.