linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation
@ 2014-10-20  5:19 Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 02/11] f2fs: reuse find_in_block code for find_in_inline_dir Jaegeuk Kim
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch introduces to reuse the existing room_for_filename for inline dentry
operation.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 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


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 02/11] f2fs: reuse find_in_block code for find_in_inline_dir
  2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
@ 2014-10-20  5:19 ` Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 03/11] f2fs: fix to wait correct block type Jaegeuk Kim
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch removes redundant copied code in find_in_inline_dir.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 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;
 		}
 
-		de = find_in_block(dentry_page, name, &max_slots,
-					namehash, res_page);
+		de = find_in_block(dentry_page, name, &max_slots, res_page);
 		if (de)
 			break;
 
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index aa055e3..6aad6e0 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1243,8 +1243,9 @@ struct dentry *f2fs_get_parent(struct dentry *child);
  * dir.c
  */
 extern unsigned char f2fs_filetype_table[F2FS_FT_MAX];
-bool early_match_name(size_t, f2fs_hash_t, struct f2fs_dir_entry *);
 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]);
 struct page *init_inode_metadata(struct inode *, struct inode *,
 							const struct qstr *);
 void update_parent_metadata(struct inode *, struct inode *, unsigned int);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 5d9dabb..6f9ba80 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -263,49 +263,31 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
 				struct qstr *name, struct page **res_page)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
-	struct page *ipage;
+	struct f2fs_inline_dentry *inline_dentry;
 	struct f2fs_dir_entry *de;
-	f2fs_hash_t namehash;
-	unsigned long bit_pos = 0;
-	struct f2fs_inline_dentry *dentry_blk;
-	const void *dentry_bits;
+	struct page *ipage;
+	int max_slots = NR_INLINE_DENTRY;
 
 	ipage = get_node_page(sbi, dir->i_ino);
 	if (IS_ERR(ipage))
 		return NULL;
 
-	namehash = f2fs_dentry_hash(name);
-
-	dentry_blk = inline_data_addr(ipage);
-	dentry_bits = &dentry_blk->dentry_bitmap;
-
-	while (bit_pos < NR_INLINE_DENTRY) {
-		if (!test_bit_le(bit_pos, dentry_bits)) {
-			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 = ipage;
-				goto found;
-			}
-		}
-
-		/*
-		 * For the most part, it should be a bug when name_len is zero.
-		 * We stop here for figuring out where the bugs are occurred.
-		 */
-		f2fs_bug_on(F2FS_P_SB(ipage), !de->name_len);
-
-		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
-	}
+	inline_dentry = inline_data_addr(ipage);
 
-	de = NULL;
-found:
+	de = find_target_dentry(name, &max_slots, &inline_dentry->dentry_bitmap,
+						inline_dentry->dentry,
+						inline_dentry->filename);
 	unlock_page(ipage);
+	if (de)
+		*res_page = ipage;
+	else
+		f2fs_put_page(ipage, 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(sbi, max_slots < 0);
 	return de;
 }
 
-- 
2.1.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 03/11] f2fs: fix to wait correct block type
  2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 02/11] f2fs: reuse find_in_block code for find_in_inline_dir Jaegeuk Kim
@ 2014-10-20  5:19 ` Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 04/11] f2fs: avoid deadlock on init_inode_metadata Jaegeuk Kim
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

The inode page needs to wait NODE block io.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 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


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 04/11] f2fs: avoid deadlock on init_inode_metadata
  2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 02/11] f2fs: reuse find_in_block code for find_in_inline_dir Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 03/11] f2fs: fix to wait correct block type Jaegeuk Kim
