[f2fs-dev] [PATCH 02/09] f2fs: invalidate inmemory page

2014-10-19 Thread Jaegeuk Kim
If user truncates file's data, we should truncate inmemory pages too.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/data.c|  3 +++
 fs/f2fs/f2fs.h|  1 +
 fs/f2fs/segment.c | 16 
 3 files changed, 20 insertions(+)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 84f20e9..5b80ada 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1116,6 +1116,9 @@ static void f2fs_invalidate_data_page(struct page *page, 
unsigned int offset,
if (offset % PAGE_CACHE_SIZE || length != PAGE_CACHE_SIZE)
return;
 
+   if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode))
+   invalidate_inmem_page(inode, page);
+
if (PageDirty(page))
inode_dec_dirty_pages(inode);
ClearPagePrivate(page);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 28f24ea..d41d1b7 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1297,6 +1297,7 @@ void destroy_node_manager_caches(void);
  * segment.c
  */
 void register_inmem_page(struct inode *, struct page *);
+void invalidate_inmem_page(struct inode *, struct page *);
 void commit_inmem_pages(struct inode *, bool);
 void f2fs_balance_fs(struct f2fs_sb_info *);
 void f2fs_balance_fs_bg(struct f2fs_sb_info *);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 9d4a7ab..902c4c3 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -203,6 +203,22 @@ retry:
mutex_unlock(&fi->inmem_lock);
 }
 
+void invalidate_inmem_page(struct inode *inode, struct page *page)
+{
+   struct f2fs_inode_info *fi = F2FS_I(inode);
+   struct inmem_pages *cur;
+
+   mutex_lock(&fi->inmem_lock);
+   cur = radix_tree_lookup(&fi->inmem_root, page->index);
+   if (cur) {
+   radix_tree_delete(&fi->inmem_root, cur->page->index);
+   f2fs_put_page(cur->page, 0);
+   list_del(&cur->list);
+   kmem_cache_free(inmem_entry_slab, cur);
+   }
+   mutex_unlock(&fi->inmem_lock);
+}
+
 void commit_inmem_pages(struct inode *inode, bool abort)
 {
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 05/09] f2fs: use highmem for directory pages

2014-10-19 Thread Jaegeuk Kim
This patch fixes to use highmem for directory pages.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/inode.c | 2 +-
 include/linux/f2fs_fs.h | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 0deead4..52d6f54 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -156,7 +156,7 @@ make_now:
inode->i_op = &f2fs_dir_inode_operations;
inode->i_fop = &f2fs_dir_operations;
inode->i_mapping->a_ops = &f2fs_dblock_aops;
-   mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
+   mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_HIGH_ZERO);
} else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &f2fs_symlink_inode_operations;
inode->i_mapping->a_ops = &f2fs_dblock_aops;
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index 860313a..6d7381b 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -33,7 +33,8 @@
 #define F2FS_META_INO(sbi) (sbi->meta_ino_num)
 
 /* This flag is used by node and meta inodes, and by recovery */
-#define GFP_F2FS_ZERO  (GFP_NOFS | __GFP_ZERO)
+#define GFP_F2FS_ZERO  (GFP_NOFS | __GFP_ZERO)
+#define GFP_F2FS_HIGH_ZERO (GFP_NOFS | __GFP_ZERO | __GFP_HIGHMEM)
 
 /*
  * For further optimization on multi-head logs, on-disk layout supports maximum
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 08/09] f2fs: avoid build warning

2014-10-19 Thread Jaegeuk Kim
This patch removes build warning.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/segment.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 902c4c3..2c1e608 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -1715,7 +1715,7 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
 * #2, flush sit entries to sit page.
 */
list_for_each_entry_safe(ses, tmp, head, set_list) {
-   struct page *page;
+   struct page *page = NULL;
struct f2fs_sit_block *raw_sit = NULL;
unsigned int start_segno = ses->start_segno;
unsigned int end = min(start_segno + SIT_ENTRY_PER_BLOCK,
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 07/09] f2fs: fix to call f2fs_unlock_op

2014-10-19 Thread Jaegeuk Kim
This patch fixes to call f2fs_unlock_op, which was missing before.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/file.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 456df07..80d9a04 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -494,7 +494,7 @@ int truncate_blocks(struct inode *inode, u64 from, bool 
lock)
/* writepage can convert inline_data under get_donde_of_data */
if (f2fs_has_inline_data(inode)) {
f2fs_put_dnode(&dn);
-   goto done;
+   goto unlock_done;
}
 
count = ADDRS_PER_PAGE(dn.node_page, F2FS_I(inode));
@@ -510,6 +510,7 @@ int truncate_blocks(struct inode *inode, u64 from, bool 
lock)
f2fs_put_dnode(&dn);
 free_next:
err = truncate_inode_blocks(inode, free_from);
+unlock_done:
if (lock)
f2fs_unlock_op(sbi);
 done:
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 01/09] f2fs: do not make dirty any inmemory pages

2014-10-19 Thread Jaegeuk Kim
This patch let inmemory pages be clean all the time.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/data.c| 11 +++
 fs/f2fs/f2fs.h|  1 +
 fs/f2fs/segment.c | 14 +-
 fs/f2fs/super.c   |  1 +
 4 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 8e58c4c..84f20e9 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1052,10 +1052,7 @@ static int f2fs_write_end(struct file *file,
 
trace_f2fs_write_end(inode, pos, len, copied);
 
-   if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode))
-   register_inmem_page(inode, page);
-   else
-   set_page_dirty(page);
+   set_page_dirty(page);
 
if (pos + copied > i_size_read(inode)) {
i_size_write(inode, pos + copied);
@@ -1138,6 +1135,12 @@ static int f2fs_set_data_page_dirty(struct page *page)
trace_f2fs_set_page_dirty(page, DATA);
 
SetPageUptodate(page);
+
+   if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode)) {
+   register_inmem_page(inode, page);
+   return 1;
+   }
+
mark_inode_dirty(inode);
 
