* [PATCH 1/6] f2fs: don't need to get f2fs_lock_op for the inline_data test
@ 2013-12-27 4:00 Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 2/6] f2fs: convert inline_data for punch_hole Jaegeuk Kim
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Jaegeuk Kim @ 2013-12-27 4:00 UTC (permalink / raw)
Cc: linux-fsdevel, linux-kernel, linux-f2fs-devel
This patch locates checking the inline_data prior to calling f2fs_lock_op()
in truncate_blocks(), since getting the lock is unnecessary.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/file.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index dd80e72..7ef2d6a 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -261,14 +261,14 @@ static int truncate_blocks(struct inode *inode, u64 from)
trace_f2fs_truncate_blocks_enter(inode, from);
+ if (f2fs_has_inline_data(inode))
+ goto done;
+
free_from = (pgoff_t)
((from + blocksize - 1) >> (sbi->log_blocksize));
f2fs_lock_op(sbi);
- if (f2fs_has_inline_data(inode))
- goto done;
-
set_new_dnode(&dn, inode, NULL, NULL, 0);
err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE);
if (err) {
@@ -295,9 +295,8 @@ static int truncate_blocks(struct inode *inode, u64 from)
f2fs_put_dnode(&dn);
free_next:
err = truncate_inode_blocks(inode, free_from);
-done:
f2fs_unlock_op(sbi);
-
+done:
/* lastly zero out the first data page */
truncate_partial_data_page(inode, from);
--
1.8.4.474.g128a96c
------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT
organizations don't have a clear picture of how application performance
affects their revenue. With AppDynamics, you get 100% visibility into your
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/6] f2fs: convert inline_data for punch_hole
2013-12-27 4:00 [PATCH 1/6] f2fs: don't need to get f2fs_lock_op for the inline_data test Jaegeuk Kim
@ 2013-12-27 4:00 ` Jaegeuk Kim
2013-12-31 6:08 ` [f2fs-dev] " Chao Yu
2013-12-27 4:00 ` [PATCH 3/6] f2fs: call f2fs_put_page at the error case Jaegeuk Kim
` (3 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Jaegeuk Kim @ 2013-12-27 4:00 UTC (permalink / raw)
Cc: linux-fsdevel, linux-kernel, linux-f2fs-devel
In the punch_hole(), let's convert inline_data all the time for simplicity and
to avoid potential deadlock conditions.
It is pretty much not a big deal to do this.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/file.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 7ef2d6a..f64a1c8 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -462,25 +462,9 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
loff_t off_start, off_end;
int ret = 0;
- if (f2fs_has_inline_data(inode)) {
- struct page *page;
- unsigned flags = AOP_FLAG_NOFS;
- page = grab_cache_page_write_begin(inode->i_mapping, 0, flags);
- if (IS_ERR(page))
- return PTR_ERR(page);
- if (offset + len > MAX_INLINE_DATA) {
- ret = f2fs_convert_inline_data(inode, page, flags);
- f2fs_put_page(page, 1);
- if (ret)
- return ret;
- } else {
- zero_user_segment(page, offset, offset + len);
- SetPageUptodate(page);
- set_page_dirty(page);
- f2fs_put_page(page, 1);
- return ret;
- }
- }
+ ret = f2fs_convert_inline_data(inode, NULL, AOP_FLAG_NOFS);
+ if (ret)
+ return ret;
pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
--
1.8.4.474.g128a96c
------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT
organizations don't have a clear picture of how application performance
affects their revenue. With AppDynamics, you get 100% visibility into your
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/6] f2fs: call f2fs_put_page at the error case
2013-12-27 4:00 [PATCH 1/6] f2fs: don't need to get f2fs_lock_op for the inline_data test Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 2/6] f2fs: convert inline_data for punch_hole Jaegeuk Kim
@ 2013-12-27 4:00 ` Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 4/6] f2fs: refactor f2fs_convert_inline_data Jaegeuk Kim
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Jaegeuk Kim @ 2013-12-27 4:00 UTC (permalink / raw)
Cc: linux-fsdevel, linux-kernel, linux-f2fs-devel
In f2fs_write_begin(), if f2fs_conver_inline_data() returns an error like
-ENOSPC, f2fs should call f2fs_put_page().
Otherwise, it is remained as a locked page, resulting in the following bug.
[<ffffffff8114657e>] sleep_on_page+0xe/0x20
[<ffffffff81146567>] __lock_page+0x67/0x70
[<ffffffff81157d08>] truncate_inode_pages_range+0x368/0x5d0
[<ffffffff81157ff5>] truncate_inode_pages+0x15/0x20
[<ffffffff8115804b>] truncate_pagecache+0x4b/0x70
[<ffffffff81158082>] truncate_setsize+0x12/0x20
[<ffffffffa02a1842>] f2fs_setattr+0x72/0x270 [f2fs]
[<ffffffff811cdae3>] notify_change+0x213/0x400
[<ffffffff811ab376>] do_truncate+0x66/0xa0
[<ffffffff811ab541>] vfs_truncate+0x191/0x1b0
[<ffffffff811ab5bc>] do_sys_truncate+0x5c/0xa0
[<ffffffff811ab78e>] SyS_truncate+0xe/0x10
[<ffffffff81756052>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/data.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index bf39eed..253e663 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -916,8 +916,10 @@ repeat:
goto inline_data;
} else if (f2fs_has_inline_data(inode)) {
err = f2fs_convert_inline_data(inode, page, flags);
- if (err)
+ if (err) {
+ f2fs_put_page(page, 1);
return err;
+ }
}
f2fs_lock_op(sbi);
--
1.8.4.474.g128a96c
------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT
organizations don't have a clear picture of how application performance
affects their revenue. With AppDynamics, you get 100% visibility into your
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/6] f2fs: refactor f2fs_convert_inline_data
2013-12-27 4:00 [PATCH 1/6] f2fs: don't need to get f2fs_lock_op for the inline_data test Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 2/6] f2fs: convert inline_data for punch_hole Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 3/6] f2fs: call f2fs_put_page at the error case Jaegeuk Kim
@ 2013-12-27 4:00 ` Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 5/6] f2fs: add the number of inline_data files to status info Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 6/6] f2fs: add inline_data recovery routine Jaegeuk Kim
4 siblings, 0 replies; 9+ messages in thread
From: Jaegeuk Kim @ 2013-12-27 4:00 UTC (permalink / raw)
Cc: linux-fsdevel, linux-kernel, linux-f2fs-devel
This patch refactors f2fs_convert_inline_data to check a couple of conditions
internally for deciding whether it needs to convert inline_data or not.
So, the new f2fs_convert_inline_data initially checks:
1) f2fs_has_inline_data(), and
2) the data size to be changed.
If the inode has inline_data but the size to fill is less than MAX_INLINE_DATA,
then we don't need to convert the inline_data with data allocation.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/data.c | 16 ++++++----------
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 25 +++++++++----------------
fs/f2fs/inline.c | 26 ++++++++++++--------------
4 files changed, 28 insertions(+), 41 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 253e663..fc7a28c 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -906,21 +906,17 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
f2fs_balance_fs(sbi);
repeat:
+ err = f2fs_convert_inline_data(inode, pos + len);
+ if (err)
+ return err;
+
page = grab_cache_page_write_begin(mapping, index, flags);
if (!page)
return -ENOMEM;
*pagep = page;
- if ((pos + len) < MAX_INLINE_DATA) {
- if (f2fs_has_inline_data(inode))
- goto inline_data;
- } else if (f2fs_has_inline_data(inode)) {
- err = f2fs_convert_inline_data(inode, page, flags);
- if (err) {
- f2fs_put_page(page, 1);
- return err;
- }
- }
+ if (f2fs_has_inline_data(inode) && (pos + len) <= MAX_INLINE_DATA)
+ goto inline_data;
f2fs_lock_op(sbi);
set_new_dnode(&dn, inode, NULL, NULL, 0);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index b01ccaa..af35039 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1302,6 +1302,6 @@ extern const struct inode_operations f2fs_special_inode_operations;
inline int f2fs_has_inline_data(struct inode *);
bool f2fs_may_inline(struct inode *);
int f2fs_read_inline_data(struct inode *, struct page *);
-int f2fs_convert_inline_data(struct inode *, struct page *, unsigned);
+int f2fs_convert_inline_data(struct inode *, pgoff_t);
int f2fs_write_inline_data(struct inode *, struct page *, unsigned int);
#endif
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index f64a1c8..68dd7bf 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -370,17 +370,12 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size != i_size_read(inode)) {
- if (f2fs_has_inline_data(inode) &&
- (attr->ia_size > MAX_INLINE_DATA)) {
- unsigned flags = AOP_FLAG_NOFS;
- err = f2fs_convert_inline_data(inode, NULL, flags);
- if (err)
- return err;
- }
+ err = f2fs_convert_inline_data(inode, attr->ia_size);
+ if (err)
+ return err;
truncate_setsize(inode, attr->ia_size);
- if (!f2fs_has_inline_data(inode))
- f2fs_truncate(inode);
+ f2fs_truncate(inode);
f2fs_balance_fs(F2FS_SB(inode->i_sb));
}
@@ -462,7 +457,7 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
loff_t off_start, off_end;
int ret = 0;
- ret = f2fs_convert_inline_data(inode, NULL, AOP_FLAG_NOFS);
+ ret = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1);
if (ret)
return ret;
@@ -512,16 +507,14 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
loff_t off_start, off_end;
int ret = 0;
- if (f2fs_has_inline_data(inode) && (offset + len > MAX_INLINE_DATA)) {
- ret = f2fs_convert_inline_data(inode, NULL, AOP_FLAG_NOFS);
- if (ret)
- return ret;
- }
-
ret = inode_newsize_ok(inode, (len + offset));
if (ret)
return ret;
+ ret = f2fs_convert_inline_data(inode, offset + len);
+ if (ret)
+ return ret;
+
pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 62c72aa..1843bc7 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -101,6 +101,7 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page)
dst_addr = kmap(page);
memcpy(dst_addr, src_addr, MAX_INLINE_DATA);
kunmap(page);
+ SetPageUptodate(page);
/* write data page to try to make data consistent */
set_page_writeback(page);
@@ -120,25 +121,22 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page)
return err;
}
-int f2fs_convert_inline_data(struct inode *inode,
- struct page *p, unsigned flags)
+int f2fs_convert_inline_data(struct inode *inode, pgoff_t to_size)
{
- int err;
struct page *page;
+ int err;
- if (!p || p->index) {
- page = grab_cache_page_write_begin(inode->i_mapping, 0, flags);
- if (IS_ERR(page))
- return PTR_ERR(page);
- } else {
- page = p;
- }
-
- err = __f2fs_convert_inline_data(inode, page);
+ if (!f2fs_has_inline_data(inode))
+ return 0;
+ else if (to_size <= MAX_INLINE_DATA)
+ return 0;
- if (!p || p->index)
- f2fs_put_page(page, 1);
+ page = grab_cache_page_write_begin(inode->i_mapping, 0, AOP_FLAG_NOFS);
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+ err = __f2fs_convert_inline_data(inode, page);
+ f2fs_put_page(page, 1);
return err;
}
--
1.8.4.474.g128a96c
------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT
organizations don't have a clear picture of how application performance
affects their revenue. With AppDynamics, you get 100% visibility into your
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/6] f2fs: add the number of inline_data files to status info
2013-12-27 4:00 [PATCH 1/6] f2fs: don't need to get f2fs_lock_op for the inline_data test Jaegeuk Kim
` (2 preceding siblings ...)
2013-12-27 4:00 ` [PATCH 4/6] f2fs: refactor f2fs_convert_inline_data Jaegeuk Kim
@ 2013-12-27 4:00 ` Jaegeuk Kim
2013-12-27 6:15 ` Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 6/6] f2fs: add inline_data recovery routine Jaegeuk Kim
4 siblings, 1 reply; 9+ messages in thread
From: Jaegeuk Kim @ 2013-12-27 4:00 UTC (permalink / raw)
Cc: linux-fsdevel, linux-kernel, linux-f2fs-devel
This patch adds the number of inline_data files into the status information.
Note that the number is reset whenever the filesystem is newly mounted.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/debug.c | 3 +++
fs/f2fs/f2fs.h | 16 +++++++++++++++-
fs/f2fs/inline.c | 2 ++
fs/f2fs/inode.c | 1 +
4 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 61adbcb..711a0d4 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -45,6 +45,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
si->valid_count = valid_user_blocks(sbi);
si->valid_node_count = valid_node_count(sbi);
si->valid_inode_count = valid_inode_count(sbi);
+ si->inline_inode = sbi->inline_inode;
si->utilization = utilization(sbi);
si->free_segs = free_segments(sbi);
@@ -200,6 +201,8 @@ static int stat_show(struct seq_file *s, void *v)
seq_printf(s, "Other: %u)\n - Data: %u\n",
si->valid_node_count - si->valid_inode_count,
si->valid_count - si->valid_node_count);
+ seq_printf(s, " - Inline_data Inode: %u\n",
+ si->inline_inode);
seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
si->main_area_segs, si->main_area_sections,
si->main_area_zones);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index af35039..ef4073f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -460,6 +460,7 @@ struct f2fs_sb_info {
unsigned int segment_count[2]; /* # of allocated segments */
unsigned int block_count[2]; /* # of allocated blocks */
int total_hit_ext, read_hit_ext; /* extent cache hit ratio */
+ int inline_inode; /* # of inline_data inodes */
int bg_gc; /* background gc calls */
unsigned int n_dirty_dirs; /* # of dir inodes */
#endif
@@ -1201,7 +1202,7 @@ struct f2fs_stat_info {
int ndirty_node, ndirty_dent, ndirty_dirs, ndirty_meta;
int nats, sits, fnids;
int total_count, utilization;
- int bg_gc;
+ int bg_gc, inline_inode;
unsigned int valid_count, valid_node_count, valid_inode_count;
unsigned int bimodal, avg_vblocks;
int util_free, util_valid, util_invalid;
@@ -1230,6 +1231,17 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
#define stat_dec_dirty_dir(sbi) ((sbi)->n_dirty_dirs--)
#define stat_inc_total_hit(sb) ((F2FS_SB(sb))->total_hit_ext++)
#define stat_inc_read_hit(sb) ((F2FS_SB(sb))->read_hit_ext++)
+#define stat_inc_inline_inode(inode) \
+ do { \
+ if (f2fs_has_inline_data(inode)) \
+ ((F2FS_SB(inode->i_sb))->inline_inode++); \
+ } while (0)
+#define stat_dec_inline_inode(inode) \
+ do { \
+ if (f2fs_has_inline_data(inode)) \
+ ((F2FS_SB(inode->i_sb))->inline_inode--); \
+ } while (0)
+
#define stat_inc_seg_type(sbi, curseg) \
((sbi)->segment_count[(curseg)->alloc_type]++)
#define stat_inc_block_count(sbi, curseg) \
@@ -1273,6 +1285,8 @@ void f2fs_destroy_root_stats(void);
#define stat_dec_dirty_dir(sbi)
#define stat_inc_total_hit(sb)
#define stat_inc_read_hit(sb)
+#define stat_inc_inline_inode(inode)
+#define stat_dec_inline_inode(inode)
#define stat_inc_seg_type(sbi, curseg)
#define stat_inc_block_count(sbi, curseg)
#define stat_inc_seg_count(si, type)
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 1843bc7..048f601 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -113,6 +113,7 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page)
zero_user_segment(ipage, INLINE_DATA_OFFSET,
INLINE_DATA_OFFSET + MAX_INLINE_DATA);
clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
+ stat_dec_inline_inode(inode);
sync_inode_page(&dn);
f2fs_put_page(ipage, 1);
@@ -165,6 +166,7 @@ int f2fs_write_inline_data(struct inode *inode,
if (!f2fs_has_inline_data(inode)) {
truncate_data_blocks_range(&dn, 1);
set_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
+ stat_inc_inline_inode(inode);
}
sync_inode_page(&dn);
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index a91f451..915f9a8 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -277,6 +277,7 @@ void f2fs_evict_inode(struct inode *inode)
f2fs_lock_op(sbi);
remove_inode_page(inode);
+ stat_dec_inline_inode(inode);
f2fs_unlock_op(sbi);
sb_end_intwrite(inode->i_sb);
--
1.8.4.474.g128a96c
------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT
organizations don't have a clear picture of how application performance
affects their revenue. With AppDynamics, you get 100% visibility into your
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/6] f2fs: add inline_data recovery routine
2013-12-27 4:00 [PATCH 1/6] f2fs: don't need to get f2fs_lock_op for the inline_data test Jaegeuk Kim
` (3 preceding siblings ...)
2013-12-27 4:00 ` [PATCH 5/6] f2fs: add the number of inline_data files to status info Jaegeuk Kim
@ 2013-12-27 4:00 ` Jaegeuk Kim
4 siblings, 0 replies; 9+ messages in thread
From: Jaegeuk Kim @ 2013-12-27 4:00 UTC (permalink / raw)
Cc: linux-fsdevel, linux-kernel, linux-f2fs-devel
This patch adds a inline_data recovery routine with the following policy.
[prev.] [next] of inline_data flag
o o -> recover inline_data
o x -> remove inline_data, and then recover data blocks
x o -> remove inline_data, and then recover inline_data
x x -> recover data blocks
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/f2fs.h | 2 ++
fs/f2fs/file.c | 2 +-
fs/f2fs/inline.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
fs/f2fs/recovery.c | 8 ++++++--
include/linux/f2fs_fs.h | 3 +--
5 files changed, 58 insertions(+), 5 deletions(-)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ef4073f..6991a28 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1010,6 +1010,7 @@ static inline int f2fs_readonly(struct super_block *sb)
*/
int f2fs_sync_file(struct file *, loff_t, loff_t, int);
void truncate_data_blocks(struct dnode_of_data *);
+int truncate_blocks(struct inode *, u64);
void f2fs_truncate(struct inode *);
int f2fs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
int f2fs_setattr(struct dentry *, struct iattr *);
@@ -1318,4 +1319,5 @@ bool f2fs_may_inline(struct inode *);
int f2fs_read_inline_data(struct inode *, struct page *);
int f2fs_convert_inline_data(struct inode *, pgoff_t);
int f2fs_write_inline_data(struct inode *, struct page *, unsigned int);
+int recover_inline_data(struct inode *, struct page *);
#endif
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 68dd7bf..c77ad4d 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -251,7 +251,7 @@ static void truncate_partial_data_page(struct inode *inode, u64 from)
f2fs_put_page(page, 1);
}
-static int truncate_blocks(struct inode *inode, u64 from)
+int truncate_blocks(struct inode *inode, u64 from)
{
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
unsigned int blocksize = inode->i_sb->s_blocksize;
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 048f601..0e940ce 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -174,3 +174,51 @@ int f2fs_write_inline_data(struct inode *inode,
return 0;
}
+
+int recover_inline_data(struct inode *inode, struct page *npage)
+{
+ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+ struct f2fs_inode *ri = NULL;
+ void *src_addr, *dst_addr;
+ struct page *ipage;
+
+ /*
+ * The inline_data recovery policy is as follows.
+ * [prev.] [next] of inline_data flag
+ * o o -> recover inline_data
+ * o x -> remove inline_data, and then recover data blocks
+ * x o -> remove inline_data, and then recover inline_data
+ * x x -> recover data blocks
+ */
+ if (IS_INODE(npage))
+ ri = F2FS_INODE(npage);
+
+ if (f2fs_has_inline_data(inode) &&
+ ri && ri->i_inline & F2FS_INLINE_DATA) {
+process_inline:
+ ipage = get_node_page(sbi, inode->i_ino);
+ f2fs_bug_on(IS_ERR(ipage));
+
+ src_addr = inline_data_addr(npage);
+ dst_addr = inline_data_addr(ipage);
+ memcpy(dst_addr, src_addr, MAX_INLINE_DATA);
+ update_inode(inode, ipage);
+ f2fs_put_page(ipage, 1);
+ return -1;
+ }
+
+ if (f2fs_has_inline_data(inode)) {
+ ipage = get_node_page(sbi, inode->i_ino);
+ f2fs_bug_on(IS_ERR(ipage));
+ zero_user_segment(ipage, INLINE_DATA_OFFSET,
+ INLINE_DATA_OFFSET + MAX_INLINE_DATA);
+ clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
+ update_inode(inode, ipage);
+ f2fs_put_page(ipage, 1);
+ } else if (ri && ri->i_inline & F2FS_INLINE_DATA) {
+ truncate_blocks(inode, 0);
+ set_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
+ goto process_inline;
+ }
+ return 0;
+}
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 96e690b6..655791e 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -298,6 +298,9 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
struct node_info ni;
int err = 0, recovered = 0;
+ if (recover_inline_data(inode, page))
+ goto out;
+
start = start_bidx_of_node(ofs_of_node(page), fi);
if (IS_INODE(page))
end = start + ADDRS_PER_INODE(fi);
@@ -305,12 +308,13 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
end = start + ADDRS_PER_BLOCK;
f2fs_lock_op(sbi);
+
set_new_dnode(&dn, inode, NULL, NULL, 0);
err = get_dnode_of_data(&dn, start, ALLOC_NODE);
if (err) {
f2fs_unlock_op(sbi);
- return err;
+ goto out;
}
wait_on_page_writeback(dn.node_page);
@@ -361,7 +365,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
err:
f2fs_put_dnode(&dn);
f2fs_unlock_op(sbi);
-
+out:
f2fs_msg(sbi->sb, KERN_NOTICE, "recover_data: ino = %lx, "
"recovered_data = %d blocks, err = %d",
inode->i_ino, recovered, err);
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index aea5eed..da74d87 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -155,12 +155,11 @@ struct f2fs_extent {
#define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */
#define F2FS_INLINE_DATA 0x02 /* file inline data flag */
-
#define MAX_INLINE_DATA (sizeof(__le32) * (DEF_ADDRS_PER_INODE - \
F2FS_INLINE_XATTR_ADDRS - 1))
#define INLINE_DATA_OFFSET (PAGE_CACHE_SIZE - sizeof(struct node_footer) \
- - sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - 1))
+ - sizeof(__le32) * (DEF_ADDRS_PER_INODE + 5 - 1))
struct f2fs_inode {
__le16 i_mode; /* file mode */
--
1.8.4.474.g128a96c
------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT
organizations don't have a clear picture of how application performance
affects their revenue. With AppDynamics, you get 100% visibility into your
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 5/6] f2fs: add the number of inline_data files to status info
2013-12-27 4:00 ` [PATCH 5/6] f2fs: add the number of inline_data files to status info Jaegeuk Kim
@ 2013-12-27 6:15 ` Jaegeuk Kim
0 siblings, 0 replies; 9+ messages in thread
From: Jaegeuk Kim @ 2013-12-27 6:15 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-kernel, linux-f2fs-devel
Change log from v1:
o fix kbuild failure
>From a9ebdcffd30b9642b2973ea8e9688e7b0d4bf7e3 Mon Sep 17 00:00:00 2001
From: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Date: Tue, 26 Nov 2013 11:08:57 +0900
Subject: [PATCH] f2fs: add the number of inline_data files to status
info
This patch adds the number of inline_data files into the status
information.
Note that the number is reset whenever the filesystem is newly mounted.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/debug.c | 3 +++
fs/f2fs/f2fs.h | 22 ++++++++++++++++++++--
fs/f2fs/inline.c | 7 ++-----
fs/f2fs/inode.c | 1 +
4 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 61adbcb..711a0d4 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -45,6 +45,7 @@ static void update_general_status(struct f2fs_sb_info
*sbi)
si->valid_count = valid_user_blocks(sbi);
si->valid_node_count = valid_node_count(sbi);
si->valid_inode_count = valid_inode_count(sbi);
+ si->inline_inode = sbi->inline_inode;
si->utilization = utilization(sbi);
si->free_segs = free_segments(sbi);
@@ -200,6 +201,8 @@ static int stat_show(struct seq_file *s, void *v)
seq_printf(s, "Other: %u)\n - Data: %u\n",
si->valid_node_count - si->valid_inode_count,
si->valid_count - si->valid_node_count);
+ seq_printf(s, " - Inline_data Inode: %u\n",
+ si->inline_inode);
seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
si->main_area_segs, si->main_area_sections,
si->main_area_zones);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index af35039..0b6bada 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -460,6 +460,7 @@ struct f2fs_sb_info {
unsigned int segment_count[2]; /* # of allocated segments */
unsigned int block_count[2]; /* # of allocated blocks */
int total_hit_ext, read_hit_ext; /* extent cache hit ratio */
+ int inline_inode; /* # of inline_data inodes */
int bg_gc; /* background gc calls */
unsigned int n_dirty_dirs; /* # of dir inodes */
#endif
@@ -992,6 +993,11 @@ static inline int inline_xattr_size(struct inode
*inode)
return 0;
}
+static inline int f2fs_has_inline_data(struct inode *inode)
+{
+ return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DATA);
+}
+
static inline void *inline_data_addr(struct page *page)
{
struct f2fs_inode *ri;
@@ -1201,7 +1207,7 @@ struct f2fs_stat_info {
int ndirty_node, ndirty_dent, ndirty_dirs, ndirty_meta;
int nats, sits, fnids;
int total_count, utilization;
- int bg_gc;
+ int bg_gc, inline_inode;
unsigned int valid_count, valid_node_count, valid_inode_count;
unsigned int bimodal, avg_vblocks;
int util_free, util_valid, util_invalid;
@@ -1230,6 +1236,17 @@ static inline struct f2fs_stat_info
*F2FS_STAT(struct f2fs_sb_info *sbi)
#define stat_dec_dirty_dir(sbi) ((sbi)->n_dirty_dirs--)
#define stat_inc_total_hit(sb) ((F2FS_SB(sb))->total_hit_ext++)
#define stat_inc_read_hit(sb) ((F2FS_SB(sb))->read_hit_ext++)
+#define stat_inc_inline_inode(inode) \
+ do { \
+ if (f2fs_has_inline_data(inode)) \
+ ((F2FS_SB(inode->i_sb))->inline_inode++); \
+ } while (0)
+#define stat_dec_inline_inode(inode) \
+ do { \
+ if (f2fs_has_inline_data(inode)) \
+ ((F2FS_SB(inode->i_sb))->inline_inode--); \
+ } while (0)
+
#define stat_inc_seg_type(sbi, curseg) \
((sbi)->segment_count[(curseg)->alloc_type]++)
#define stat_inc_block_count(sbi, curseg) \
@@ -1273,6 +1290,8 @@ void f2fs_destroy_root_stats(void);
#define stat_dec_dirty_dir(sbi)
#define stat_inc_total_hit(sb)
#define stat_inc_read_hit(sb)
+#define stat_inc_inline_inode(inode)
+#define stat_dec_inline_inode(inode)
#define stat_inc_seg_type(sbi, curseg)
#define stat_inc_block_count(sbi, curseg)
#define stat_inc_seg_count(si, type)
@@ -1299,7 +1318,6 @@ extern const struct inode_operations
f2fs_special_inode_operations;
/*
* inline.c
*/
-inline int f2fs_has_inline_data(struct inode *);
bool f2fs_may_inline(struct inode *);
int f2fs_read_inline_data(struct inode *, struct page *);
int f2fs_convert_inline_data(struct inode *, pgoff_t);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 1843bc7..5b259df 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -13,11 +13,6 @@
#include "f2fs.h"
-inline int f2fs_has_inline_data(struct inode *inode)
-{
- return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DATA);
-}
-
bool f2fs_may_inline(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
@@ -113,6 +108,7 @@ static int __f2fs_convert_inline_data(struct inode
*inode, struct page *page)
zero_user_segment(ipage, INLINE_DATA_OFFSET,
INLINE_DATA_OFFSET + MAX_INLINE_DATA);
clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
+ stat_dec_inline_inode(inode);
sync_inode_page(&dn);
f2fs_put_page(ipage, 1);
@@ -165,6 +161,7 @@ int f2fs_write_inline_data(struct inode *inode,
if (!f2fs_has_inline_data(inode)) {
truncate_data_blocks_range(&dn, 1);
set_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
+ stat_inc_inline_inode(inode);
}
sync_inode_page(&dn);
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index a91f451..915f9a8 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -277,6 +277,7 @@ void f2fs_evict_inode(struct inode *inode)
f2fs_lock_op(sbi);
remove_inode_page(inode);
+ stat_dec_inline_inode(inode);
f2fs_unlock_op(sbi);
sb_end_intwrite(inode->i_sb);
--
1.8.4.474.g128a96c
--
Jaegeuk Kim
Samsung
^ permalink raw reply related [flat|nested] 9+ messages in thread
* RE: [f2fs-dev] [PATCH 2/6] f2fs: convert inline_data for punch_hole
2013-12-27 4:00 ` [PATCH 2/6] f2fs: convert inline_data for punch_hole Jaegeuk Kim
@ 2013-12-31 6:08 ` Chao Yu
2014-01-06 7:41 ` Jaegeuk Kim
0 siblings, 1 reply; 9+ messages in thread
From: Chao Yu @ 2013-12-31 6:08 UTC (permalink / raw)
To: 'Jaegeuk Kim'; +Cc: linux-fsdevel, linux-kernel, linux-f2fs-devel
Hi,
One comment as following.
> -----Original Message-----
> From: Jaegeuk Kim [mailto:jaegeuk.kim@samsung.com]
> Sent: Friday, December 27, 2013 12:00 PM
> Cc: linux-fsdevel@vger.kernel.org; linux-kernel@vger.kernel.org; linux-f2fs-devel@lists.sourceforge.net
> Subject: [f2fs-dev] [PATCH 2/6] f2fs: convert inline_data for punch_hole
>
> In the punch_hole(), let's convert inline_data all the time for simplicity and
> to avoid potential deadlock conditions.
> It is pretty much not a big deal to do this.
>
> Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Reviewed-by: Chao Yu <chao2.yu@samsung.com>
> ---
> fs/f2fs/file.c | 22 +++-------------------
> 1 file changed, 3 insertions(+), 19 deletions(-)
>
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 7ef2d6a..f64a1c8 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -462,25 +462,9 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
> loff_t off_start, off_end;
> int ret = 0;
>
> - if (f2fs_has_inline_data(inode)) {
> - struct page *page;
> - unsigned flags = AOP_FLAG_NOFS;
> - page = grab_cache_page_write_begin(inode->i_mapping, 0, flags);
> - if (IS_ERR(page))
> - return PTR_ERR(page);
We use following code because grab_cache_page_write_begin only use
NULL value as its error number.
if (!page)
return -ENOMEM;
> - if (offset + len > MAX_INLINE_DATA) {
> - ret = f2fs_convert_inline_data(inode, page, flags);
> - f2fs_put_page(page, 1);
> - if (ret)
> - return ret;
> - } else {
> - zero_user_segment(page, offset, offset + len);
> - SetPageUptodate(page);
> - set_page_dirty(page);
> - f2fs_put_page(page, 1);
> - return ret;
> - }
> - }
> + ret = f2fs_convert_inline_data(inode, NULL, AOP_FLAG_NOFS);
> + if (ret)
> + return ret;
>
> pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
> pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
> --
> 1.8.4.474.g128a96c
>
>
> ------------------------------------------------------------------------------
> Rapidly troubleshoot problems before they affect your business. Most IT
> organizations don't have a clear picture of how application performance
> affects their revenue. With AppDynamics, you get 100% visibility into your
> Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
> http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [f2fs-dev] [PATCH 2/6] f2fs: convert inline_data for punch_hole
2013-12-31 6:08 ` [f2fs-dev] " Chao Yu
@ 2014-01-06 7:41 ` Jaegeuk Kim
0 siblings, 0 replies; 9+ messages in thread
From: Jaegeuk Kim @ 2014-01-06 7:41 UTC (permalink / raw)
To: Chao Yu; +Cc: linux-fsdevel, linux-kernel, linux-f2fs-devel
Hi,
2013-12-31 (화), 14:08 +0800, Chao Yu:
> Hi,
>
> One comment as following.
>
> > -----Original Message-----
> > From: Jaegeuk Kim [mailto:jaegeuk.kim@samsung.com]
> > Sent: Friday, December 27, 2013 12:00 PM
> > Cc: linux-fsdevel@vger.kernel.org; linux-kernel@vger.kernel.org; linux-f2fs-devel@lists.sourceforge.net
> > Subject: [f2fs-dev] [PATCH 2/6] f2fs: convert inline_data for punch_hole
> >
> > In the punch_hole(), let's convert inline_data all the time for simplicity and
> > to avoid potential deadlock conditions.
> > It is pretty much not a big deal to do this.
> >
> > Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
>
> Reviewed-by: Chao Yu <chao2.yu@samsung.com>
>
> > ---
> > fs/f2fs/file.c | 22 +++-------------------
> > 1 file changed, 3 insertions(+), 19 deletions(-)
> >
> > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> > index 7ef2d6a..f64a1c8 100644
> > --- a/fs/f2fs/file.c
> > +++ b/fs/f2fs/file.c
> > @@ -462,25 +462,9 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
> > loff_t off_start, off_end;
> > int ret = 0;
> >
> > - if (f2fs_has_inline_data(inode)) {
> > - struct page *page;
> > - unsigned flags = AOP_FLAG_NOFS;
> > - page = grab_cache_page_write_begin(inode->i_mapping, 0, flags);
> > - if (IS_ERR(page))
> > - return PTR_ERR(page);
>
> We use following code because grab_cache_page_write_begin only use
> NULL value as its error number.
Right. :)
Applied to the following patch:
f2fs: refactor f2fs_convert_inline_data.
Thanks,
--
Jaegeuk Kim
Samsung
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-01-06 7:41 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-27 4:00 [PATCH 1/6] f2fs: don't need to get f2fs_lock_op for the inline_data test Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 2/6] f2fs: convert inline_data for punch_hole Jaegeuk Kim
2013-12-31 6:08 ` [f2fs-dev] " Chao Yu
2014-01-06 7:41 ` Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 3/6] f2fs: call f2fs_put_page at the error case Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 4/6] f2fs: refactor f2fs_convert_inline_data Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 5/6] f2fs: add the number of inline_data files to status info Jaegeuk Kim
2013-12-27 6:15 ` Jaegeuk Kim
2013-12-27 4:00 ` [PATCH 6/6] f2fs: add inline_data recovery routine Jaegeuk Kim
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).