@ 2014-10-20  5:19 ` Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 05/11] f2fs: add stat info for inline_dentry inodes Jaegeuk Kim
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: 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 ffff88003fc94580     0 11006  11004 0x00000000
 ffff880007717b10 0000000000000002 ffff88003c323220 ffff880007717fd8
 0000000000014580 0000000000014580 ffff88003daecb30 ffff88003c323220
 ffff88003fc94e80 ffff88003ffbb4e8 ffff880007717ba0 0000000000000002
Call Trace:
 [<ffffffff8173dc40>] ? bit_wait+0x50/0x50
 [<ffffffff8173d4cd>] io_schedule+0x9d/0x130
 [<ffffffff8173dc6c>] bit_wait_io+0x2c/0x50
 [<ffffffff8173da3b>] __wait_on_bit_lock+0x4b/0xb0
 [<ffffffff811640a7>] __lock_page+0x67/0x70
 [<ffffffff810acf50>] ? autoremove_wake_function+0x40/0x40
 [<ffffffff811652cc>] pagecache_get_page+0x14c/0x1e0
 [<ffffffffa029afa9>] get_node_page+0x59/0x130 [f2fs]
 [<ffffffffa02a63ad>] read_all_xattrs+0x24d/0x430 [f2fs]
 [<ffffffffa02a6ca2>] f2fs_getxattr+0x52/0xe0 [f2fs]
 [<ffffffffa02a7481>] f2fs_get_acl+0x41/0x2d0 [f2fs]
 [<ffffffff8122d847>] get_acl+0x47/0x70
 [<ffffffff8122db5a>] posix_acl_create+0x5a/0x150
 [<ffffffffa02a7759>] f2fs_init_acl+0x29/0xcb [f2fs]
 [<ffffffffa0286a8d>] init_inode_metadata+0x5d/0x340 [f2fs]
 [<ffffffffa029253a>] f2fs_add_inline_entry+0x12a/0x2e0 [f2fs]
 [<ffffffffa0286ea5>] __f2fs_add_link+0x45/0x4a0 [f2fs]
 [<ffffffffa028b5b6>] ? f2fs_new_inode+0x146/0x220 [f2fs]
 [<ffffffffa028b816>] f2fs_mknod+0x86/0xf0 [f2fs]
 [<ffffffff811e3ec1>] vfs_mknod+0xe1/0x160
 [<ffffffff811e4b26>] SyS_mknod+0x1f6/0x200
 [<ffffffff81741d7f>] tracesys+0xe1/0xe6

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 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 = pa;
+			break;
+
+		case ACL_OTHER:
+			pa->e_perm &= mode | ~S_IRWXO;
+			mode &= pa->e_perm | ~S_IRWXO;
+			break;
+
+		case ACL_MASK:
+			mask_obj = pa;
+			not_equiv = 1;
+			break;
+
+		default:
+			return -EIO;
+		}
+	}
+
+	if (mask_obj) {
+		mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
+		mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
+	} else {
+		if (!group_obj)
+			return -EIO;
+		group_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
+		mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
+	}
+
+	*mode_p = (*mode_p & ~S_IRWXUGO) | mode;
+        return not_equiv;
+}
+
+static int f2fs_acl_create(struct inode *dir, umode_t *mode,
+		struct posix_acl **default_acl, struct posix_acl **acl,
+		struct page *dpage)
+{
+	struct posix_acl *p;
+	int ret;
+
+	if (S_ISLNK(*mode) || !IS_POSIXACL(dir))
+		goto no_acl;
+
+	p = __f2fs_get_acl(dir, ACL_TYPE_DEFAULT, dpage);
+	if (IS_ERR(p)) {
+		if (p == ERR_PTR(-EOPNOTSUPP))
+			goto apply_umask;
+		return PTR_ERR(p);
+	}
+
+	if (!p)
+		goto apply_umask;
+
+	*acl = f2fs_acl_clone(p, GFP_NOFS);
+	if (!*acl)
+		return -ENOMEM;
+
+	ret = f2fs_acl_create_masq(*acl, mode);
+	if (ret < 0) {
+		posix_acl_release(*acl);
+		return -ENOMEM;
+	}
+
+	if (ret == 0) {
+		posix_acl_release(*acl);
+		*acl = NULL;
+	}
+
+	if (!S_ISDIR(*mode)) {
+		posix_acl_release(p);
+		*default_acl = NULL;
+	} else {
+		*default_acl = p;
+	}
+	return 0;
+
+apply_umask:
+	*mode &= ~current_umask();
+no_acl:
+	*default_acl = NULL;
+	*acl = NULL;
+	return 0;
+}
+
+int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage,
+							struct page *dpage)
 {
-	struct posix_acl *default_acl, *acl;
+	struct posix_acl *default_acl = NULL, *acl = NULL;
 	int error = 0;
 
-	error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
+	error = f2fs_acl_create(dir, &inode->i_mode, &default_acl, &acl, dpage);
 	if (error)
 		return error;
 
diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h
index e086465..997ca8e 100644
--- a/fs/f2fs/acl.h
+++ b/fs/f2fs/acl.h
@@ -38,14 +38,15 @@ struct f2fs_acl_header {
 
 extern struct posix_acl *f2fs_get_acl(struct inode *, int);
 extern int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
-extern int f2fs_init_acl(struct inode *, struct inode *, struct page *);
+extern int f2fs_init_acl(struct inode *, struct inode *, struct page *,
+							struct page *);
 #else
 #define f2fs_check_acl	NULL
 #define f2fs_get_acl	NULL
 #define f2fs_set_acl	NULL
 
 static inline int f2fs_init_acl(struct inode *inode, struct inode *dir,
-							struct page *page)
+				struct page *ipage, struct page *dpage)
 {
 	return 0;
 }
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 644b480..334e227 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -362,8 +362,8 @@ static int make_empty_dir(struct inode *inode,
 	return 0;
 }
 
-struct page *init_inode_metadata(struct inode *inode,
-		struct inode *dir, const struct qstr *name)
+struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
+			const struct qstr *name, struct page *dpage)
 {
 	struct page *page;
 	int err;
@@ -379,7 +379,7 @@ struct page *init_inode_metadata(struct inode *inode,
 				goto error;
 		}
 
-		err = f2fs_init_acl(inode, dir, page);
+		err = f2fs_init_acl(inode, dir, page, dpage);
 		if (err)
 			goto put_error;
 
@@ -540,7 +540,7 @@ add_dentry:
 	f2fs_wait_on_page_writeback(dentry_page, DATA);
 
 	down_write(&F2FS_I(inode)->i_sem);
-	page = init_inode_metadata(inode, dir, name);
+	page = init_inode_metadata(inode, dir, name, NULL);
 	if (IS_ERR(page)) {
 		err = PTR_ERR(page);
 		goto fail;
@@ -579,7 +579,7 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
 	int err = 0;
 
 	down_write(&F2FS_I(inode)->i_sem);
-	page = init_inode_metadata(inode, dir, NULL);
+	page = init_inode_metadata(inode, dir, NULL, NULL);
 	if (IS_ERR(page)) {
 		err = PTR_ERR(page);
 		goto fail;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 6aad6e0..d4dcd93 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1247,7 +1247,7 @@ 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]);
 struct page *init_inode_metadata(struct inode *, struct inode *,
-							const struct qstr *);
+			const struct qstr *, struct page *);
 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 *);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 6fbdce7..3d44947 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -429,14 +429,14 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name,
 		goto out;
 	}
 
-	f2fs_wait_on_page_writeback(ipage, NODE);
-
 	down_write(&F2FS_I(inode)->i_sem);
-	page = init_inode_metadata(inode, dir, name);
+	page = init_inode_metadata(inode, dir, name, ipage);
 	if (IS_ERR(page)) {
 		err = PTR_ERR(page);
 		goto fail;
 	}
+
+	f2fs_wait_on_page_writeback(ipage, NODE);
 	de = &dentry_blk->dentry[bit_pos];
 	de->hash_code = name_hash;
 	de->name_len = cpu_to_le16(namelen);
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index deca872..5072bf9 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -83,7 +83,7 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
 	}
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return f2fs_getxattr(dentry->d_inode, type, name, buffer, size);
+	return f2fs_getxattr(dentry->d_inode, type, name, buffer, size, NULL);
 }
 
 static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
@@ -398,7 +398,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
 }
 
 int f2fs_getxattr(struct inode *inode, int index, const char *name,
-		void *buffer, size_t buffer_size)
+		void *buffer, size_t buffer_size, struct page *ipage)
 {
 	struct f2fs_xattr_entry *entry;
 	void *base_addr;
@@ -412,7 +412,7 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name,
 	if (len > F2FS_NAME_LEN)
 		return -ERANGE;
 
-	base_addr = read_all_xattrs(inode, NULL);
+	base_addr = read_all_xattrs(inode, ipage);
 	if (!base_addr)
 		return -ENOMEM;
 
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
index 34ab7db..969d792 100644
--- a/fs/f2fs/xattr.h
+++ b/fs/f2fs/xattr.h
@@ -115,7 +115,8 @@ extern const struct xattr_handler *f2fs_xattr_handlers[];
 
 extern int f2fs_setxattr(struct inode *, int, const char *,
 				const void *, size_t, struct page *, int);
-extern int f2fs_getxattr(struct inode *, int, const char *, void *, size_t);
+extern int f2fs_getxattr(struct inode *, int, const char *, void *,
+						size_t, struct page *);
 extern ssize_t f2fs_listxattr(struct dentry *, char *, size_t);
 #else
 
@@ -126,7 +127,8 @@ static inline int f2fs_setxattr(struct inode *inode, int index,
 	return -EOPNOTSUPP;
 }
 static inline int f2fs_getxattr(struct inode *inode, int index,
-		const char *name, void *buffer, size_t buffer_size)
+			const char *name, void *buffer,
+			size_t buffer_size, struct page *dpage)
 {
 	return -EOPNOTSUPP;
 }
-- 
2.1.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 05/11] f2fs: add stat info for inline_dentry inodes
  2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
                   ` (2 preceding siblings ...)
  2014-10-20  5:19 ` [PATCH 04/11] f2fs: avoid deadlock on init_inode_metadata Jaegeuk Kim
@ 2014-10-20  5:19 ` Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 06/11] f2fs: fix counting inline_data inode numbers Jaegeuk Kim
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch adds status information for inline_dentry inodes.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 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, inode->i_ino);
 	if (xnid)
 		invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid);