if (!PageDirty(page)) {
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 8171e80..28f24ea 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -269,6 +269,7 @@ struct f2fs_inode_info {
struct extent_info ext; /* in-memory extent cache entry */
struct dir_inode_entry *dirty_dir;  /* the pointer of dirty dir */
 
+   struct radix_tree_root inmem_root;  /* radix tree for inmem pages */
struct list_head inmem_pages;   /* inmemory pages managed by f2fs */
struct mutex inmem_lock;/* lock for inmemory pages */
 };
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 923cb76..9d4a7ab 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -178,7 +178,8 @@ void register_inmem_page(struct inode *inode, struct page 
*page)
 {
struct f2fs_inode_info *fi = F2FS_I(inode);
struct inmem_pages *new;
-
+   int err;
+retry:
new = f2fs_kmem_cache_alloc(inmem_entry_slab, GFP_NOFS);
 
/* add atomic page indices to the list */
@@ -187,6 +188,16 @@ void register_inmem_page(struct inode *inode, struct page 
*page)
 
/* increase reference count with clean state */
mutex_lock(&fi->inmem_lock);
+   err = radix_tree_insert(&fi->inmem_root, page->index, new);
+   if (err == -EEXIST) {
+   mutex_unlock(&fi->inmem_lock);
+   kmem_cache_free(inmem_entry_slab, new);
+   return;
+   } else if (err) {
+   mutex_unlock(&fi->inmem_lock);
+   kmem_cache_free(inmem_entry_slab, new);
+   goto retry;
+   }
get_page(page);
list_add_tail(&new->list, &fi->inmem_pages);
mutex_unlock(&fi->inmem_lock);
@@ -216,6 +227,7 @@ void commit_inmem_pages(struct inode *inode, bool abort)
do_write_data_page(cur->page, &fio);
submit_bio = true;
}
+   radix_tree_delete(&fi->inmem_root, cur->page->index);
f2fs_put_page(cur->page, 1);
list_del(&cur->list);
kmem_cache_free(inmem_entry_slab, cur);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 41d6f70..76b14c8 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -373,6 +373,7 @@ static struct inode *f2fs_alloc_inode(struct super_block 
*sb)
fi->i_advise = 0;
rwlock_init(&fi->ext.ext_lock);
init_rwsem(&fi->i_sem);
+   INIT_RADIX_TREE(&fi->inmem_root, GFP_NOFS);
INIT_LIST_HEAD(&fi->inmem_pages);
mutex_init(&fi->inmem_lock);
 
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 03/09] f2fs: should truncate any allocated block for inline_data write

2014-10-19 Thread Jaegeuk Kim
When trying to write inline_data, we should truncate any data block allocated
and pointed by the inode block.
We should consider the data index is not 0.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/inline.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 88036fd..e3abcfb 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -166,6 +166,14 @@ int f2fs_write_inline_data(struct inode *inode,
return err;
ipage = dn.inode_page;
 
+   /* Release any data block if it is allocated */
+   if (!f2fs_has_inline_data(inode)) {
+   int count = ADDRS_PER_PAGE(dn.node_page, F2FS_I(inode));
+   truncate_data_blocks_range(&dn, count);
+   set_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
+   stat_inc_inline_inode(inode);
+   }
+
f2fs_wait_on_page_writeback(ipage, NODE);
zero_user_segment(ipage, INLINE_DATA_OFFSET,
 INLINE_DATA_OFFSET + MAX_INLINE_DATA);
@@ -174,13 +182,6 @@ int f2fs_write_inline_data(struct inode *inode,
memcpy(dst_addr, src_addr, size);
kunmap(page);
 
-   /* Release the first data block if it is allocated */
-   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);
-   }
-
set_inode_flag(F2FS_I(inode), FI_APPEND_WRITE);
sync_inode_page(&dn);
f2fs_put_dnode(&dn);
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 06/09] f2fs: avoid to allocate when inline_data was written

2014-10-19 Thread Jaegeuk Kim
The sceanrio is like this.
inline_data   i_size page write_begin/vm_page_mkwrite
  X 30   dirty_page
  X 30write to #4096 position
  X 30   get_dnode_of_datawait for get_dnode_of_data
  O 30   write inline_data
  O 30get_dnode_of_data
  O 30reserve data block
..

In this case, we have #0 = NEW_ADDR and inline_data as well.
We should not allow this condition for further access.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/data.c | 32 +++-
 fs/f2fs/file.c | 26 ++
 2 files changed, 45 insertions(+), 13 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 5b80ada..973fd77 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -257,9 +257,6 @@ int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t 
index)
bool need_put = dn->inode_page ? false : true;
int err;
 
-   /* if inode_page exists, index should be zero */
-   f2fs_bug_on(F2FS_I_SB(dn->inode), !need_put && index);
-
err = get_dnode_of_data(dn, index, ALLOC_NODE);
if (err)
return err;
@@ -951,7 +948,7 @@ static int f2fs_write_begin(struct file *file, struct 
address_space *mapping,
 {
struct inode *inode = mapping->host;
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-   struct page *page;
+   struct page *page, *ipage;
pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT;
struct dnode_of_data dn;
int err = 0;
@@ -979,13 +976,26 @@ repeat:
goto inline_data;
 
f2fs_lock_op(sbi);
-   set_new_dnode(&dn, inode, NULL, NULL, 0);
-   err = f2fs_reserve_block(&dn, index);
-   f2fs_unlock_op(sbi);
-   if (err) {
+
+   /* check inline_data */
+   ipage = get_node_page(sbi, inode->i_ino);
+   if (IS_ERR(ipage))
+   goto unlock_fail;
+
+   if (f2fs_has_inline_data(inode)) {
+   f2fs_put_page(ipage, 1);
+   f2fs_unlock_op(sbi);
f2fs_put_page(page, 0);
-   goto fail;
+   goto repeat;
}
+
+   set_new_dnode(&dn, inode, ipage, NULL, 0);
+   err = f2fs_reserve_block(&dn, index);
+   if (err)
+   goto unlock_fail;
+   f2fs_put_dnode(&dn);
+   f2fs_unlock_op(sbi);
+
 inline_data:
lock_page(page);
if (unlikely(page->mapping != mapping)) {
@@ -1038,6 +1048,10 @@ out:
SetPageUptodate(page);
clear_cold_data(page);
return 0;
+
+unlock_fail:
+   f2fs_unlock_op(sbi);
+   f2fs_put_page(page, 0);
 fail:
f2fs_write_failed(mapping, pos + len);
return err;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 543d8c6..456df07 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -35,12 +35,13 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
struct inode *inode = file_inode(vma->vm_file);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct dnode_of_data dn;
+   struct page *ipage;
int err;
 
f2fs_balance_fs(sbi);
 
sb_start_pagefault(inode->i_sb);
-
+retry:
/* force to convert with normal data indices */
err = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1, page);
if (err)
@@ -48,11 +49,28 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
 
/* block allocation */
f2fs_lock_op(sbi);
-   set_new_dnode(&dn, inode, NULL, NULL, 0);
+
+   /* check inline_data */
+   ipage = get_node_page(sbi, inode->i_ino);
+   if (IS_ERR(ipage)) {
+   f2fs_unlock_op(sbi);
+   goto out;
+   }
+
+   if (f2fs_has_inline_data(inode)) {
+   f2fs_put_page(ipage, 1);
+   f2fs_unlock_op(sbi);
+   goto retry;
+   }
+
+   set_new_dnode(&dn, inode, ipage, NULL, 0);
err = f2fs_reserve_block(&dn, page->index);
-   f2fs_unlock_op(sbi);
-   if (err)
+   if (err) {
+   f2fs_unlock_op(sbi);
goto out;
+   }
+   f2fs_put_dnode(&dn);
+   f2fs_unlock_op(sbi);
 
file_update_time(vma->vm_file);
lock_page(page);
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 04/09] f2fs: fix race conditon on truncation with inline_data

2014-10-19 Thread Jaegeuk Kim
Let's consider the following scenario.

blkaddr[0] inline_data i_size  i_blocks writepage   truncate
  NEWX40962dirty page #0
  NEWX 0change i_size
  NEWX 0  2f2fs_write_inline_data
  NEWX 0  2get_dnode_of_data
  NEWX 0  2truncate_data_blocks_range
  NULL   O 0  1memcpy(inline_data)
  NULL   O 0  1f2fs_put_dnode
  NULL   O 0  1 f2fs_truncate
  NULL   O 0  1 get_dnode_of_data
  NULL   O 0  1   *invalid block addr*

This patch adds checking inline_data flag during f2fs_truncate not to refer
corrupted block indices.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/file.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 8e68bb6..543d8c6 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -473,6 +473,12 @@ int truncate_blocks(struct inode *inode, u64 from, bool 
lock)
return err;
}
 
+   /* writepage can convert inline_data under get_donde_of_data */
+   if (f2fs_has_inline_data(inode)) {
+   f2fs_put_dnode(&dn);
+   goto done;
+   }
+
count = ADDRS_PER_PAGE(dn.node_page, F2FS_I(inode));
 
count -= dn.ofs_in_node;
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 09/09] f2fs: avoid infinite loop at cp_error

