mirror of
https://github.com/hardkernel/linux.git
synced 2026-04-10 15:08:06 +09:00
Pull f2fs updates from Jaegeuk Kim:
"In this round, we've followed up to support some generic features such
as cgroup, block reservation, linking fscrypt_ops, delivering
write_hints, and some ioctls. And, we could fix some corner cases in
terms of power-cut recovery and subtle deadlocks.
Enhancements:
- bitmap operations to handle NAT blocks
- readahead to improve readdir speed
- switch to use fscrypt_*
- apply write hints for direct IO
- add reserve_root=%u,resuid=%u,resgid=%u to reserve blocks for root/uid/gid
- modify b_avail and b_free to consider root reserved blocks
- support cgroup writeback
- support FIEMAP_FLAG_XATTR for fibmap
- add F2FS_IOC_PRECACHE_EXTENTS to pre-cache extents
- add F2FS_IOC_{GET/SET}_PIN_FILE to pin LBAs for data blocks
- support inode creation time
Bug fixs:
- sysfile-based quota operations
- memory footprint accounting
- allow to write data on partial preallocation case
- fix deadlock case on fallocate
- fix to handle fill_super errors
- fix missing inode updates of fsync'ed file
- recover renamed file which was fsycn'ed before
- drop inmemory pages in corner error case
- keep last_disk_size correctly
- recover missing i_inline flags during roll-forward
Various clean-up patches were added as well"
Cherry-pick from origin/upstream-f2fs-stable-linux-4.4.y:
5f9b3abb91 f2fs: support inode creation time
9fb0de1751 f2fs: rebuild sit page from sit info in mem
1062a0c018 f2fs: stop issuing discard if fs is readonly
fa043fae90 f2fs: clean up duplicated assignment in init_discard_policy
b007190234 f2fs: use GFP_F2FS_ZERO for cleanup
35b11839a1 f2fs: allow to recover node blocks given updated checkpoint
e56500860b f2fs: recover some i_inline flags
64aa9569a1 f2fs: correct removexattr behavior for null valued extended attribute
70b3a923da f2fs: drop page cache after fs shutdown
8069a0e983 f2fs: stop gc/discard thread after fs shutdown
bb924f7777 f2fs: hanlde error case in f2fs_ioc_shutdown
700b53f21e f2fs: split need_inplace_update
f31d52811c f2fs: fix to update last_disk_size correctly
eeb0118b83 f2fs: kill F2FS_INLINE_XATTR_ADDRS for cleanup
c1b74c9670 f2fs: clean up error path of fill_super
d5efd57e01 f2fs: avoid hungtask when GC encrypted block if io_bits is set
c4027d0843 f2fs: allow quota to use reserved blocks
18d267c273 f2fs: fix to drop all inmem pages correctly
4dca47531e f2fs: speed up defragment on sparse file
999f806a7c f2fs: support F2FS_IOC_PRECACHE_EXTENTS
84960fca96 f2fs: add an ioctl to disable GC for specific file
292c8e1cfd f2fs: prevent newly created inode from being dirtied incorrectly
58b1f5b0fc f2fs: support FIEMAP_FLAG_XATTR
6afa9a94d0 f2fs: fix to cover f2fs_inline_data_fiemap with inode_lock
10f4a4140b f2fs: check node page again in write end io
b203c58dfd f2fs: fix to caclulate required free section correctly
d49132d45c f2fs: handle newly created page when revoking inmem pages
2ce6b9d816 f2fs: add resgid and resuid to reserve root blocks
f53dcf6799 f2fs: implement cgroup writeback support
1338f376d5 f2fs: remove unused pend_list_tag
d4f19f6266 f2fs: avoid high cpu usage in discard thread
b78e9302e2 f2fs: make local functions static
62438ba87b f2fs: add reserved blocks for root user
06a366757f f2fs: check segment type in __f2fs_replace_block
4c6bc4be37 f2fs: update inode info to inode page for new file
591b336387 f2fs: show precise # of blocks that user/root can use
b242d7edc5 f2fs: clean up unneeded declaration
87b8168e9e f2fs: continue to do direct IO if we only preallocate partial blocks
2b4d859bd9 f2fs: enable quota at remount from r to w
54bf13a0ad f2fs: skip stop_checkpoint for user data writes
25ef3006ba f2fs: fix missing error number for xattr operation
cff2c7fe41 f2fs: recover directory operations by fsync
e2bb618a0a f2fs: return error during fill_super
8a2c11d865 f2fs: fix an error case of missing update inode page
cd38d5ada5 f2fs: fix potential hangtask in f2fs_trace_pid
e81cafbeba f2fs: no need return value in restore summary process
04d44000d6 f2fs: use unlikely for release case
925d0933d8 f2fs: don't return value in truncate_data_blocks_range
f7986c416d f2fs: clean up f2fs_map_blocks
e4f5e26cda f2fs: clean up hash codes
1f994d4708 f2fs: fix error handling in fill_super
e7db649b5f f2fs: spread f2fs_k{m,z}alloc
5d4e487b99 f2fs: inject fault to kvmalloc
8b33886c37 f2fs: inject fault to kzalloc
d946807987 f2fs: remove a redundant conditional expression
3bc01114a3 f2fs: apply write hints to select the type of segment for direct write
c80f019591 f2fs: switch to fscrypt_prepare_setattr()
bb8b850365 f2fs: switch to fscrypt_prepare_lookup()
9ab470eaf8 f2fs: switch to fscrypt_prepare_rename()
aeaac517a1 f2fs: switch to fscrypt_prepare_link()
101c6a96ad f2fs: switch to fscrypt_file_open()
6d025237a1 f2fs: remove repeated f2fs_bug_on
b01e03d724 f2fs: remove an excess variable
e1f9be2f7c f2fs: fix lock dependency in between dio_rwsem & i_mmap_sem
e5c7c86010 f2fs: remove unused parameter
f130dbb98a f2fs: still write data if preallocate only partial blocks
47ee9b2598 f2fs: introduce sysfs readdir_ra to readahead inode block in readdir
55e2f89181 f2fs: fix concurrent problem for updating free bitmap
e1398f6554 f2fs: remove unneeded memory footprint accounting
2d69561135 f2fs: no need to read nat block if nat_block_bitmap is set
4dd2d07338 f2fs: reserve nid resource for quota sysfile
Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
163 lines
3.5 KiB
C
163 lines
3.5 KiB
C
/*
|
|
* f2fs IO tracer
|
|
*
|
|
* Copyright (c) 2014 Motorola Mobility
|
|
* Copyright (c) 2014 Jaegeuk Kim <jaegeuk@kernel.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
#include <linux/fs.h>
|
|
#include <linux/f2fs_fs.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/radix-tree.h>
|
|
|
|
#include "f2fs.h"
|
|
#include "trace.h"
|
|
|
|
static RADIX_TREE(pids, GFP_ATOMIC);
|
|
static struct mutex pids_lock;
|
|
static struct last_io_info last_io;
|
|
|
|
static inline void __print_last_io(void)
|
|
{
|
|
if (!last_io.len)
|
|
return;
|
|
|
|
trace_printk("%3x:%3x %4x %-16s %2x %5x %5x %12x %4x\n",
|
|
last_io.major, last_io.minor,
|
|
last_io.pid, "----------------",
|
|
last_io.type,
|
|
last_io.fio.op, last_io.fio.op_flags,
|
|
last_io.fio.new_blkaddr,
|
|
last_io.len);
|
|
memset(&last_io, 0, sizeof(last_io));
|
|
}
|
|
|
|
static int __file_type(struct inode *inode, pid_t pid)
|
|
{
|
|
if (f2fs_is_atomic_file(inode))
|
|
return __ATOMIC_FILE;
|
|
else if (f2fs_is_volatile_file(inode))
|
|
return __VOLATILE_FILE;
|
|
else if (S_ISDIR(inode->i_mode))
|
|
return __DIR_FILE;
|
|
else if (inode->i_ino == F2FS_NODE_INO(F2FS_I_SB(inode)))
|
|
return __NODE_FILE;
|
|
else if (inode->i_ino == F2FS_META_INO(F2FS_I_SB(inode)))
|
|
return __META_FILE;
|
|
else if (pid)
|
|
return __NORMAL_FILE;
|
|
else
|
|
return __MISC_FILE;
|
|
}
|
|
|
|
void f2fs_trace_pid(struct page *page)
|
|
{
|
|
struct inode *inode = page->mapping->host;
|
|
pid_t pid = task_pid_nr(current);
|
|
void *p;
|
|
|
|
set_page_private(page, (unsigned long)pid);
|
|
|
|
if (radix_tree_preload(GFP_NOFS))
|
|
return;
|
|
|
|
mutex_lock(&pids_lock);
|
|
p = radix_tree_lookup(&pids, pid);
|
|
if (p == current)
|
|
goto out;
|
|
if (p)
|
|
radix_tree_delete(&pids, pid);
|
|
|
|
f2fs_radix_tree_insert(&pids, pid, current);
|
|
|
|
trace_printk("%3x:%3x %4x %-16s\n",
|
|
MAJOR(inode->i_sb->s_dev), MINOR(inode->i_sb->s_dev),
|
|
pid, current->comm);
|
|
out:
|
|
mutex_unlock(&pids_lock);
|
|
radix_tree_preload_end();
|
|
}
|
|
|
|
void f2fs_trace_ios(struct f2fs_io_info *fio, int flush)
|
|
{
|
|
struct inode *inode;
|
|
pid_t pid;
|
|
int major, minor;
|
|
|
|
if (flush) {
|
|
__print_last_io();
|
|
return;
|
|
}
|
|
|
|
inode = fio->page->mapping->host;
|
|
pid = page_private(fio->page);
|
|
|
|
major = MAJOR(inode->i_sb->s_dev);
|
|
minor = MINOR(inode->i_sb->s_dev);
|
|
|
|
if (last_io.major == major && last_io.minor == minor &&
|
|
last_io.pid == pid &&
|
|
last_io.type == __file_type(inode, pid) &&
|
|
last_io.fio.op == fio->op &&
|
|
last_io.fio.op_flags == fio->op_flags &&
|
|
last_io.fio.new_blkaddr + last_io.len ==
|
|
fio->new_blkaddr) {
|
|
last_io.len++;
|
|
return;
|
|
}
|
|
|
|
__print_last_io();
|
|
|
|
last_io.major = major;
|
|
last_io.minor = minor;
|
|
last_io.pid = pid;
|
|
last_io.type = __file_type(inode, pid);
|
|
last_io.fio = *fio;
|
|
last_io.len = 1;
|
|
return;
|
|
}
|
|
|
|
void f2fs_build_trace_ios(void)
|
|
{
|
|
mutex_init(&pids_lock);
|
|
}
|
|
|
|
#define PIDVEC_SIZE 128
|
|
static unsigned int gang_lookup_pids(pid_t *results, unsigned long first_index,
|
|
unsigned int max_items)
|
|
{
|
|
struct radix_tree_iter iter;
|
|
void **slot;
|
|
unsigned int ret = 0;
|
|
|
|
if (unlikely(!max_items))
|
|
return 0;
|
|
|
|
radix_tree_for_each_slot(slot, &pids, &iter, first_index) {
|
|
results[ret] = iter.index;
|
|
if (++ret == max_items)
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void f2fs_destroy_trace_ios(void)
|
|
{
|
|
pid_t pid[PIDVEC_SIZE];
|
|
pid_t next_pid = 0;
|
|
unsigned int found;
|
|
|
|
mutex_lock(&pids_lock);
|
|
while ((found = gang_lookup_pids(pid, next_pid, PIDVEC_SIZE))) {
|
|
unsigned idx;
|
|
|
|
next_pid = pid[found - 1] + 1;
|
|
for (idx = 0; idx < found; idx++)
|
|
radix_tree_delete(&pids, pid[idx]);
|
|
}
|
|
mutex_unlock(&pids_lock);
|
|
}
|