@@ -327,6 +329,7 @@ void handle_failed_inode(struct inode *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);
 	f2fs_unlock_op(sbi);
 
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index c8290da..94ba291 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -297,6 +297,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 		goto out_fail;
 	f2fs_unlock_op(sbi);
 
+	stat_inc_inline_dir(inode);
 	alloc_nid_done(sbi, inode->i_ino);
 
 	d_instantiate(dentry, inode);
-- 
2.1.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 06/11] f2fs: fix counting inline_data inode numbers
  2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
                   ` (3 preceding siblings ...)
  2014-10-20  5:19 ` [PATCH 05/11] f2fs: add stat info for inline_dentry inodes Jaegeuk Kim
@ 2014-10-20  5:19 ` Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 07/11] f2fs: reuse core function in f2fs_readdir for inline_dentry Jaegeuk Kim
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch fixes wrongly counting inline_data inode numbers.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 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


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 07/11] f2fs: reuse core function in f2fs_readdir for inline_dentry
  2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
                   ` (4 preceding siblings ...)
  2014-10-20  5:19 ` [PATCH 06/11] f2fs: fix counting inline_data inode numbers Jaegeuk Kim
@ 2014-10-20  5:19 ` Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 08/11] f2fs: should not truncate any inline_dentry Jaegeuk Kim
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: 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 <jaegeuk@kernel.org>
---
 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 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 633d5e8..403c8f7 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -519,49 +519,24 @@ bool f2fs_empty_inline_dir(struct inode *dir)
 int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx)
 {
 	struct inode *inode = file_inode(file);
-	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-	unsigned int bit_pos = 0;
 	struct f2fs_inline_dentry *inline_dentry = NULL;
-	struct f2fs_dir_entry *de = NULL;
 	struct page *ipage = NULL;
-	unsigned char d_type = DT_UNKNOWN;
 
 	if (ctx->pos == NR_INLINE_DENTRY)
 		return 0;
 
-	ipage = get_node_page(sbi, inode->i_ino);
+	ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino);
 	if (IS_ERR(ipage))
 		return PTR_ERR(ipage);
 