2014-10-19 Thread Jaegeuk Kim
This patch avoids an infinite loop in sync_dirty_inode_page when -EIO was
detected.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/checkpoint.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index dd10a03..ca514d5 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -731,6 +731,9 @@ void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
struct dir_inode_entry *entry;
struct inode *inode;
 retry:
+   if (unlikely(f2fs_cp_error(sbi)))
+   return;
+
spin_lock(&sbi->dir_inode_lock);
 
head = &sbi->dir_inode_list;
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 02/11] f2fs: reuse find_in_block code for find_in_inline_dir

2014-10-19 Thread Jaegeuk Kim
This patch removes redundant copied code in find_in_inline_dir.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/dir.c| 72 +++-
 fs/f2fs/f2fs.h   |  3 ++-
 fs/f2fs/inline.c | 52 +---
 3 files changed, 64 insertions(+), 63 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 164c6c9..c60b93f 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -77,7 +77,7 @@ static unsigned long dir_block_index(unsigned int level,
return bidx;
 }
 
-bool early_match_name(size_t namelen, f2fs_hash_t namehash,
+static bool early_match_name(size_t namelen, f2fs_hash_t namehash,
struct f2fs_dir_entry *de)
 {
if (le16_to_cpu(de->name_len) != namelen)
@@ -90,49 +90,68 @@ bool early_match_name(size_t namelen, f2fs_hash_t namehash,
 }
 
 static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
-   struct qstr *name, int *max_slots,
-   f2fs_hash_t namehash, struct page **res_page)
+   struct qstr *name, int *max_slots,
+   struct page **res_page)
+{
+   struct f2fs_dentry_block *dentry_blk;
+   struct f2fs_dir_entry *de;
+
+   *max_slots = NR_DENTRY_IN_BLOCK;
+
+   dentry_blk = (struct f2fs_dentry_block *)kmap(dentry_page);
+   de = find_target_dentry(name, max_slots, &dentry_blk->dentry_bitmap,
+   dentry_blk->dentry,
+   dentry_blk->filename);
+   kunmap(dentry_page);
+   if (de)
+   *res_page = dentry_page;
+
+   /*
+* For the most part, it should be a bug when name_len is zero.
+* We stop here for figuring out where the bugs has occurred.
+*/
+   f2fs_bug_on(F2FS_P_SB(dentry_page), *max_slots < 0);
+   return de;
+}
+
+struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots,
+   const void *bitmap, struct f2fs_dir_entry *dentry,
+   __u8 (*filenames)[F2FS_SLOT_LEN])
 {
struct f2fs_dir_entry *de;
unsigned long bit_pos = 0;
-   struct f2fs_dentry_block *dentry_blk = kmap(dentry_page);
-   const void *dentry_bits = &dentry_blk->dentry_bitmap;
+   f2fs_hash_t namehash = f2fs_dentry_hash(name);
+   int max_bits = *max_slots;
int max_len = 0;
 
-   while (bit_pos < NR_DENTRY_IN_BLOCK) {
-   if (!test_bit_le(bit_pos, dentry_bits)) {
+   *max_slots = 0;
+   while (bit_pos < max_bits) {
+   if (!test_bit_le(bit_pos, bitmap)) {
if (bit_pos == 0)
max_len = 1;
-   else if (!test_bit_le(bit_pos - 1, dentry_bits))
+   else if (!test_bit_le(bit_pos - 1, bitmap))
max_len++;
bit_pos++;
continue;
}
-   de = &dentry_blk->dentry[bit_pos];
-   if (early_match_name(name->len, namehash, de)) {
-   if (!memcmp(dentry_blk->filename[bit_pos],
-   name->name,
-   name->len)) {
-   *res_page = dentry_page;
-   goto found;
-   }
-   }
-   if (max_len > *max_slots) {
+   de = &dentry[bit_pos];
+   if (early_match_name(name->len, namehash, de) &&
+   !memcmp(filenames[bit_pos], name->name, name->len))
+   goto found;
+
+   if (*max_slots >= 0 && max_len > *max_slots) {
*max_slots = max_len;
max_len = 0;
}
 
-   /*
-* For the most part, it should be a bug when name_len is zero.
-* We stop here for figuring out where the bugs has occurred.
-*/
-   f2fs_bug_on(F2FS_P_SB(dentry_page), !de->name_len);
+   /* remain bug on condition */
+   if (unlikely(!de->name_len))
+   *max_slots = -1;
 
bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
}
 
de = NULL;
-   kunmap(dentry_page);
 found:
if (max_len > *max_slots)
*max_slots = max_len;
@@ -149,7 +168,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode 
*dir,
struct page *dentry_page;
struct f2fs_dir_entry *de = NULL;
bool room = false;
-   int max_slots = 0;
+   int max_slots;
 
f2fs_bug_on(F2FS_I_SB(dir), level > MAX_DIR_HASH_DEPTH);
 
@@ -168,8 +187,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode 
*dir,
continue;
}
 
-

[f2fs-dev] [PATCH 09/11] f2fs: introduce f2fs_dentry_ptr structure for code clean-up

2014-10-19 Thread Jaegeuk Kim
This patch introduces f2fs_dentry_ptr structure for the use of a function
parameter in inline_dentry operations.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/dir.c| 61 +++-
 fs/f2fs/f2fs.h   | 34 ++-
 fs/f2fs/inline.c | 18 -
 3 files changed, 67 insertions(+), 46 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 721d061..80665ce 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -95,13 +95,13 @@ static struct f2fs_dir_entry *find_in_block(struct page 
*dentry_page,
 {
struct f2fs_dentry_block *dentry_blk;
struct f2fs_dir_entry *de;
-
-   *max_slots = NR_DENTRY_IN_BLOCK;
+   struct f2fs_dentry_ptr d;
 
dentry_blk = (struct f2fs_dentry_block *)kmap(dentry_page);
-   de = find_target_dentry(name, max_slots, &dentry_blk->dentry_bitmap,
-   dentry_blk->dentry,
-   dentry_blk->filename);
+
+   make_dentry_ptr(&d, dentry_blk, NULL, 1);
+   de = find_target_dentry(name, max_slots, &d);
+
kunmap(dentry_page);
if (de)
*res_page = dentry_page;
@@ -110,50 +110,49 @@ static struct f2fs_dir_entry *find_in_block(struct page 
*dentry_page,
 * For the most part, it should be a bug when name_len is zero.
 * We stop here for figuring out where the bugs has occurred.
 */
-   f2fs_bug_on(F2FS_P_SB(dentry_page), *max_slots < 0);
+   f2fs_bug_on(F2FS_P_SB(dentry_page), d.max < 0);
return de;
 }
 
 struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots,
-   const void *bitmap, struct f2fs_dir_entry *dentry,
-   __u8 (*filenames)[F2FS_SLOT_LEN])
+   struct f2fs_dentry_ptr *d)
 {
struct f2fs_dir_entry *de;
unsigned long bit_pos = 0;
f2fs_hash_t namehash = f2fs_dentry_hash(name);
-   int max_bits = *max_slots;
int max_len = 0;
 
-   *max_slots = 0;
-   while (bit_pos < max_bits) {
-   if (!test_bit_le(bit_pos, bitmap)) {
+   if (max_slots)
+   *max_slots = 0;
+   while (bit_pos < d->max) {
+   if (!test_bit_le(bit_pos, d->bitmap)) {
if (bit_pos == 0)
max_len = 1;
-   else if (!test_bit_le(bit_pos - 1, bitmap))
+   else if (!test_bit_le(bit_pos - 1, d->bitmap))
max_len++;
bit_pos++;
continue;
}
-   de = &dentry[bit_pos];
+   de = &d->dentry[bit_pos];
if (early_match_name(name->len, namehash, de) &&
-   !memcmp(filenames[bit_pos], name->name, name->len))
+   !memcmp(d->filename[bit_pos], name->name, name->len))
goto found;
 
-   if (*max_slots >= 0 && max_len > *max_slots) {
+   if (max_slots && *max_slots >= 0 && max_len > *max_slots) {
*max_slots = max_len;
max_len = 0;
}
 
/* remain bug on condition */
if (unlikely(!de->name_len))
-   *max_slots = -1;
+   d->max = -1;
 
bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
}
 
de = NULL;
 found:
-   if (max_len > *max_slots)
+   if (max_slots && max_len > *max_slots)
*max_slots = max_len;
return de;
 }
@@ -705,28 +704,26 @@ bool f2fs_empty_dir(struct inode *dir)
return true;
 }
 
-bool f2fs_fill_dentries(struct dir_context *ctx,
-   const void *bitmap, struct f2fs_dir_entry *dentry,
-   __u8 (*filenames)[F2FS_SLOT_LEN], int max,
-   unsigned int start_pos)
+bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
+   unsigned int start_pos)
 {
unsigned char d_type = DT_UNKNOWN;
unsigned int bit_pos;
struct f2fs_dir_entry *de = NULL;
 
-   bit_pos = ((unsigned long)ctx->pos % max);
+   bit_pos = ((unsigned long)ctx->pos % d->max);
 
-   while (bit_pos < max) {
-   bit_pos = find_next_bit_le(bitmap, max, bit_pos);
-   if (bit_pos >= max)
+   while (bit_pos < d->max) {
+   bit_pos = find_next_bit_le(d->bitmap, d->max, bit_pos);
+   if (bit_pos >= d->max)
break;
 
-   de = &dentry[bit_pos];
+   de = &d->dentry[bit_pos];
if (de->file_type < F2FS_FT_MAX)
d_type = f2fs_filetype_table[de->file_type];
else
d_type = DT_UNKNOWN;
-  

[f2fs-dev] [PATCH 03/11] f2fs: fix to wait correct block type

2014-10-19 Thread Jaegeuk Kim
The inode page needs to wait NODE block io.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/dir.c| 3 ++-
 fs/f2fs/inline.c | 4 ++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index c60b93f..644b480 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -282,8 +282,9 @@ ino_t f2fs_inode_by_name(struct inode *dir, struct qstr 
*qstr)
 void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
struct page *page, struct inode *inode)
 {
+   enum page_type type = f2fs_has_inline_dentry(dir) ? NODE : DATA;
lock_page(page);
-   f2fs_wait_on_page_writeback(page, DATA);
+   f2fs_wait_on_page_writeback(page, type);
de->ino = cpu_to_le32(inode->i_ino);
set_de_type(de, inode);
if (!f2fs_has_inline_dentry(dir))
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 6f9ba80..6fbdce7 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -429,7 +429,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct 
qstr *name,
goto out;
}
 
-   f2fs_wait_on_page_writeback(ipage, DATA);
+   f2fs_wait_on_page_writeback(ipage, NODE);
 
down_write(&F2FS_I(inode)->i_sem);
page = init_inode_metadata(inode, dir, name);
@@ -474,7 +474,7 @@ void f2fs_delete_inline_entry(struct f2fs_dir_entry 
*dentry, struct page *page,
int i;
 
lock_page(page);
-   f2fs_wait_on_page_writeback(page, DATA);
+   f2fs_wait_on_page_writeback(page, NODE);
 
inline_dentry = inline_data_addr(page);
bit_pos = dentry - inline_dentry->dentry;
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 10/11] f2fs: reuse make_empty_dir code for inline_dentry

2014-10-19 Thread Jaegeuk Kim
This patch introduces do_make_empty_dir to mitigate code redundancy
for inline_dentry.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/dir.c| 42 ++
 fs/f2fs/f2fs.h   |  2 ++
 fs/f2fs/inline.c | 20 +++-
 3 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 80665ce..b751f94 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -322,12 +322,35 @@ int update_dent_inode(struct inode *inode, const struct 
qstr *name)
return 0;
 }
 
+void do_make_empty_dir(struct inode *inode, struct inode *parent,
+   struct f2fs_dentry_ptr *d)
+{
+   struct f2fs_dir_entry *de;
+
+   de = &d->dentry[0];
+   de->name_len = cpu_to_le16(1);
+   de->hash_code = 0;
+   de->ino = cpu_to_le32(inode->i_ino);
+   memcpy(d->filename[0], ".", 1);
+   set_de_type(de, inode);
+
+   de = &d->dentry[1];
+   de->hash_code = 0;
+   de->name_len = cpu_to_le16(2);
+   de->ino = cpu_to_le32(parent->i_ino);
+   memcpy(d->filename[1], "..", 2);
+   set_de_type(de, inode);
+
+   test_and_set_bit_le(0, (void *)d->bitmap);
+   test_and_set_bit_le(1, (void *)d->bitmap);
+}
+
 static int make_empty_dir(struct inode *inode,
struct inode *parent, struct page *page)
 {
struct page *dentry_page;
struct f2fs_dentry_block *dentry_blk;
-   struct f2fs_dir_entry *de;
+   struct f2fs_dentry_ptr d;
 
if (f2fs_has_inline_dentry(inode))
return make_empty_inline_dir(inode, parent, page);
@@ -338,22 +361,9 @@ static int make_empty_dir(struct inode *inode,
 
dentry_blk = kmap_atomic(dentry_page);
 
-   de = &dentry_blk->dentry[0];
-   de->name_len = cpu_to_le16(1);
-   de->hash_code = 0;
-   de->ino = cpu_to_le32(inode->i_ino);
-   memcpy(dentry_blk->filename[0], ".", 1);
-   set_de_type(de, inode);
-
-   de = &dentry_blk->dentry[1];
-   de->hash_code = 0;
-   de->name_len = cpu_to_le16(2);
-   de->ino = cpu_to_le32(parent->i_ino);
-   memcpy(dentry_blk->filename[1], "..", 2);
-   set_de_type(de, inode);
+   make_dentry_ptr(&d, dentry_blk, NULL, 1);
+   do_make_empty_dir(inode, parent, &d);
 
-   test_and_set_bit_le(0, &dentry_blk->dentry_bitmap);
-   test_and_set_bit_le(1, &dentry_blk->dentry_bitmap);
kunmap_atomic(dentry_blk);
 
set_page_dirty(dentry_page);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 0856a38..267d54e 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1274,6 +1274,8 @@ struct f2fs_dir_entry *find_target_dentry(struct qstr *, 
int *,
struct f2fs_dentry_ptr *);
 bool f2fs_fill_dentries(struct dir_context *, struct f2fs_dentry_ptr *,
unsigned int);
+void do_make_empty_dir(struct inode *, struct inode *,
+   struct f2fs_dentry_ptr *);
 struct page *init_inode_metadata(struct inode *, struct inode *,
const struct qstr *, struct page *);
 void update_parent_metadata(struct inode *, struct inode *, unsigned int);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index edacfa1..825995f 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -314,26 +314,12 @@ int make_empty_inline_dir(struct inode *inode, struct 
inode *parent,
struct page *ipage)
 {
struct f2fs_inline_dentry *dentry_blk;
-   struct f2fs_dir_entry *de;
+   struct f2fs_dentry_ptr d;
 
dentry_blk = inline_data_addr(ipage);
 
-   de = &dentry_blk->dentry[0];
-   de->name_len = cpu_to_le16(1);
-   de->hash_code = 0;
-   de->ino = cpu_to_le32(inode->i_ino);
-   memcpy(dentry_blk->filename[0], ".", 1);
-   set_de_type(de, inode);
-
-   de = &dentry_blk->dentry[1];
-   de->hash_code = 0;
-   de->name_len = cpu_to_le16(2);
-   de->ino = cpu_to_le32(parent->i_ino);
-   memcpy(dentry_blk->filename[1], "..", 2);
-   set_de_type(de, inode);
-
-   test_and_set_bit_le(0, &dentry_blk->dentry_bitmap);
-   test_and_set_bit_le(1, &dentry_blk->dentry_bitmap);
+   make_dentry_ptr(&d, NULL, dentry_blk, 2);
+   do_make_empty_dir(inode, parent, &d);
 
set_page_dirty(ipage);
 
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 11/11] f2fs: use kmap_atomic instead of kmap

2014-10-19 Thread Jaegeuk Kim
For better performance, we need to use kmap_atomic instead of kmap.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/inline.c | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 825995f..c03653d 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -55,11 +55,10 @@ int f2fs_read_inline_data(struct inode *inode, struct page 
*page)
 
/* Copy the whole inline data block */
src_addr = inline_data_addr(ipage);
-   dst_addr = kmap(page);
+   dst_addr = kmap_atomic(page);
memcpy(dst_addr, src_addr, MAX_INLINE_DATA);
-   kunmap(page);
+   kunmap_atomic(dst_addr);
f2fs_put_page(ipage, 1);
-
 out:
SetPageUptodate(page);
unlock_page(page);
@@ -105,9 +104,9 @@ static int __f2fs_convert_inline_data(struct inode *inode, 
struct page *page)
 
/* Copy the whole inline data block */
src_addr = inline_data_addr(ipage);
-   dst_addr = kmap(page);
+   dst_addr = kmap_atomic(page);
memcpy(dst_addr, src_addr, MAX_INLINE_DATA);
-   kunmap(page);
+   kunmap_atomic(dst_addr);
SetPageUptodate(page);
 
/* write data page to try to make data consistent */
@@ -177,10 +176,10 @@ int f2fs_write_inline_data(struct inode *inode,
f2fs_wait_on_page_writeback(ipage, NODE);
zero_user_segment(ipage, INLINE_DATA_OFFSET,
 INLINE_DATA_OFFSET + MAX_INLINE_DATA);
-   src_addr = kmap(page);
+   src_addr = kmap_atomic(page);
dst_addr = inline_data_addr(ipage);
memcpy(dst_addr, src_addr, size);
-   kunmap(page);
+   kunmap_atomic(src_addr);
 
set_inode_flag(F2FS_I(inode), FI_APPEND_WRITE);
sync_inode_page(&dn);
@@ -351,7 +350,7 @@ int f2fs_convert_inline_dir(struct inode *dir, struct page 
*ipage,
f2fs_wait_on_page_writeback(page, DATA);
zero_user_segment(page, 0, PAGE_CACHE_SIZE);
 
-   dentry_blk = kmap(page);
+   dentry_blk = kmap_atomic(page);
 
/* copy data from inline dentry block to new dentry block */
memcpy(dentry_blk->dentry_bitmap, inline_dentry->dentry_bitmap,
@@ -363,7 +362,7 @@ int f2fs_convert_inline_dir(struct inode *dir, struct page 
*ipage,
memcpy(dentry_blk->filename, inline_dentry->filename,
NR_INLINE_DENTRY * F2FS_SLOT_LEN);
 
-   kunmap(page);
+   kunmap_atomic(dentry_blk);
SetPageUptodate(page);
set_page_dirty(page);
 
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation

2014-10-19 Thread Jaegeuk Kim
This patch introduces to reuse the existing room_for_filename for inline dentry
operation.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/dir.c| 21 +
 fs/f2fs/f2fs.h   |  1 +
 fs/f2fs/inline.c | 27 ++-
 3 files changed, 12 insertions(+), 37 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index cc6474a..164c6c9 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -427,27 +427,23 @@ void update_parent_metadata(struct inode *dir, struct 
inode *inode,
clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
 }
 
-static int room_for_filename(struct f2fs_dentry_block *dentry_blk, int slots)
+int room_for_filename(const void *bitmap, int slots, int max_slots)
 {
int bit_start = 0;
int zero_start, zero_end;
 next:
-   zero_start = find_next_zero_bit_le(&dentry_blk->dentry_bitmap,
-   NR_DENTRY_IN_BLOCK,
-   bit_start);
-   if (zero_start >= NR_DENTRY_IN_BLOCK)
-   return NR_DENTRY_IN_BLOCK;
+   zero_start = find_next_zero_bit_le(bitmap, max_slots, bit_start);
+   if (zero_start >= max_slots)
+   return max_slots;
 
-   zero_end = find_next_bit_le(&dentry_blk->dentry_bitmap,
-   NR_DENTRY_IN_BLOCK,
-   zero_start);
+   zero_end = find_next_bit_le(bitmap, max_slots, zero_start);
if (zero_end - zero_start >= slots)
return zero_start;
 
bit_start = zero_end + 1;
 
-   if (zero_end + 1 >= NR_DENTRY_IN_BLOCK)
-   return NR_DENTRY_IN_BLOCK;
+   if (zero_end + 1 >= max_slots)
+   return max_slots;
goto next;
 }
 
@@ -509,7 +505,8 @@ start:
return PTR_ERR(dentry_page);
 
dentry_blk = kmap(dentry_page);
-   bit_pos = room_for_filename(dentry_blk, slots);
+   bit_pos = room_for_filename(&dentry_blk->dentry_bitmap,
+   slots, NR_DENTRY_IN_BLOCK);
if (bit_pos < NR_DENTRY_IN_BLOCK)
goto add_dentry;
 
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c537699..aa055e3 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1248,6 +1248,7 @@ void set_de_type(struct f2fs_dir_entry *, struct inode *);
 struct page *init_inode_metadata(struct inode *, struct inode *,
const struct qstr *);
 void update_parent_metadata(struct inode *, struct inode *, unsigned int);
+int room_for_filename(const void *, int, int);
 void f2fs_drop_nlink(struct inode *, struct inode *, struct page *);
 struct f2fs_dir_entry *f2fs_find_entry(struct inode *, struct qstr *,
struct page **);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 02e2449..5d9dabb 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -363,30 +363,6 @@ int make_empty_inline_dir(struct inode *inode, struct 
inode *parent,
return 0;
 }
 
-int room_in_inline_dir(struct f2fs_inline_dentry *dentry_blk, int slots)
-{
-   int bit_start = 0;
-   int zero_start, zero_end;
-next:
-   zero_start = find_next_zero_bit_le(&dentry_blk->dentry_bitmap,
-   NR_INLINE_DENTRY,
-   bit_start);
-   if (zero_start >= NR_INLINE_DENTRY)
-   return NR_INLINE_DENTRY;
-
-   zero_end = find_next_bit_le(&dentry_blk->dentry_bitmap,
-   NR_INLINE_DENTRY,
-   zero_start);
-   if (zero_end - zero_start >= slots)
-   return zero_start;
-
-   bit_start = zero_end + 1;
-
-   if (zero_end + 1 >= NR_INLINE_DENTRY)
-   return NR_INLINE_DENTRY;
-   goto next;
-}
-
 int f2fs_convert_inline_dir(struct inode *dir, struct page *ipage,
struct f2fs_inline_dentry *inline_dentry)
 {
@@ -462,7 +438,8 @@ int f2fs_add_inline_entry(struct inode *dir, const struct 
qstr *name,
return PTR_ERR(ipage);
 
dentry_blk = inline_data_addr(ipage);
-   bit_pos = room_in_inline_dir(dentry_blk, slots);
+   bit_pos = room_for_filename(&dentry_blk->dentry_bitmap,
+   slots, NR_INLINE_DENTRY);
if (bit_pos >= NR_INLINE_DENTRY) {
err = f2fs_convert_inline_dir(dir, ipage, dentry_blk);
if (!err)
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___

[f2fs-dev] [PATCH 08/11] f2fs: should not truncate any inline_dentry

2014-10-19 Thread Jaegeuk Kim
If the inode has inline_dentry, we should not truncate any block indices.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/file.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index d054e0e..402e381 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -471,7 +471,7 @@ int truncate_blocks(struct inode *inode, u64 from, bool 
lock)
 
trace_f2fs_truncate_blocks_enter(inode, from);
 
-   if (f2fs_has_inline_data(inode))
+   if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode))
goto done;
 
free_from = (pgoff_t)
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 06/11] f2fs: fix counting inline_data inode numbers

2014-10-19 Thread Jaegeuk Kim
This patch fixes wrongly counting inline_data inode numbers.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/inode.c | 4 ++--
 fs/f2fs/namei.c | 2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index b9b1d6b..4131e3c 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -169,6 +169,7 @@ make_now:
goto bad_inode;
}
unlock_new_inode(inode);
+   stat_inc_inline_inode(inode);
stat_inc_inline_dir(inode);
trace_f2fs_iget(inode);
return inode;
@@ -296,12 +297,12 @@ 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);
 no_delete:
stat_dec_inline_dir(inode);
+   stat_dec_inline_inode(inode);
invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino);
if (xnid)
invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid);
@@ -327,7 +328,6 @@ void handle_failed_inode(struct inode *inode)
f2fs_truncate(inode);
 
remove_inode_page(inode);
-   stat_dec_inline_inode(inode);
 
clear_inode_flag(F2FS_I(inode), FI_INLINE_DENTRY);
alloc_nid_failed(sbi, inode->i_ino);
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 94ba291..a004a97 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -198,8 +198,6 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct 
dentry *dentry,
inode = f2fs_iget(dir->i_sb, ino);
if (IS_ERR(inode))
return ERR_CAST(inode);
-
-   stat_inc_inline_inode(inode);
}
 
return d_splice_alias(inode, dentry);
-- 
2.1.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH 07/11] f2fs: reuse core function in f2fs_readdir for inline_dentry

2014-10-19 Thread Jaegeuk Kim
This patch introduces a core function, f2fs_fill_dentries, to remove
redundant code in f2fs_readdir and f2fs_read_inline_dir.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/dir.c| 64 +---
 fs/f2fs/f2fs.h   |  3 +++
 fs/f2fs/inline.c | 39 +++---
 3 files changed, 48 insertions(+), 58 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 334e227..721d061 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -705,23 +705,50 @@ bool f2fs_empty_dir(struct inode *dir)
return true;
 }
 
+bool f2fs_fill_dentries(struct dir_context *ctx,
+   const void *bitmap, struct f2fs_dir_entry *dentry,
+   __u8 (*filenames)[F2FS_SLOT_LEN], int max,
+   unsigned int start_pos)
+{
+   unsigned char d_type = DT_UNKNOWN;
+   unsigned int bit_pos;
+   struct f2fs_dir_entry *de = NULL;
+
+   bit_pos = ((unsigned long)ctx->pos % max);
+
+   while (bit_pos < max) {
+   bit_pos = find_next_bit_le(bitmap, max, bit_pos);
+   if (bit_pos >= max)
+   break;
+
+   de = &dentry[bit_pos];
+   if (de->file_type < F2FS_FT_MAX)
+   d_type = f2fs_filetype_table[de->file_type];
+   else
+   d_type = DT_UNKNOWN;
+   if (!dir_emit(ctx, filenames[bit_pos],
+   le16_to_cpu(de->name_len),
+   le32_to_cpu(de->ino), d_type))
+   return true;
+
+   bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
+   ctx->pos = start_pos + bit_pos;
+   }
+   return false;
+}
+
 static int f2fs_readdir(struct file *file, struct dir_context *ctx)
 {
struct inode *inode = file_inode(file);
unsigned long npages = dir_blocks(inode);
-   unsigned int bit_pos = 0;
struct f2fs_dentry_block *dentry_blk = NULL;
-   struct f2fs_dir_entry *de = NULL;
struct page *dentry_page = NULL;
struct file_ra_state *ra = &file->f_ra;
unsigned int n = ((unsigned long)ctx->pos / NR_DENTRY_IN_BLOCK);
-   unsigned char d_type = DT_UNKNOWN;
 
if (f2fs_has_inline_dentry(inode))
return f2fs_read_inline_dir(file, ctx);
 
-   bit_pos = ((unsigned long)ctx->pos % NR_DENTRY_IN_BLOCK);
-
/* readahead for multi pages of dir */
if (npages - n > 1 && !ra_has_index(ra, n))
page_cache_sync_readahead(inode->i_mapping, ra, file, n,
@@ -733,28 +760,13 @@ static int f2fs_readdir(struct file *file, struct 
dir_context *ctx)
continue;
 
dentry_blk = kmap(dentry_page);
-   while (bit_pos < NR_DENTRY_IN_BLOCK) {
-   bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
-   NR_DENTRY_IN_BLOCK,
-   bit_pos);
-   if (bit_pos >= NR_DENTRY_IN_BLOCK)
-   break;
-
-   de = &dentry_blk->dentry[bit_pos];
-   if (de->file_type < F2FS_FT_MAX)
-   d_type = f2fs_filetype_table[de->file_type];
-   else
-   d_type = DT_UNKNOWN;
-   if (!dir_emit(ctx,
-   dentry_blk->filename[bit_pos],
-   le16_to_cpu(de->name_len),
-   le32_to_cpu(de->ino), d_type))
-   goto stop;
 
-   bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
-   ctx->pos = n * NR_DENTRY_IN_BLOCK + bit_pos;
-   }
-   bit_pos = 0;
+   if (f2fs_fill_dentries(ctx,
+   &dentry_blk->dentry_bitmap, dentry_blk->dentry,
+   dentry_blk->filename,
+   NR_DENTRY_IN_BLOCK, n * NR_DENTRY_IN_BLOCK))
+   goto stop;
+
ctx->pos = (n + 1) * NR_DENTRY_IN_BLOCK;
kunmap(dentry_page);
f2fs_put_page(dentry_page, 1);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 9c4c8d1..3b0f490 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1247,6 +1247,9 @@ extern unsigned char f2fs_filetype_table[F2FS_FT_MAX];
 void set_de_type(struct f2fs_dir_entry *, struct inode *);
 struct f2fs_dir_entry *find_target_dentry(struct qstr *, int *, const void *,
struct f2fs_dir_entry *, __u8 (*)[F2FS_SLOT_LEN]);
+bool f2fs_fill_dentries(struct dir_context *,
+   const void *, struct f2fs_dir_entry *,
+   __u8 (*)[F2FS_SLOT_LEN], int, unsigned int);
 struct page *init_inode_metadata(struct ino

[f2fs-dev] [PATCH 04/11] f2fs: avoid deadlock on init_inode_metadata

2014-10-19 Thread Jaegeuk Kim
Previously, init_inode_metadata does not hold any parent directory's inode
page. So, f2fs_init_acl can grab its parent inode page without any problem.
But, when we use inline_dentry, that page is grabbed during f2fs_add_link,
so that we can fall into deadlock condition like below.

INFO: task mknod:11006 blocked for more than 120 seconds.
  Tainted: G   OE  3.17.0-rc1+ #13
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
mknod   D 88003fc94580 0 11006  11004 0x
 880007717b10 0002 88003c323220 880007717fd8
 00014580 00014580 88003daecb30 88003c323220
 88003fc94e80 88003ffbb4e8 880007717ba0 0002
Call Trace:
 [] ? bit_wait+0x50/0x50
 [] io_schedule+0x9d/0x130
 [] bit_wait_io+0x2c/0x50
 [] __wait_on_bit_lock+0x4b/0xb0
 [] __lock_page+0x67/0x70
 [] ? autoremove_wake_function+0x40/0x40
 [] pagecache_get_page+0x14c/0x1e0
 [] get_node_page+0x59/0x130 [f2fs]
 [] read_all_xattrs+0x24d/0x430 [f2fs]
 [] f2fs_getxattr+0x52/0xe0 [f2fs]
 [] f2fs_get_acl+0x41/0x2d0 [f2fs]
 [] get_acl+0x47/0x70
 [] posix_acl_create+0x5a/0x150
 [] f2fs_init_acl+0x29/0xcb [f2fs]
 [] init_inode_metadata+0x5d/0x340 [f2fs]
 [] f2fs_add_inline_entry+0x12a/0x2e0 [f2fs]
 [] __f2fs_add_link+0x45/0x4a0 [f2fs]
 [] ? f2fs_new_inode+0x146/0x220 [f2fs]
 [] f2fs_mknod+0x86/0xf0 [f2fs]
 [] vfs_mknod+0xe1/0x160
 [] SyS_mknod+0x1f6/0x200
 [] tracesys+0xe1/0xe6

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/acl.c| 144 ---
 fs/f2fs/acl.h|   5 +-
 fs/f2fs/dir.c|  10 ++--
 fs/f2fs/f2fs.h   |   2 +-
 fs/f2fs/inline.c |   6 +--
 fs/f2fs/xattr.c  |   6 +--
 fs/f2fs/xattr.h  |   6 ++-
 7 files changed, 157 insertions(+), 22 deletions(-)

diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 83b9b5a..6207455 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -162,7 +162,8 @@ fail:
return ERR_PTR(-EINVAL);
 }
 
-struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
+static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type,
+   struct page *dpage)
 {
int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
void *value = NULL;
@@ -172,12 +173,13 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int 
type)
if (type == ACL_TYPE_ACCESS)
name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
 
-   retval = f2fs_getxattr(inode, name_index, "", NULL, 0);
+   retval = f2fs_getxattr(inode, name_index, "", NULL, 0, dpage);
if (retval > 0) {
value = kmalloc(retval, GFP_F2FS_ZERO);
if (!value)
return ERR_PTR(-ENOMEM);
-   retval = f2fs_getxattr(inode, name_index, "", value, retval);
+   retval = f2fs_getxattr(inode, name_index, "", value,
+   retval, dpage);
}
 
if (retval > 0)
@@ -194,6 +196,11 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int 
type)
return acl;
 }
 
+struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
+{
+   return __f2fs_get_acl(inode, type, NULL);
+}
+
 static int __f2fs_set_acl(struct inode *inode, int type,
struct posix_acl *acl, struct page *ipage)
 {
@@ -249,12 +256,137 @@ int f2fs_set_acl(struct inode *inode, struct posix_acl 
*acl, int type)
return __f2fs_set_acl(inode, type, acl, NULL);
 }
 
-int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage)
+/*
+ * Most part of f2fs_acl_clone, f2fs_acl_create_masq, f2fs_acl_create
+ * are copied from posix_acl.c
+ */
+static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl,
+   gfp_t flags)
+{
+   struct posix_acl *clone = NULL;
+
+   if (acl) {
+   int size = sizeof(struct posix_acl) + acl->a_count *
+   sizeof(struct posix_acl_entry);
+   clone = kmemdup(acl, size, flags);
+   if (clone)
+   atomic_set(&clone->a_refcount, 1);
+   }
+   return clone;
+}
+
+static int f2fs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
+{
+   struct posix_acl_entry *pa, *pe;
+   struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
+   umode_t mode = *mode_p;
+   int not_equiv = 0;
+
+   /* assert(atomic_read(acl->a_refcount) == 1); */
+
+   FOREACH_ACL_ENTRY(pa, acl, pe) {
+   switch(pa->e_tag) {
+   case ACL_USER_OBJ:
+   pa->e_perm &= (mode >> 6) | ~S_IRWXO;
+   mode &= (pa->e_perm << 6) | ~S_IRWXU;
+   break;
+
+   case ACL_USER:
+   case ACL_GROUP:
+   not_equiv = 1;
+   break;
+
+   case ACL_GROUP_OBJ:
+   group_obj

[f2fs-dev] [PATCH 05/11] f2fs: add stat info for inline_dentry inodes

2014-10-19 Thread Jaegeuk Kim
This patch adds status information for inline_dentry inodes.

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/debug.c  |  3 +++
 fs/f2fs/f2fs.h   | 16 ++--
 fs/f2fs/inline.c |  2 +-
 fs/f2fs/inode.c  |  3 +++
 fs/f2fs/namei.c  |  1 +
 5 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 0a91ab8..86e6e92 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -46,6 +46,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
si->valid_node_count = valid_node_count(sbi);
si->valid_inode_count = valid_inode_count(sbi);
si->inline_inode = sbi->inline_inode;
+   si->inline_dir = sbi->inline_dir;
si->utilization = utilization(sbi);
 
si->free_segs = free_segments(sbi);
@@ -200,6 +201,8 @@ static int stat_show(struct seq_file *s, void *v)
   si->valid_count - si->valid_node_count);
seq_printf(s, "  - Inline_data Inode: %u\n",
   si->inline_inode);
+   seq_printf(s, "  - Inline_dentry Inode: %u\n",
+  si->inline_dir);
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 d4dcd93..9c4c8d1 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -560,6 +560,7 @@ struct f2fs_sb_info {
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 inline_dir; /* # of inline_dentry inodes */
int bg_gc;  /* background gc calls */
unsigned int n_dirty_dirs;  /* # of dir inodes */
 #endif
@@ -1434,7 +1435,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, inline_inode;
+   int bg_gc, inline_inode, inline_dir;
unsigned int valid_count, valid_node_count, valid_inode_count;
unsigned int bimodal, avg_vblocks;
int util_free, util_valid, util_invalid;
@@ -1474,7 +1475,16 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct 
f2fs_sb_info *sbi)
if (f2fs_has_inline_data(inode))\
((F2FS_I_SB(inode))->inline_inode--);   \
} while (0)
-
+#define stat_inc_inline_dir(inode) \
+   do {\
+   if (f2fs_has_inline_dentry(inode))  \
+   ((F2FS_I_SB(inode))->inline_dir++); \
+   } while (0)
+#define stat_dec_inline_dir(inode) \
+   do {\
+   if (f2fs_has_inline_dentry(inode))  \
+   ((F2FS_I_SB(inode))->inline_dir--); \
+   } while (0)
 #define stat_inc_seg_type(sbi, curseg) \
((sbi)->segment_count[(curseg)->alloc_type]++)
 #define stat_inc_block_count(sbi, curseg)  \
@@ -1521,6 +1531,8 @@ void f2fs_destroy_root_stats(void);
 #define stat_inc_read_hit(sb)
 #define stat_inc_inline_inode(inode)
 #define stat_dec_inline_inode(inode)
+#define stat_inc_inline_dir(inode)
+#define stat_dec_inline_dir(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 3d44947..633d5e8 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -384,8 +384,8 @@ int f2fs_convert_inline_dir(struct inode *dir, struct page 
*ipage,
/* clear inline dir and flag after data writeback */
zero_user_segment(ipage, INLINE_DATA_OFFSET,
 INLINE_DATA_OFFSET + MAX_INLINE_DATA);
+   stat_dec_inline_dir(dir);
clear_inode_flag(F2FS_I(dir), FI_INLINE_DENTRY);
-   stat_dec_inline_inode(dir);
 
if (i_size_read(dir) < PAGE_CACHE_SIZE) {
i_size_write(dir, PAGE_CACHE_SIZE);
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 52d6f54..b9b1d6b 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -169,6 +169,7 @@ make_now:
goto bad_inode;
}
unlock_new_inode(inode);
+   stat_inc_inline_dir(inode);
trace_f2fs_iget(inode);
return inode;
 
@@ -300,6 +301,7 @@ void f2fs_evict_inode(struct inode *inode)
 
sb_end_intwrite(inode->i_sb);
 no_delete:
+   stat_dec_inline_dir(inode);
invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino,