Re: [f2fs-dev] [PATCH 1/2] f2fs: introduce F2FS_INODE macro to get f2fs_inode

2013-12-26 Thread Chao Yu
Hi,

 -Original Message-
 From: Jaegeuk Kim [mailto:jaegeuk@samsung.com]
 Sent: Thursday, December 26, 2013 4:17 PM
 Cc: linux-fsde...@vger.kernel.org; linux-ker...@vger.kernel.org; 
 linux-f2fs-devel@lists.sourceforge.net
 Subject: [f2fs-dev] [PATCH 1/2] f2fs: introduce F2FS_INODE macro to get 
 f2fs_inode
 
 This patch introduces F2FS_INODE that returns struct f2fs_inode * from the 
 inode
 page.
 By using this macro, we can remove unnecessary casting codes like below.
 
struct f2fs_inode *ri = F2FS_NODE(inode_page)-i;
 - struct f2fs_inode *ri = F2FS_INODE(inode_page);

Looks Nice!

Could we apply this to recover_inode_page?
It seems that we just use inode data only.

 
 Signed-off-by: Jaegeuk Kim jaegeuk@samsung.com

Reviewed-by: Chao Yu chao2...@samsung.com

 ---
  fs/f2fs/dir.c  |  8 
  fs/f2fs/f2fs.h |  5 +
  fs/f2fs/inode.c|  8 ++--
  fs/f2fs/node.c | 14 +++---
  fs/f2fs/recovery.c |  6 ++
  5 files changed, 20 insertions(+), 21 deletions(-)
 
 diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
 index f0b4630..6da77e5 100644
 --- a/fs/f2fs/dir.c
 +++ b/fs/f2fs/dir.c
 @@ -261,12 +261,12 @@ void f2fs_set_link(struct inode *dir, struct 
 f2fs_dir_entry *de,
 
  static void init_dent_inode(const struct qstr *name, struct page *ipage)
  {
 - struct f2fs_node *rn;
 + struct f2fs_inode *ri;
 
   /* copy name info. to this inode page */
 - rn = F2FS_NODE(ipage);
 - rn-i.i_namelen = cpu_to_le32(name-len);
 - memcpy(rn-i.i_name, name-name, name-len);
 + ri = F2FS_INODE(ipage);
 + ri-i_namelen = cpu_to_le32(name-len);
 + memcpy(ri-i_name, name-name, name-len);
   set_page_dirty(ipage);
  }
 
 diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
 index ba91186..1a06f0a 100644
 --- a/fs/f2fs/f2fs.h
 +++ b/fs/f2fs/f2fs.h
 @@ -498,6 +498,11 @@ static inline struct f2fs_node *F2FS_NODE(struct page 
 *page)
   return (struct f2fs_node *)page_address(page);
  }
 
 +static inline struct f2fs_inode *F2FS_INODE(struct page *page)
 +{
 + return ((struct f2fs_node *)page_address(page))-i;
 +}
 +
  static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
  {
   return (struct f2fs_nm_info *)(sbi-nm_info);
 diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
 index d0eaa9f..a91f451 100644
 --- a/fs/f2fs/inode.c
 +++ b/fs/f2fs/inode.c
 @@ -67,7 +67,6 @@ static int do_read_inode(struct inode *inode)
   struct f2fs_sb_info *sbi = F2FS_SB(inode-i_sb);
   struct f2fs_inode_info *fi = F2FS_I(inode);
   struct page *node_page;
 - struct f2fs_node *rn;
   struct f2fs_inode *ri;
 
   /* Check if ino is within scope */
 @@ -81,8 +80,7 @@ static int do_read_inode(struct inode *inode)
   if (IS_ERR(node_page))
   return PTR_ERR(node_page);
 
 - rn = F2FS_NODE(node_page);
 - ri = (rn-i);
 + ri = F2FS_INODE(node_page);
 
   inode-i_mode = le16_to_cpu(ri-i_mode);
   i_uid_write(inode, le32_to_cpu(ri-i_uid));
 @@ -175,13 +173,11 @@ bad_inode:
 
  void update_inode(struct inode *inode, struct page *node_page)
  {
 - struct f2fs_node *rn;
   struct f2fs_inode *ri;
 
   f2fs_wait_on_page_writeback(node_page, NODE, false);
 
 - rn = F2FS_NODE(node_page);
 - ri = (rn-i);
 + ri = F2FS_INODE(node_page);
 
   ri-i_mode = cpu_to_le16(inode-i_mode);
   ri-i_advise = F2FS_I(inode)-i_advise;
 diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
 index e8fe52d..6fdd88c 100644
 --- a/fs/f2fs/node.c
 +++ b/fs/f2fs/node.c
 @@ -684,7 +684,7 @@ int truncate_inode_blocks(struct inode *inode, pgoff_t 
 from)
   int err = 0, cont = 1;
   int level, offset[4], noffset[4];
   unsigned int nofs = 0;
 - struct f2fs_node *rn;
 + struct f2fs_inode *ri;
   struct dnode_of_data dn;
   struct page *page;
 
 @@ -701,7 +701,7 @@ restart:
   set_new_dnode(dn, inode, page, NULL, 0);
   unlock_page(page);
 
 - rn = F2FS_NODE(page);
 + ri = F2FS_INODE(page);
   switch (level) {
   case 0:
   case 1:
 @@ -711,7 +711,7 @@ restart:
   nofs = noffset[1];
   if (!offset[level - 1])
   goto skip_partial;
 - err = truncate_partial_nodes(dn, rn-i, offset, level);
 + err = truncate_partial_nodes(dn, ri, offset, level);
   if (err  0  err != -ENOENT)
   goto fail;
   nofs += 1 + NIDS_PER_BLOCK;
 @@ -720,7 +720,7 @@ restart:
   nofs = 5 + 2 * NIDS_PER_BLOCK;
   if (!offset[level - 1])
   goto skip_partial;
 - err = truncate_partial_nodes(dn, rn-i, offset, level);
 + err = truncate_partial_nodes(dn, ri, offset, level);
   if (err  0  err != -ENOENT)
   goto fail;
   break;
 @@ -730,7 +730,7 @@ restart:
 
  skip_partial:
   while (cont) {
 - dn.nid = le32_to_cpu(rn-i.i_nid[offset[0] - NODE_DIR1_BLOCK]);
 +   

[f2fs-dev] [PATCH] f2fs: convert max_orphans to a field of f2fs_sb_info

2013-12-26 Thread Gu Zheng
Previously, we need to calculate the max orphan num when we try to acquire an
orphan inode, but it's a stable value since the super block was inited. So
converting it to a field of f2fs_sb_info and use it directly when needed seems
a better choose.

Signed-off-by: Gu Zheng guz.f...@cn.fujitsu.com
---
 fs/f2fs/checkpoint.c |   20 ++--
 fs/f2fs/f2fs.h   |1 +
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 2fc3b6b..0d78bbe 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -194,23 +194,15 @@ const struct address_space_operations f2fs_meta_aops = {
 
 int acquire_orphan_inode(struct f2fs_sb_info *sbi)
 {
-   unsigned int max_orphans;
int err = 0;
 
-   /*
-* considering 512 blocks in a segment 8 blocks are needed for cp
-* and log segment summaries. Remaining blocks are used to keep
-* orphan entries with the limitation one reserved segment
-* for cp pack we can have max 1020*504 orphan entries
-*/
-   max_orphans = (sbi-blocks_per_seg - 2 - NR_CURSEG_TYPE)
-   * F2FS_ORPHANS_PER_BLOCK;
mutex_lock(sbi-orphan_inode_mutex);
-   if (unlikely(sbi-n_orphans = max_orphans))
+   if (unlikely(sbi-n_orphans = sbi-max_orphans))
err = -ENOSPC;
else
sbi-n_orphans++;
mutex_unlock(sbi-orphan_inode_mutex);
+
return err;
 }
 
@@ -834,6 +826,14 @@ void init_orphan_info(struct f2fs_sb_info *sbi)
mutex_init(sbi-orphan_inode_mutex);
INIT_LIST_HEAD(sbi-orphan_inode_list);
sbi-n_orphans = 0;
+   /*
+* considering 512 blocks in a segment 8 blocks are needed for cp
+* and log segment summaries. Remaining blocks are used to keep
+* orphan entries with the limitation one reserved segment
+* for cp pack we can have max 1020*504 orphan entries
+*/
+   sbi-max_orphans = (sbi-blocks_per_seg - 2 - NR_CURSEG_TYPE)
+   * F2FS_ORPHANS_PER_BLOCK;
 }
 
 int __init create_checkpoint_caches(void)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 1a06f0a..36211cb 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -414,6 +414,7 @@ struct f2fs_sb_info {
struct list_head orphan_inode_list; /* orphan inode list */
struct mutex orphan_inode_mutex;/* for orphan inode list */
unsigned int n_orphans; /* # of orphan inodes */
+   unsigned int max_orphans;   /* max orphan inodes */
 
/* for directory inode management */
struct list_head dir_inode_list;/* dir inode list */
-- 
1.7.7


--
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=84349831iu=/4140/ostg.clktrk
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH] f2fs: check the blocksize before calling generic_direct_IO path

2013-12-26 Thread Jaegeuk Kim
The f2fs supports 4KB block size. If user requests dwrite with under 4KB data,
it allocates a new 4KB data block.
However, f2fs doesn't add zero data into the untouched data area inside the
newly allocated data block.

This incurs an error during the xfstest #263 test as follow.

263 12s ... [failed, exit status 1] - output mismatch (see 263.out.bad)
--- 263.out 2013-03-09 03:37:15.043967603 +0900
+++ 263.out.bad 2013-12-27 04:20:39.230203114 +0900
@@ -1,3 +1,976 @@
QA output created by 263
fsx -N 1 -o 8192 -l 50 -r PSIZE -t BSIZE -w BSIZE -Z
-fsx -N 1 -o 128000 -l 50 -r PSIZE -t BSIZE -w BSIZE -Z
+fsx -N 1 -o 8192 -l 50 -r PSIZE -t BSIZE -w BSIZE -Z
+truncating to largest ever: 0x12a00
+truncating to largest ever: 0x75400
+fallocating to largest ever: 0x79cbf
...
(Run 'diff -u 263.out 263.out.bad' to see the entire diff)
Ran: 263
Failures: 263
Failed 1 of 1 tests

It turns out that, when the test tries to write 2KB data with dio, the new dio
path allocates 4KB data block without filling zero data inside the remained 2KB
area. Finally, the output file contains a garbage data for that region.

Signed-off-by: Jaegeuk Kim jaegeuk@samsung.com
---
 fs/f2fs/data.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 991e368..e0965b4 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -953,11 +953,33 @@ static int f2fs_write_end(struct file *file,
return copied;
 }
 
+static int check_direct_IO(struct inode *inode, int rw,
+   const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+{
+   unsigned blocksize_mask = inode-i_sb-s_blocksize - 1;
+   int i;
+
+   if (rw == READ)
+   return 0;
+
+   if (offset  blocksize_mask)
+   return -EINVAL;
+
+   for (i = 0; i  nr_segs; i++)
+   if (iov[i].iov_len  blocksize_mask)
+   return -EINVAL;
+   return 0;
+}
+
 static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
const struct iovec *iov, loff_t offset, unsigned long nr_segs)
 {
struct file *file = iocb-ki_filp;
struct inode *inode = file-f_mapping-host;
+
+   if (check_direct_IO(inode, rw, iov, offset, nr_segs))
+   return 0;
+
return blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
get_data_block);
 }
-- 
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=84349831iu=/4140/ostg.clktrk
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH v2] f2fs: introduce F2FS_INODE macro to get f2fs_inode

2013-12-26 Thread Jaegeuk Kim
Hi,

Nice catch. :)

Change log from v1:
 o handle recover_inode_page too

From 58bfaf44df58082c72882b235cae611c975537d4 Mon Sep 17 00:00:00 2001
From: Jaegeuk Kim jaegeuk@samsung.com
Date: Thu, 26 Dec 2013 16:30:41 +0900
Subject: [PATCH] f2fs: introduce F2FS_INODE macro to get f2fs_inode

This patch introduces F2FS_INODE that returns struct f2fs_inode * from
the inode
page.
By using this macro, we can remove unnecessary casting codes like below.

   struct f2fs_inode *ri = F2FS_NODE(inode_page)-i;
- struct f2fs_inode *ri = F2FS_INODE(inode_page);

Reviewed-by: Chao Yu chao2...@samsung.com
Signed-off-by: Jaegeuk Kim jaegeuk@samsung.com
---
 fs/f2fs/dir.c  |  8 
 fs/f2fs/f2fs.h |  5 +
 fs/f2fs/inode.c|  8 ++--
 fs/f2fs/node.c | 30 +++---
 fs/f2fs/recovery.c |  6 ++
 5 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index f0b4630..6da77e5 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -261,12 +261,12 @@ void f2fs_set_link(struct inode *dir, struct
f2fs_dir_entry *de,
 
 static void init_dent_inode(const struct qstr *name, struct page
*ipage)
 {
-   struct f2fs_node *rn;
+   struct f2fs_inode *ri;
 
/* copy name info. to this inode page */
-   rn = F2FS_NODE(ipage);
-   rn-i.i_namelen = cpu_to_le32(name-len);
-   memcpy(rn-i.i_name, name-name, name-len);
+   ri = F2FS_INODE(ipage);
+   ri-i_namelen = cpu_to_le32(name-len);
+   memcpy(ri-i_name, name-name, name-len);
set_page_dirty(ipage);
 }
 
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ba91186..1a06f0a 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -498,6 +498,11 @@ static inline struct f2fs_node *F2FS_NODE(struct
page *page)
return (struct f2fs_node *)page_address(page);
 }
 
+static inline struct f2fs_inode *F2FS_INODE(struct page *page)
+{
+   return ((struct f2fs_node *)page_address(page))-i;
+}
+
 static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
 {
return (struct f2fs_nm_info *)(sbi-nm_info);
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index d0eaa9f..a91f451 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -67,7 +67,6 @@ static int do_read_inode(struct inode *inode)
struct f2fs_sb_info *sbi = F2FS_SB(inode-i_sb);
struct f2fs_inode_info *fi = F2FS_I(inode);
struct page *node_page;
-   struct f2fs_node *rn;
struct f2fs_inode *ri;
 
/* Check if ino is within scope */
@@ -81,8 +80,7 @@ static int do_read_inode(struct inode *inode)
if (IS_ERR(node_page))
return PTR_ERR(node_page);
 
-   rn = F2FS_NODE(node_page);
-   ri = (rn-i);
+   ri = F2FS_INODE(node_page);
 
inode-i_mode = le16_to_cpu(ri-i_mode);
i_uid_write(inode, le32_to_cpu(ri-i_uid));
@@ -175,13 +173,11 @@ bad_inode:
 
 void update_inode(struct inode *inode, struct page *node_page)
 {
-   struct f2fs_node *rn;
struct f2fs_inode *ri;
 
f2fs_wait_on_page_writeback(node_page, NODE, false);
 
-   rn = F2FS_NODE(node_page);
-   ri = (rn-i);
+   ri = F2FS_INODE(node_page);
 
ri-i_mode = cpu_to_le16(inode-i_mode);
ri-i_advise = F2FS_I(inode)-i_advise;
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index e8fe52d..9405a17 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -684,7 +684,7 @@ int truncate_inode_blocks(struct inode *inode,
pgoff_t from)
int err = 0, cont = 1;
int level, offset[4], noffset[4];
unsigned int nofs = 0;
-   struct f2fs_node *rn;
+   struct f2fs_inode *ri;
struct dnode_of_data dn;
struct page *page;
 
@@ -701,7 +701,7 @@ restart:
set_new_dnode(dn, inode, page, NULL, 0);
unlock_page(page);
 
-   rn = F2FS_NODE(page);
+   ri = F2FS_INODE(page);
switch (level) {
case 0:
case 1:
@@ -711,7 +711,7 @@ restart:
nofs = noffset[1];
if (!offset[level - 1])
goto skip_partial;
-   err = truncate_partial_nodes(dn, rn-i, offset, level);
+   err = truncate_partial_nodes(dn, ri, offset, level);
if (err  0  err != -ENOENT)
goto fail;
nofs += 1 + NIDS_PER_BLOCK;
@@ -720,7 +720,7 @@ restart:
nofs = 5 + 2 * NIDS_PER_BLOCK;
if (!offset[level - 1])
goto skip_partial;
-   err = truncate_partial_nodes(dn, rn-i, offset, level);
+   err = truncate_partial_nodes(dn, ri, offset, level);
if (err  0  err != -ENOENT)
goto fail;
break;
@@ -730,7 +730,7 @@ restart:
 
 skip_partial:
while (cont) {
-   dn.nid = le32_to_cpu(rn-i.i_nid[offset[0] - NODE_DIR1_BLOCK]);
+   dn.nid = le32_to_cpu(ri-i_nid[offset[0] - NODE_DIR1_BLOCK]);
switch (offset[0]) {
   

[f2fs-dev] Можем собрать для Вас контакты только Ваших потенциальных клиентов несколько десятков тысяч в течение суток Skype: prodawez389

2013-12-26 Thread linux-f2fs-devel
Можем собрать для Вас контакты только Ваших потенциальных клиентов несколько 
десятков тысяч в течение суток Skype: prodawez389

--
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=84349831iu=/4140/ostg.clktrk
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 4/6] f2fs: refactor f2fs_convert_inline_data

2013-12-26 Thread Jaegeuk Kim
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@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)

[f2fs-dev] [PATCH 6/6] f2fs: add inline_data recovery routine

2013-12-26 Thread Jaegeuk Kim
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@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 

[f2fs-dev] [PATCH 1/6] f2fs: don't need to get f2fs_lock_op for the inline_data test

2013-12-26 Thread Jaegeuk Kim
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@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=84349831iu=/4140/ostg.clktrk
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 2/6] f2fs: convert inline_data for punch_hole

2013-12-26 Thread Jaegeuk Kim
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@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=84349831iu=/4140/ostg.clktrk
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH 5/6] f2fs: add the number of inline_data files to status info

2013-12-26 Thread Jaegeuk Kim
Change log from v1:
 o fix kbuild failure

From a9ebdcffd30b9642b2973ea8e9688e7b0d4bf7e3 Mon Sep 17 00:00:00 2001
From: Jaegeuk Kim jaegeuk@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@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
@@