-	bit_pos = ((unsigned long)ctx->pos % NR_INLINE_DENTRY);
-
 	inline_dentry = inline_data_addr(ipage);
-	while (bit_pos < NR_INLINE_DENTRY) {
-		bit_pos = find_next_bit_le(&inline_dentry->dentry_bitmap,
-						NR_INLINE_DENTRY,
-						bit_pos);
-		if (bit_pos >= NR_INLINE_DENTRY)
-			break;
-
-		de = &inline_dentry->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,
-				inline_dentry->filename[bit_pos],
-				le16_to_cpu(de->name_len),
-				le32_to_cpu(de->ino), d_type))
-			goto out;
-
-		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
-		ctx->pos = bit_pos;
-	}
 
-	ctx->pos = NR_INLINE_DENTRY;
-out:
-	f2fs_put_page(ipage, 1);
+	if (!f2fs_fill_dentries(ctx, &inline_dentry->dentry_bitmap,
+				inline_dentry->dentry,
+				inline_dentry->filename,
+				NR_INLINE_DENTRY, 0))
+		ctx->pos = NR_INLINE_DENTRY;
 
+	f2fs_put_page(ipage, 1);
 	return 0;
 }
-- 
2.1.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 08/11] f2fs: should not truncate any inline_dentry
  2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
                   ` (5 preceding siblings ...)
  2014-10-20  5:19 ` [PATCH 07/11] f2fs: reuse core function in f2fs_readdir for inline_dentry Jaegeuk Kim
