Skip to content

Commit

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

Pull f2fs updates from Jaegeuk Kim:
 "This patch-set includes the following major enhancement patches:
   - support inline xattrs
   - add sysfs support to control GCs explicitly
   - add proc entry to show the current segment usage information
   - improve the GC/SSR performance

  The other bug fixes are as follows:
   - avoid the overflow on status calculation
   - fix some error handling routines
   - fix inconsistent xattr states after power-off-recovery
   - fix incorrect xattr node offset definition
   - fix deadlock condition in fsync
   - fix the fdatasync routine for power-off-recovery"

* tag 'for-f2fs-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (40 commits)
  f2fs: optimize gc for better performance
  f2fs: merge more bios of node block writes
  f2fs: avoid an overflow during utilization calculation
  f2fs: trigger GC when there are prefree segments
  f2fs: use strncasecmp() simplify the string comparison
  f2fs: fix omitting to update inode page
  f2fs: support the inline xattrs
  f2fs: add the truncate_xattr_node function
  f2fs: introduce __find_xattr for readability
  f2fs: reserve the xattr space dynamically
  f2fs: add flags for inline xattrs
  f2fs: fix error return code in init_f2fs_fs()
  f2fs: fix wrong BUG_ON condition
  f2fs: fix memory leak when init f2fs filesystem fail
  f2fs: fix a compound statement label error
  f2fs: avoid writing inode redundantly when creating a file
  f2fs: alloc_page() doesn't return an ERR_PTR
  f2fs: should cover i_xattr_nid with its xattr node page lock
  f2fs: check the free space first in new_node_page
  f2fs: clean up the needless end 'return' of void function
  ...
  • Loading branch information
Linus Torvalds committed Sep 6, 2013
2 parents 2e03285 + a26b7c8 commit eb97a78
Show file tree
Hide file tree
Showing 21 changed files with 890 additions and 344 deletions.
26 changes: 26 additions & 0 deletions Documentation/ABI/testing/sysfs-fs-f2fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
What: /sys/fs/f2fs/<disk>/gc_max_sleep_time
Date: July 2013
Contact: "Namjae Jeon" <namjae.jeon@samsung.com>
Description:
Controls the maximun sleep time for gc_thread. Time
is in milliseconds.

What: /sys/fs/f2fs/<disk>/gc_min_sleep_time
Date: July 2013
Contact: "Namjae Jeon" <namjae.jeon@samsung.com>
Description:
Controls the minimum sleep time for gc_thread. Time
is in milliseconds.

What: /sys/fs/f2fs/<disk>/gc_no_gc_sleep_time
Date: July 2013
Contact: "Namjae Jeon" <namjae.jeon@samsung.com>
Description:
Controls the default sleep time for gc_thread. Time
is in milliseconds.

What: /sys/fs/f2fs/<disk>/gc_idle
Date: July 2013
Contact: "Namjae Jeon" <namjae.jeon@samsung.com>
Description:
Controls the victim selection policy for garbage collection.
75 changes: 71 additions & 4 deletions Documentation/filesystems/f2fs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ according to its internal geometry or flash memory management scheme, namely FTL
F2FS and its tools support various parameters not only for configuring on-disk
layout, but also for selecting allocation and cleaning algorithms.

The file system formatting tool, "mkfs.f2fs", is available from the following
git tree:
The following git tree provides the file system formatting tool (mkfs.f2fs),
a consistency checking tool (fsck.f2fs), and a debugging tool (dump.f2fs).
>> git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git

For reporting bugs and sending patches, please use the following mailing list:
Expand Down Expand Up @@ -132,6 +132,38 @@ f2fs. Each file shows the whole f2fs information.
- average SIT information about whole segments
- current memory footprint consumed by f2fs.

================================================================================
SYSFS ENTRIES
================================================================================

Information about mounted f2f2 file systems can be found in
/sys/fs/f2fs. Each mounted filesystem will have a directory in
/sys/fs/f2fs based on its device name (i.e., /sys/fs/f2fs/sda).
The files in each per-device directory are shown in table below.

Files in /sys/fs/f2fs/<devname>
(see also Documentation/ABI/testing/sysfs-fs-f2fs)
..............................................................................
File Content

gc_max_sleep_time This tuning parameter controls the maximum sleep
time for the garbage collection thread. Time is
in milliseconds.

gc_min_sleep_time This tuning parameter controls the minimum sleep
time for the garbage collection thread. Time is
in milliseconds.

gc_no_gc_sleep_time This tuning parameter controls the default sleep
time for the garbage collection thread. Time is
in milliseconds.

gc_idle This parameter controls the selection of victim
policy for garbage collection. Setting gc_idle = 0
(default) will disable this option. Setting
gc_idle = 1 will select the Cost Benefit approach
& setting gc_idle = 2 will select the greedy aproach.

================================================================================
USAGE
================================================================================
Expand All @@ -149,8 +181,12 @@ USAGE
# mkfs.f2fs -l label /dev/block_device
# mount -t f2fs /dev/block_device /mnt/f2fs

Format options
--------------
mkfs.f2fs
---------
The mkfs.f2fs is for the use of formatting a partition as the f2fs filesystem,
which builds a basic on-disk layout.

The options consist of:
-l [label] : Give a volume label, up to 512 unicode name.
-a [0 or 1] : Split start location of each area for heap-based allocation.
1 is set by default, which performs this.
Expand All @@ -164,6 +200,37 @@ Format options
-t [0 or 1] : Disable discard command or not.
1 is set by default, which conducts discard.

fsck.f2fs
---------
The fsck.f2fs is a tool to check the consistency of an f2fs-formatted
partition, which examines whether the filesystem metadata and user-made data
are cross-referenced correctly or not.
Note that, initial version of the tool does not fix any inconsistency.

The options consist of:
-d debug level [default:0]

dump.f2fs
---------
The dump.f2fs shows the information of specific inode and dumps SSA and SIT to
file. Each file is dump_ssa and dump_sit.

The dump.f2fs is used to debug on-disk data structures of the f2fs filesystem.
It shows on-disk inode information reconized by a given inode number, and is
able to dump all the SSA and SIT entries into predefined files, ./dump_ssa and
./dump_sit respectively.

The options consist of:
-d debug level [default:0]
-i inode no (hex)
-s [SIT dump segno from #1~#2 (decimal), for all 0~-1]
-a [SSA dump segno from #1~#2 (decimal), for all 0~-1]

Examples:
# dump.f2fs -i [ino] /dev/sdx
# dump.f2fs -s 0~-1 /dev/sdx (SIT dump)
# dump.f2fs -a 0~-1 /dev/sdx (SSA dump)

================================================================================
DESIGN
================================================================================
Expand Down
24 changes: 15 additions & 9 deletions fs/f2fs/checkpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ const struct address_space_operations f2fs_meta_aops = {
.set_page_dirty = f2fs_set_meta_page_dirty,
};

int check_orphan_space(struct f2fs_sb_info *sbi)
int acquire_orphan_inode(struct f2fs_sb_info *sbi)
{
unsigned int max_orphans;
int err = 0;
Expand All @@ -197,10 +197,19 @@ int check_orphan_space(struct f2fs_sb_info *sbi)
mutex_lock(&sbi->orphan_inode_mutex);
if (sbi->n_orphans >= max_orphans)
err = -ENOSPC;
else
sbi->n_orphans++;
mutex_unlock(&sbi->orphan_inode_mutex);
return err;
}

void release_orphan_inode(struct f2fs_sb_info *sbi)
{
mutex_lock(&sbi->orphan_inode_mutex);
sbi->n_orphans--;
mutex_unlock(&sbi->orphan_inode_mutex);
}

void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
{
struct list_head *head, *this;
Expand Down Expand Up @@ -229,21 +238,18 @@ void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
list_add(&new->list, this->prev);
else
list_add_tail(&new->list, head);

sbi->n_orphans++;
out:
mutex_unlock(&sbi->orphan_inode_mutex);
}

void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
{
struct list_head *this, *next, *head;
struct list_head *head;
struct orphan_inode_entry *orphan;

mutex_lock(&sbi->orphan_inode_mutex);
head = &sbi->orphan_inode_list;
list_for_each_safe(this, next, head) {
orphan = list_entry(this, struct orphan_inode_entry, list);
list_for_each_entry(orphan, head, list) {
if (orphan->ino == ino) {
list_del(&orphan->list);
kmem_cache_free(orphan_entry_slab, orphan);
Expand Down Expand Up @@ -373,7 +379,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
if (!f2fs_crc_valid(crc, cp_block, crc_offset))
goto invalid_cp1;

pre_version = le64_to_cpu(cp_block->checkpoint_ver);
pre_version = cur_cp_version(cp_block);

/* Read the 2nd cp block in this CP pack */
cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1;
Expand All @@ -388,7 +394,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
if (!f2fs_crc_valid(crc, cp_block, crc_offset))
goto invalid_cp2;

cur_version = le64_to_cpu(cp_block->checkpoint_ver);
cur_version = cur_cp_version(cp_block);

if (cur_version == pre_version) {
*version = cur_version;
Expand Down Expand Up @@ -793,7 +799,7 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
* Increase the version number so that
* SIT entries and seg summaries are written at correct place
*/
ckpt_ver = le64_to_cpu(ckpt->checkpoint_ver);
ckpt_ver = cur_cp_version(ckpt);
ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver);

/* write cached NAT/SIT entries to NAT/SIT area */
Expand Down
28 changes: 16 additions & 12 deletions fs/f2fs/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ static void __set_data_blkaddr(struct dnode_of_data *dn, block_t new_addr)
struct page *node_page = dn->node_page;
unsigned int ofs_in_node = dn->ofs_in_node;

wait_on_page_writeback(node_page);
f2fs_wait_on_page_writeback(node_page, NODE, false);

rn = (struct f2fs_node *)page_address(node_page);
rn = F2FS_NODE(node_page);

/* Get physical address of data block */
addr_array = blkaddr_in_node(rn);
Expand Down Expand Up @@ -117,7 +117,8 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
block_t start_blkaddr, end_blkaddr;

BUG_ON(blk_addr == NEW_ADDR);
fofs = start_bidx_of_node(ofs_of_node(dn->node_page)) + dn->ofs_in_node;
fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) +
dn->ofs_in_node;

/* Update the page address in the parent node */
__set_data_blkaddr(dn, blk_addr);
Expand Down Expand Up @@ -176,7 +177,6 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
end_update:
write_unlock(&fi->ext.ext_lock);
sync_inode_page(dn);
return;
}

struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync)
Expand Down Expand Up @@ -260,8 +260,17 @@ struct page *get_lock_data_page(struct inode *inode, pgoff_t index)
if (PageUptodate(page))
return page;

BUG_ON(dn.data_blkaddr == NEW_ADDR);
BUG_ON(dn.data_blkaddr == NULL_ADDR);
/*
* A new dentry page is allocated but not able to be written, since its
* new inode page couldn't be allocated due to -ENOSPC.
* In such the case, its blkaddr can be remained as NEW_ADDR.
* see, f2fs_add_link -> get_new_data_page -> init_inode_metadata.
*/
if (dn.data_blkaddr == NEW_ADDR) {
zero_user_segment(page, 0, PAGE_CACHE_SIZE);
SetPageUptodate(page);
return page;
}

err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
if (err)
Expand Down Expand Up @@ -365,7 +374,6 @@ static void read_end_io(struct bio *bio, int err)
}
unlock_page(page);
} while (bvec >= bio->bi_io_vec);
kfree(bio->bi_private);
bio_put(bio);
}

Expand All @@ -391,7 +399,6 @@ int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page,
bio->bi_end_io = read_end_io;

if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
kfree(bio->bi_private);
bio_put(bio);
up_read(&sbi->bio_sem);
f2fs_put_page(page, 1);
Expand Down Expand Up @@ -442,7 +449,7 @@ static int get_data_block_ro(struct inode *inode, sector_t iblock,
unsigned int end_offset;

end_offset = IS_INODE(dn.node_page) ?
ADDRS_PER_INODE :
ADDRS_PER_INODE(F2FS_I(inode)) :
ADDRS_PER_BLOCK;

clear_buffer_new(bh_result);
Expand Down Expand Up @@ -636,9 +643,6 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
int err = 0;
int ilock;

/* for nobh_write_end */
*fsdata = NULL;

f2fs_balance_fs(sbi);
repeat:
page = grab_cache_page_write_begin(mapping, index, flags);
Expand Down
34 changes: 17 additions & 17 deletions fs/f2fs/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static DEFINE_MUTEX(f2fs_stat_mutex);

static void update_general_status(struct f2fs_sb_info *sbi)
{
struct f2fs_stat_info *si = sbi->stat_info;
struct f2fs_stat_info *si = F2FS_STAT(sbi);
int i;

/* valid check of the segment numbers */
Expand Down Expand Up @@ -83,7 +83,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
*/
static void update_sit_info(struct f2fs_sb_info *sbi)
{
struct f2fs_stat_info *si = sbi->stat_info;
struct f2fs_stat_info *si = F2FS_STAT(sbi);
unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
struct sit_info *sit_i = SIT_I(sbi);
unsigned int segno, vblocks;
Expand Down Expand Up @@ -118,7 +118,7 @@ static void update_sit_info(struct f2fs_sb_info *sbi)
*/
static void update_mem_info(struct f2fs_sb_info *sbi)
{
struct f2fs_stat_info *si = sbi->stat_info;
struct f2fs_stat_info *si = F2FS_STAT(sbi);
unsigned npages;

if (si->base_mem)
Expand Down Expand Up @@ -253,21 +253,21 @@ static int stat_show(struct seq_file *s, void *v)
si->nats, NM_WOUT_THRESHOLD);
seq_printf(s, " - SITs: %5d\n - free_nids: %5d\n",
si->sits, si->fnids);
seq_printf(s, "\nDistribution of User Blocks:");
seq_printf(s, " [ valid | invalid | free ]\n");
seq_printf(s, " [");
seq_puts(s, "\nDistribution of User Blocks:");
seq_puts(s, " [ valid | invalid | free ]\n");
seq_puts(s, " [");

for (j = 0; j < si->util_valid; j++)
seq_printf(s, "-");
seq_printf(s, "|");
seq_putc(s, '-');
seq_putc(s, '|');

for (j = 0; j < si->util_invalid; j++)
seq_printf(s, "-");
seq_printf(s, "|");
seq_putc(s, '-');
seq_putc(s, '|');

for (j = 0; j < si->util_free; j++)
seq_printf(s, "-");
seq_printf(s, "]\n\n");
seq_putc(s, '-');
seq_puts(s, "]\n\n");
seq_printf(s, "SSR: %u blocks in %u segments\n",
si->block_count[SSR], si->segment_count[SSR]);
seq_printf(s, "LFS: %u blocks in %u segments\n",
Expand Down Expand Up @@ -305,11 +305,10 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
struct f2fs_stat_info *si;

sbi->stat_info = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL);
if (!sbi->stat_info)
si = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL);
if (!si)
return -ENOMEM;

si = sbi->stat_info;
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 @@ -319,6 +318,7 @@ int f2fs_build_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;
sbi->stat_info = si;

mutex_lock(&f2fs_stat_mutex);
list_add_tail(&si->stat_list, &f2fs_stat_list);
Expand All @@ -329,13 +329,13 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)

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

mutex_lock(&f2fs_stat_mutex);
list_del(&si->stat_list);
mutex_unlock(&f2fs_stat_mutex);

kfree(sbi->stat_info);
kfree(si);
}

void __init f2fs_create_root_stats(void)
Expand Down
Loading

0 comments on commit eb97a78

Please sign in to comment.