@ 2014-10-20  5:19 ` Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 09/11] f2fs: introduce f2fs_dentry_ptr structure for code clean-up Jaegeuk Kim
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

If the inode has inline_dentry, we should not truncate any block indices.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 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


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 09/11] f2fs: introduce f2fs_dentry_ptr structure for code clean-up
  2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
                   ` (6 preceding siblings ...)
  2014-10-20  5:19 ` [PATCH 08/11] f2fs: should not truncate any inline_dentry Jaegeuk Kim
@ 2014-10-20  5:19 ` Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 10/11] f2fs: reuse make_empty_dir code for inline_dentry Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 11/11] f2fs: use kmap_atomic instead of kmap Jaegeuk Kim
  9 siblings, 0 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: 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 <jaegeuk@kernel.org>
---
 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;
-		if (!dir_emit(ctx, filenames[bit_pos],
+		if (!dir_emit(ctx, d->filename[bit_pos],
 					le16_to_cpu(de->name_len),
 					le32_to_cpu(de->ino), d_type))
 			return true;
@@ -745,6 +742,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
 	struct page *dentry_page = NULL;
 	struct file_ra_state *ra = &file->f_ra;
 	unsigned int n = ((unsigned long)ctx->pos / NR_DENTRY_IN_BLOCK);
+	struct f2fs_dentry_ptr d;
 
 	if (f2fs_has_inline_dentry(inode))
 		return f2fs_read_inline_dir(file, ctx);
@@ -761,10 +759,9 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
 
 		dentry_blk = kmap(dentry_page);
 
-		if (f2fs_fill_dentries(ctx,
-				&dentry_blk->dentry_bitmap, dentry_blk->dentry,
-				dentry_blk->filename,
-				NR_DENTRY_IN_BLOCK, n * NR_DENTRY_IN_BLOCK))
+		make_dentry_ptr(&d, dentry_blk, NULL, 1);
+
+		if (f2fs_fill_dentries(ctx, &d, n * NR_DENTRY_IN_BLOCK))
 			goto stop;
 
 		ctx->pos = (n + 1) * NR_DENTRY_IN_BLOCK;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 3b0f490..0856a38 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -212,6 +212,31 @@ static inline bool __has_cursum_space(struct f2fs_summary_block *sum, int size,
 /*
  * For INODE and NODE manager
  */
+/* for directory operations */
+struct f2fs_dentry_ptr {
+	const void *bitmap;
+	struct f2fs_dir_entry *dentry;
+	__u8 (*filename)[F2FS_SLOT_LEN];
+	int max;
+};
+
+static inline void make_dentry_ptr(struct f2fs_dentry_ptr *d,
+			struct f2fs_dentry_block *d1,
+			struct f2fs_inline_dentry *d2, int type)
+{
+	if (type == 1) {
+		d->max = NR_DENTRY_IN_BLOCK;
+		d->bitmap = &d1->dentry_bitmap;
+		d->dentry = d1->dentry;
+		d->filename = d1->filename;
+	} else {
+		d->max = NR_INLINE_DENTRY;
+		d->bitmap = &d2->dentry_bitmap;
+		d->dentry = d2->dentry;
+		d->filename = d2->filename;
+	}
+}
+
 /*
  * XATTR_NODE_OFFSET stores xattrs to one node block per file keeping -1
  * as its node offset to distinguish from index node blocks.
@@ -1245,11 +1270,10 @@ struct dentry *f2fs_get_parent(struct dentry *child);
  */
 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 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);
 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 403c8f7..edacfa1 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -265,8 +265,8 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
 	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
 	struct f2fs_inline_dentry *inline_dentry;
 	struct f2fs_dir_entry *de;
+	struct f2fs_dentry_ptr d;
 	struct page *ipage;
-	int max_slots = NR_INLINE_DENTRY;
 
 	ipage = get_node_page(sbi, dir->i_ino);
 	if (IS_ERR(ipage))
@@ -274,9 +274,9 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
 
 	inline_dentry = inline_data_addr(ipage);
 
-	de = find_target_dentry(name, &max_slots, &inline_dentry->dentry_bitmap,
-						inline_dentry->dentry,
-						inline_dentry->filename);
+	make_dentry_ptr(&d, NULL, inline_dentry, 2);
+	de = find_target_dentry(name, NULL, &d);
+
 	unlock_page(ipage);
 	if (de)
 		*res_page = ipage;
@@ -287,7 +287,7 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
 	 * 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(sbi, max_slots < 0);
+	f2fs_bug_on(sbi, d.max < 0);
 	return de;
 }
 
@@ -521,6 +521,7 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx)
 	struct inode *inode = file_inode(file);
 	struct f2fs_inline_dentry *inline_dentry = NULL;
 	struct page *ipage = NULL;
+	struct f2fs_dentry_ptr d;
 
 	if (ctx->pos == NR_INLINE_DENTRY)
 		return 0;
@@ -531,10 +532,9 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx)
 
 	inline_dentry = inline_data_addr(ipage);
 
-	if (!f2fs_fill_dentries(ctx, &inline_dentry->dentry_bitmap,
-				inline_dentry->dentry,
-				inline_dentry->filename,
-				NR_INLINE_DENTRY, 0))
+	make_dentry_ptr(&d, NULL, inline_dentry, 2);
+
+	if (!f2fs_fill_dentries(ctx, &d, 0))
 		ctx->pos = NR_INLINE_DENTRY;
 
 	f2fs_put_page(ipage, 1);
-- 
2.1.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 10/11] f2fs: reuse make_empty_dir code for inline_dentry
  2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
                   ` (7 preceding siblings ...)
  2014-10-20  5:19 ` [PATCH 09/11] f2fs: introduce f2fs_dentry_ptr structure for code clean-up Jaegeuk Kim
@ 2014-10-20  5:19 ` Jaegeuk Kim
  2014-10-20  5:19 ` [PATCH 11/11] f2fs: use kmap_atomic instead of kmap Jaegeuk Kim
  9 siblings, 0 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch introduces do_make_empty_dir to mitigate code redundancy
for inline_dentry.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 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


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 11/11] f2fs: use kmap_atomic instead of kmap
  2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
                   ` (8 preceding siblings ...)
  2014-10-20  5:19 ` [PATCH 10/11] f2fs: reuse make_empty_dir code for inline_dentry Jaegeuk Kim
@ 2014-10-20  5:19 ` Jaegeuk Kim
  9 siblings, 0 replies; 11+ messages in thread
From: Jaegeuk Kim @ 2014-10-20  5:19 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

For better performance, we need to use kmap_atomic instead of kmap.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 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


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-10-20  5:22 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-20  5:19 [PATCH 01/11] f2fs: reuse room_for_filename for inline dentry operation Jaegeuk Kim
2014-10-20  5:19 ` [PATCH 02/11] f2fs: reuse find_in_block code for find_in_inline_dir Jaegeuk Kim
2014-10-20  5:19 ` [PATCH 03/11] f2fs: fix to wait correct block type Jaegeuk Kim
2014-10-20  5:19 ` [PATCH 04/11] f2fs: avoid deadlock on init_inode_metadata Jaegeuk Kim
2014-10-20  5:19 ` [PATCH 05/11] f2fs: add stat info for inline_dentry inodes Jaegeuk Kim
2014-10-20  5:19 ` [PATCH 06/11] f2fs: fix counting inline_data inode numbers Jaegeuk Kim
2014-10-20  5:19 ` [PATCH 07/11] f2fs: reuse core function in f2fs_readdir for inline_dentry Jaegeuk Kim
2014-10-20  5:19 ` [PATCH 08/11] f2fs: should not truncate any inline_dentry Jaegeuk Kim
2014-10-20  5:19 ` [PATCH 09/11] f2fs: introduce f2fs_dentry_ptr structure for code clean-up Jaegeuk Kim
2014-10-20  5:19 ` [PATCH 10/11] f2fs: reuse make_empty_dir code for inline_dentry Jaegeuk Kim
2014-10-20  5:19 ` [PATCH 11/11] f2fs: use kmap_atomic instead of kmap 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).