All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data
@ 2012-07-31 11:47 Zheng Liu
  2012-07-31 11:47 ` [PATCH 01/36 v4] libext2fs: add EXT4_FEATURE_INCOMPAT_INLINE_DATA flag Zheng Liu
                   ` (36 more replies)
  0 siblings, 37 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:47 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

Hi list,

Here is v4 for making e2fsprogs support inline data.  In this patch set, the
major difference is that we can set inline_data feature when ext_attr enabled
in tune2fs.  We cannot clear inline_data feature because, when clearing this
feature, we need to allocate some blocks for inode which contains inline data,
and it may exhaust all of disk space.  Another modification is that
EXT4_INLINE_DATA_FL is set to 0x10000000 because the old value conflicts with
FS_NOCOW_FL in btrfs.

v3->v4:
* [tune2fs] add inline data support
* [libext2fs] set EXT4_INLINE_DATA_FL to 0x1000000

v2->v3:
* [mke2fs] EXT4_FEATURE_INCOMPAT_INLINE_DATA is set back to 0x8000
* [mke2fs] enable inline_data on ext4dev filesystem
* [tests] modify a regression test in tests
* rebase to the latest pu branch of e2fsprogs
* fix some bugs

v1->v2:
* [mke2fs] automatically set EXT_ATTR feature when INLINE_DATA is set
* [debugfs] supports read-write mode

Regards,
Zheng

Zheng Liu (36):
      libext2fs: add EXT4_FEATURE_INCOMPAT_INLINE_DATA flag
      mke2fs: make it support inline data feature
      mke2fs: add inline_data feature in mke2fs's manpage
      libext2fs: add ext2fs_find_entry_ext_attr function
      libext2fs: add EXT4_INLINE_DATA_FL flag for inode
      libext2fs: add data structures for inline data feature
      libext2fs: add inline_data file
      debugfs: make ncheck cmd support inline data
      debugfs: make icheck cmd support inline data
      debugfs: make chroot and cd cmd support inline data
      debugfs: make ls cmd support inline data
      debugfs: make stat cmd support inline data
      debugfs: make blocks cmd support inline data
      debugfs: make filefrag cmd support inline data
      debugfs: make link cmd support inline data
      debugfs: make unlink cmd support inline data
      debugfs: make mkdir cmd support inline data
      debugfs: make rmdir cmd support inline data
      debugfs: make rm and kill_file cmd support inline data
      debugfs: make pwd cmd support inline data
      debugfs: make expand_dir cmd support inline data
      debugfs: make lsdel cmd support inline data
      debugfs: make undelete cmd support inline data
      debugfs: make dump and cat cmd support inline data
      debugfs: make rdump cmd support inline data
      debugfs: make dirsearch cmd support inline data
      debugfs: make bmap cmd support inline data
      debugfs: make punch/truncate cmd support inline data
      e2fsck: add three problem descriptions in pass1
      e2fsck: check incorrect inline data flag
      e2fsck: make pass1 support inline data
      libext2fs: add read/write inline data functions
      e2fsck: check inline data in pass2
      mke2fs: add inline_data feature into ext4dev
      tests: change test f_bad_disconnected_inode to support inline_data feature
      tune2fs: set inline_data feature

 debugfs/debugfs.c                       |   25 +-
 debugfs/dump.c                          |   38 ++-
 debugfs/filefrag.c                      |   30 +-
 debugfs/htree.c                         |    6 +
 debugfs/icheck.c                        |    9 +-
 debugfs/ls.c                            |    8 +-
 debugfs/lsdel.c                         |   19 +-
 debugfs/ncheck.c                        |    8 +-
 e2fsck/pass1.c                          |  109 +++++-
 e2fsck/pass1b.c                         |    5 +-
 e2fsck/pass2.c                          |   64 +++-
 e2fsck/problem.c                        |   15 +
 e2fsck/problem.h                        |    9 +
 lib/e2p/feature.c                       |    2 +-
 lib/ext2fs/Makefile.in                  |    5 +
 lib/ext2fs/Makefile.pq                  |    1 +
 lib/ext2fs/bmap.c                       |   16 +
 lib/ext2fs/dblist_dir.c                 |    8 +-
 lib/ext2fs/dirblock.c                   |   62 +++
 lib/ext2fs/expanddir.c                  |    8 +-
 lib/ext2fs/ext2_ext_attr.h              |    4 +
 lib/ext2fs/ext2_fs.h                    |   10 +-
 lib/ext2fs/ext2fs.h                     |   74 +++-
 lib/ext2fs/ext_attr.c                   |   26 ++
 lib/ext2fs/get_pathname.c               |    7 +-
 lib/ext2fs/inline_data.c                |  724 +++++++++++++++++++++++++++++++
 lib/ext2fs/link.c                       |    9 +-
 lib/ext2fs/lookup.c                     |    6 +-
 lib/ext2fs/mkdir.c                      |   33 ++-
 lib/ext2fs/punch.c                      |   33 ++-
 lib/ext2fs/unlink.c                     |    9 +-
 misc/mke2fs.8.in                        |    3 +
 misc/mke2fs.c                           |   10 +-
 misc/mke2fs.conf.in                     |    2 +-
 misc/tune2fs.8.in                       |    5 +
 misc/tune2fs.c                          |   15 +-
 tests/f_bad_disconnected_inode/expect.1 |   27 +-
 37 files changed, 1348 insertions(+), 96 deletions(-)

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

* [PATCH 01/36 v4] libext2fs: add EXT4_FEATURE_INCOMPAT_INLINE_DATA flag
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
@ 2012-07-31 11:47 ` Zheng Liu
  2012-07-31 11:47 ` [PATCH 02/36 v4] mke2fs: make it support inline data feature Zheng Liu
                   ` (35 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:47 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Add EXT4_FEATURE_INCOMPAT_INLINE_DATA flag to support inline
data feature.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/e2p/feature.c    |    2 +-
 lib/ext2fs/ext2_fs.h |    2 +-
 lib/ext2fs/ext2fs.h  |    6 ++++--
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c
index 8ac4f3f..70815ef 100644
--- a/lib/e2p/feature.c
+++ b/lib/e2p/feature.c
@@ -93,7 +93,7 @@ static struct feature feature_list[] = {
 			"dirdata"},
 	{       E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_LARGEDIR,
 			"large_dir"},
-	{       E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_INLINEDATA,
+	{       E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_INLINE_DATA,
 			"inline_data"},
 	{	0, 0, 0 },
 };
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index 4093d5b..c6de26a 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -750,7 +750,7 @@ struct ext2_super_block {
 #define EXT4_FEATURE_INCOMPAT_DIRDATA		0x1000
 /* 0x2000 was EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM but this was never used */
 #define EXT4_FEATURE_INCOMPAT_LARGEDIR		0x4000 /* >2GB or 3-lvl htree */
-#define EXT4_FEATURE_INCOMPAT_INLINEDATA	0x8000 /* data in inode */
+#define EXT4_FEATURE_INCOMPAT_INLINE_DATA	0x8000 /* data in inode */
 
 #define EXT2_FEATURE_COMPAT_SUPP	0
 #define EXT2_FEATURE_INCOMPAT_SUPP    (EXT2_FEATURE_INCOMPAT_FILETYPE| \
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 02e1b4e..65d30de 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -566,7 +566,8 @@ typedef struct ext2_icount *ext2_icount_t;
 					 EXT3_FEATURE_INCOMPAT_EXTENTS|\
 					 EXT4_FEATURE_INCOMPAT_FLEX_BG|\
 					 EXT4_FEATURE_INCOMPAT_MMP|\
-					 EXT4_FEATURE_INCOMPAT_64BIT)
+					 EXT4_FEATURE_INCOMPAT_64BIT|\
+					 EXT4_FEATURE_INCOMPAT_INLINE_DATA)
 #else
 #define EXT2_LIB_FEATURE_INCOMPAT_SUPP	(EXT2_FEATURE_INCOMPAT_FILETYPE|\
 					 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
@@ -575,7 +576,8 @@ typedef struct ext2_icount *ext2_icount_t;
 					 EXT3_FEATURE_INCOMPAT_EXTENTS|\
 					 EXT4_FEATURE_INCOMPAT_FLEX_BG|\
 					 EXT4_FEATURE_INCOMPAT_MMP|\
-					 EXT4_FEATURE_INCOMPAT_64BIT)
+					 EXT4_FEATURE_INCOMPAT_64BIT|\
+					 EXT4_FEATURE_INCOMPAT_INLINE_DATA)
 #endif
 #ifdef CONFIG_QUOTA
 #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
-- 
1.7.4.1


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

* [PATCH 02/36 v4] mke2fs: make it support inline data feature
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
  2012-07-31 11:47 ` [PATCH 01/36 v4] libext2fs: add EXT4_FEATURE_INCOMPAT_INLINE_DATA flag Zheng Liu
@ 2012-07-31 11:47 ` Zheng Liu
  2012-07-31 11:47 ` [PATCH 03/36 v4] mke2fs: add inline_data feature in mke2fs's manpage Zheng Liu
                   ` (34 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:47 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

EXT2_FEATURE_COMPAT_EXT_ATTR flag will be set when inline_data is set
because inline data feature depends on it.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 misc/mke2fs.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 9564e81..13c3634 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -883,7 +883,8 @@ static __u32 ok_features[3] = {
 		EXT2_FEATURE_INCOMPAT_META_BG|
 		EXT4_FEATURE_INCOMPAT_FLEX_BG|
 		EXT4_FEATURE_INCOMPAT_MMP |
-		EXT4_FEATURE_INCOMPAT_64BIT,
+		EXT4_FEATURE_INCOMPAT_64BIT|
+		EXT4_FEATURE_INCOMPAT_INLINE_DATA,
 	/* R/O compat */
 	EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
 		EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -1956,6 +1957,13 @@ profile_error:
 		exit(1);
 	}
 
+	/* if inline_data is set, ext_attr would be set because inline_data
+	 * depends on it.
+	 */
+	if ((fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_INLINE_DATA) &&
+	    !(fs_param.s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR))
+		fs_param.s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
+
 	if (fs_param.s_blocks_per_group) {
 		if (fs_param.s_blocks_per_group < 256 ||
 		    fs_param.s_blocks_per_group > 8 * (unsigned) blocksize) {
-- 
1.7.4.1


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

* [PATCH 03/36 v4] mke2fs: add inline_data feature in mke2fs's manpage
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
  2012-07-31 11:47 ` [PATCH 01/36 v4] libext2fs: add EXT4_FEATURE_INCOMPAT_INLINE_DATA flag Zheng Liu
  2012-07-31 11:47 ` [PATCH 02/36 v4] mke2fs: make it support inline data feature Zheng Liu
@ 2012-07-31 11:47 ` Zheng Liu
  2012-07-31 11:47 ` [PATCH 04/36 v4] libext2fs: add ext2fs_find_entry_ext_attr function Zheng Liu
                   ` (33 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:47 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Update mke2fs's manpage.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 misc/mke2fs.8.in |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in
index 6d443a2..bfe6c94 100644
--- a/misc/mke2fs.8.in
+++ b/misc/mke2fs.8.in
@@ -551,6 +551,9 @@ option).
 @JDEV@must be created with the same
 @JDEV@block size as the filesystems that will be using it.
 .TP
+.B inline_data
+Allow data to be stored in inode
+.TP
 .B large_file
 Filesystem can contain files that are greater than 2GB.  (Modern kernels
 set this feature automatically when a file > 2GB is created.)
-- 
1.7.4.1


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

* [PATCH 04/36 v4] libext2fs: add ext2fs_find_entry_ext_attr function
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (2 preceding siblings ...)
  2012-07-31 11:47 ` [PATCH 03/36 v4] mke2fs: add inline_data feature in mke2fs's manpage Zheng Liu
@ 2012-07-31 11:47 ` Zheng Liu
  2012-07-31 11:47 ` [PATCH 05/36 v4] libext2fs: add EXT4_INLINE_DATA_FL flag for inode Zheng Liu
                   ` (32 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:47 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

We need to search extend attributes to get entry of inline data.
Thus, add this function to do this work.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/ext2fs.h   |    4 ++++
 lib/ext2fs/ext_attr.c |   26 ++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 65d30de..fd051b1 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1136,6 +1136,10 @@ extern errcode_t ext2fs_adjust_ea_refcount3(ext2_filsys fs, blk64_t blk,
 					   char *block_buf,
 					   int adjust, __u32 *newcount,
 					   ext2_ino_t inum);
+extern errcode_t ext2fs_find_entry_ext_attr(struct ext2_ext_attr_entry **pentry,
+					    int name_index, const char *name,
+					    size_t size, int sorted);
+ 
 
 /* extent.c */
 extern errcode_t ext2fs_extent_header_verify(void *ptr, int size);
diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c
index 9649a14..b2d36b6 100644
--- a/lib/ext2fs/ext_attr.c
+++ b/lib/ext2fs/ext_attr.c
@@ -171,6 +171,32 @@ errout:
 	return retval;
 }
 
+errcode_t ext2fs_find_entry_ext_attr(struct ext2_ext_attr_entry **pentry,
+				     int name_index, const char *name,
+				     size_t size, int sorted)
+{
+	struct ext2_ext_attr_entry *entry;
+	size_t name_len;
+	int cmp;
+
+	if (name == NULL)
+		return -1;
+	name_len = strlen(name);
+	entry = *pentry;
+	for (; !EXT2_EXT_IS_LAST_ENTRY(entry); entry = EXT2_EXT_ATTR_NEXT(entry)) {
+		cmp = name_index - entry->e_name_index;
+		if (!cmp)
+			cmp = name_len - entry->e_name_len;
+		if (!cmp)
+			cmp = memcmp(name, EXT2_EXT_ATTR_NAME(entry), name_len);
+		if (!cmp)
+			break;
+	}
+	*pentry = entry;
+
+	return cmp;
+}
+
 errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk,
 				    char *block_buf, int adjust,
 				    __u32 *newcount)
-- 
1.7.4.1


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

* [PATCH 05/36 v4] libext2fs: add EXT4_INLINE_DATA_FL flag for inode
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (3 preceding siblings ...)
  2012-07-31 11:47 ` [PATCH 04/36 v4] libext2fs: add ext2fs_find_entry_ext_attr function Zheng Liu
@ 2012-07-31 11:47 ` Zheng Liu
  2012-08-07 18:27   ` Theodore Ts'o
  2012-07-31 11:47 ` [PATCH 06/36 v4] libext2fs: add data structures for inline data feature Zheng Liu
                   ` (31 subsequent siblings)
  36 siblings, 1 reply; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:47 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Add EXT4_INLINE_DATA_FL flag.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/ext2_fs.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index c6de26a..6688763 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -318,6 +318,7 @@ struct ext2_dx_tail {
 #define EXT4_SNAPFILE_FL		0x01000000  /* Inode is a snapshot */
 #define EXT4_SNAPFILE_DELETED_FL	0x04000000  /* Snapshot is being deleted */
 #define EXT4_SNAPFILE_SHRUNK_FL		0x08000000  /* Snapshot shrink has completed */
+#define EXT4_INLINE_DATA_FL		0x10000000 /* Inode has inline data */
 #define EXT2_RESERVED_FL		0x80000000 /* reserved for ext2 lib */
 
 #define EXT2_FL_USER_VISIBLE		0x004BDFFF /* User visible flags */
-- 
1.7.4.1


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

* [PATCH 06/36 v4] libext2fs: add data structures for inline data feature
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (4 preceding siblings ...)
  2012-07-31 11:47 ` [PATCH 05/36 v4] libext2fs: add EXT4_INLINE_DATA_FL flag for inode Zheng Liu
@ 2012-07-31 11:47 ` Zheng Liu
  2012-08-07 18:50   ` Theodore Ts'o
  2012-07-31 11:48 ` [PATCH 07/36 v4] libext2fs: add inline_data file Zheng Liu
                   ` (30 subsequent siblings)
  36 siblings, 1 reply; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:47 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Add ext2_ext_attr_ibody_heaer to check extend attribute.  Add inline_data
to indicate the position of inline data in extend attribute and the size
of inline data.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/ext2_ext_attr.h |    4 ++++
 lib/ext2fs/ext2_fs.h       |    7 +++++++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/lib/ext2fs/ext2_ext_attr.h b/lib/ext2fs/ext2_ext_attr.h
index bbb0aaa..5c7c715 100644
--- a/lib/ext2fs/ext2_ext_attr.h
+++ b/lib/ext2fs/ext2_ext_attr.h
@@ -25,6 +25,10 @@ struct ext2_ext_attr_header {
 	__u32	h_reserved[3];	/* zero right now */
 };
 
+struct ext2_ext_attr_ibody_header {
+	__u32	h_magic;
+};
+
 struct ext2_ext_attr_entry {
 	__u8	e_name_len;	/* length of name */
 	__u8	e_name_index;	/* attribute name index */
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index aa3e808..7e05183 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -904,4 +904,11 @@ struct mmp_struct {
  */
 #define EXT4_MMP_MIN_CHECK_INTERVAL     5
 
+struct inline_data {
+	__u16	inline_off;
+	__u16	inline_size;
+};
+
+#define EXT4_MIN_INLINE_DATA_SIZE	((sizeof(__u32) * EXT2_N_BLOCKS))
+
 #endif	/* _LINUX_EXT2_FS_H */
-- 
1.7.4.1


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

* [PATCH 07/36 v4] libext2fs: add inline_data file
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (5 preceding siblings ...)
  2012-07-31 11:47 ` [PATCH 06/36 v4] libext2fs: add data structures for inline data feature Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-08-07 18:40   ` Theodore Ts'o
  2012-07-31 11:48 ` [PATCH 08/36 v4] debugfs: make ncheck cmd support inline data Zheng Liu
                   ` (29 subsequent siblings)
  36 siblings, 1 reply; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

inline_data.c file is created to implement related functions to
support inline_data feature.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/Makefile.in   |    5 +
 lib/ext2fs/Makefile.pq   |    1 +
 lib/ext2fs/ext2fs.h      |   57 ++++
 lib/ext2fs/inline_data.c |  724 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 787 insertions(+), 0 deletions(-)
 create mode 100644 lib/ext2fs/inline_data.c

diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index f9200fa..5b4ec15 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -58,6 +58,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
 	ind_block.o \
 	initialize.o \
 	inline.o \
+	inline_data.o \
 	inode.o \
 	io_manager.o \
 	ismounted.o \
@@ -130,6 +131,7 @@ SRCS= ext2_err.c \
 	$(srcdir)/ind_block.c \
 	$(srcdir)/initialize.c \
 	$(srcdir)/inline.c \
+	$(srcdir)/inline_data.c \
 	$(srcdir)/inode.c \
 	$(srcdir)/inode_io.c \
 	$(srcdir)/imager.c \
@@ -734,6 +736,9 @@ inline.o: $(srcdir)/inline.c $(top_builddir)/lib/config.h \
  $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
  $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
  $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
+inline_data.o: $(srcdir)/inline_data.c $(top_builddir)/lib/config.h \
+ $(srcdir)/ext2_fs.h $(srcdir)/ext2fs.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/ext2fsP.h
 inode.o: $(srcdir)/inode.c $(top_builddir)/lib/config.h \
  $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \
  $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
diff --git a/lib/ext2fs/Makefile.pq b/lib/ext2fs/Makefile.pq
index 2f7b654..89082a7 100644
--- a/lib/ext2fs/Makefile.pq
+++ b/lib/ext2fs/Makefile.pq
@@ -27,6 +27,7 @@ OBJS= 	alloc.obj \
 	icount.obj \
 	initialize.obj \
 	inline.obj \
+	inline_data.obj \
 	inode.obj \
 	ismounted.obj \
 	link.obj \
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index fd051b1..bacc14d 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1329,6 +1329,63 @@ extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
 extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
 errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
 
+/* inline_data.c */
+extern errcode_t ext2fs_inline_data_iterate(ext2_filsys fs,
+                                            ext2_ino_t ino,
+                                            int flags,
+                                            char *block_buf,
+                                            int (*func)(struct ext2_dir_entry *dirent,
+                                                        int offset,
+                                                        int blocksize,
+                                                        char *buf,
+                                                        void *priv_data),
+                                            void *priv_data);
+extern errcode_t ext2fs_inline_data_iterate2(ext2_filsys fs,
+                                             ext2_ino_t ino,
+                                             int flags,
+                                             char *block_buf,
+                                             int (*func)(ext2_ino_t ino,
+                                                         int entry,
+                                                         struct ext2_dir_entry *dirent,
+                                                         int offset,
+                                                         int blocksize,
+                                                         char *buf,
+                                                         void *priv_data),
+                                             void *priv_data);
+extern errcode_t ext2fs_inline_data_iterate3(ext2_filsys fs,
+                                             ext2_ino_t ino,
+                                             int flags,
+                                             char *block_buf,
+                                             const char *name,
+                                             int namelen,
+                                             int (*func)(struct ext2_dir_entry *dirent,
+                                                         int offset,
+                                                         int blocksize,
+                                                         char *buf,
+                                                         void *priv_data),
+                                             void *priv_data);
+extern errcode_t ext2fs_inline_data_search_dir(ext2_filsys fs, ext2_ino_t ino,
+                                               char *search_name, int len);
+extern errcode_t ext2fs_inline_data_expand_dir(ext2_filsys fs, ext2_ino_t ino,
+                                               int flags, char *block_buf,
+                                               int (*func)(ext2_filsys fs,
+                                                           blk64_t *blocknr,
+                                                           e2_blkcnt_t blockcnt,
+                                                           blk64_t ref_blk,
+                                                           int ref_offset,
+                                                           void *priv_data),
+                                               void *priv_data);
+extern void *ext2fs_get_inline_xattr_pos(struct ext2_inode_large *inode,
+                                  struct inline_data *idata);
+extern void ext2fs_iget_extra_inode(ext2_filsys fs, struct ext2_inode_large *inode,
+                                    struct inline_data *idata);
+extern int ext2fs_has_inline_data(ext2_filsys fs, ext2_ino_t ino);
+extern int ext2fs_inline_data_in_extra(ext2_filsys fs, ext2_ino_t ino);
+extern int ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino);
+extern int inline_data_destory_data(ext2_filsys fs, ext2_ino_t ino,
+				    struct ext2_inode_large *inode,
+				    struct inline_data *idata);
+
 /* inode.c */
 extern errcode_t ext2fs_flush_icache(ext2_filsys fs);
 extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan,
diff --git a/lib/ext2fs/inline_data.c b/lib/ext2fs/inline_data.c
new file mode 100644
index 0000000..59483a6
--- /dev/null
+++ b/lib/ext2fs/inline_data.c
@@ -0,0 +1,724 @@
+/*
+ * inline_data.c --- data in inode
+ *
+ * Copyright (C) 2012 Zheng Liu <wenqing.lz@taobao.com>
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Library
+ * General Public License, version 2.
+ * %End-Header%
+ */
+
+#include "config.h"
+#include <stdio.h>
+
+#include "ext2_fs.h"
+#include "ext2_ext_attr.h"
+
+#include "ext2fs.h"
+#include "ext2fsP.h"
+
+#define EXT4_XATTR_SYSTEM_DATA_INDEX	7
+#define EXT4_XATTR_SYSTEM_DATA_NAME 	"data"
+
+struct inline_data_context {
+	ext2_ino_t	ino;
+	int		flags;
+	char		*buf;
+	int (*func)(ext2_ino_t ino,
+		    int entry,
+		    struct ext2_dir_entry *dirent,
+		    int offset,
+		    int blocksize,
+		    char *buf,
+		    void *priv_data);
+	void		*priv_data;
+	errcode_t	errcode;
+};
+
+static void inline_data_update_dir_entry(ext2_filsys fs, void *de_buf,
+					 int old_size, int new_size)
+{
+	struct ext2_dir_entry *entry, *prev;
+	void *limit;
+	unsigned int de_len;
+
+	entry = (struct ext2_dir_entry *)de_buf;
+	limit = de_buf + old_size;
+	do {
+		prev = entry;
+		ext2fs_get_rec_len(fs, entry, &de_len);
+		de_buf += de_len;
+		entry = (struct ext2_dir_entry *)de_buf;
+	} while (de_buf < limit);
+
+	ext2fs_set_rec_len(fs, de_len  + new_size - old_size, prev);
+}
+
+int inline_data_destory_data(ext2_filsys fs, ext2_ino_t ino,
+			     struct ext2_inode_large *inode,
+			     struct inline_data *idata)
+{
+	struct ext2_ext_attr_entry *entry;
+	errcode_t retval;
+	char *start, *end;
+	int cmp;
+	__u32 *magic;
+
+	if (!idata->inline_off)
+		return 0;
+
+	if (inode->i_extra_isize > (EXT2_INODE_SIZE(fs->super) -
+				   EXT2_GOOD_OLD_INODE_SIZE)) {
+		fprintf(stderr, "invalid inode->i_extra_isize (%u)\n",
+			inode->i_extra_isize);
+		return -1;
+	}
+
+	magic = (__u32*)((char *)inode + EXT2_GOOD_OLD_INODE_SIZE +
+			 inode->i_extra_isize);
+	start = (char *)magic + sizeof(__u32);
+	end = (char *)inode + EXT2_INODE_SIZE(fs->super);
+	entry = (struct ext2_ext_attr_entry *)start;
+
+	cmp = ext2fs_find_entry_ext_attr(&entry, EXT4_XATTR_SYSTEM_DATA_INDEX,
+					 EXT4_XATTR_SYSTEM_DATA_NAME,
+					 end - start, 0);
+
+	if (!cmp) {
+		entry->e_value_offs = 0;
+		entry->e_value_block = 0;
+		entry->e_value_size = 0;
+	}
+
+	memset((void *)inode->i_block, 0, EXT4_MIN_INLINE_DATA_SIZE);
+
+	return 0;
+}
+
+static int inline_data_search_dir(ext2_filsys fs,
+				  struct ext2_inode_large *inode,
+				  char *start,
+				  int size,
+				  void *priv_data)
+{
+	struct inline_data_context *ctx;
+	struct ext2_dir_entry *dirent;
+	unsigned int rec_len;
+	unsigned int offset = 0;
+	char *dlimit;
+	int ret;
+	int do_abort = 0;
+	int changed = 0;
+
+	ctx = (struct inline_data_context *)priv_data;
+
+	dirent = (struct ext2_dir_entry *)start;
+	dlimit = start + size;
+
+	while ((char *)dirent < dlimit) {
+		if (ext2fs_get_rec_len(fs, dirent, &rec_len))
+			return BLOCK_ABORT;
+		if (!dirent->inode &&
+		    !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
+			goto next;
+		ret = (ctx->func)(ctx->ino, 0, dirent,
+				  offset, size, start,
+				  ctx->priv_data);
+
+		if (ret & DIRENT_CHANGED) {
+			if (ext2fs_get_rec_len(fs, dirent, &rec_len))
+				return BLOCK_ABORT;
+			changed++;
+		}
+
+		if (ret & DIRENT_ABORT)
+			do_abort++;
+
+next:
+		dirent = (struct ext2_dir_entry *)((char *)dirent + rec_len);
+		offset += rec_len;
+	}
+
+	if (changed) {
+		ctx->errcode = ext2fs_write_inode_full(fs, ctx->ino, (void *)inode,
+						       EXT2_INODE_SIZE(fs->super));
+		if (ctx->errcode)
+			return BLOCK_ABORT;
+	}
+
+	if (do_abort)
+		return BLOCK_ABORT;
+
+	return 0;
+}
+
+static int inline_data_search_dir2(ext2_filsys fs, char *start, int size,
+				   char *search_name, int len)
+{
+	struct ext2_dir_entry *dirent;
+	unsigned int rec_len;
+	char *dlimit;
+	int ret;
+	int do_abort = 0;
+
+	dirent = (struct ext2_dir_entry *)start;
+	dlimit = start + size;
+
+	while ((char *)dirent < dlimit) {
+		if (ext2fs_get_rec_len(fs, dirent, &rec_len))
+			return BLOCK_ABORT;
+		if (dirent->inode &&
+		    len == (dirent->name_len & 0xFF) &&
+		    strncmp(search_name, dirent->name, len) == 0) {
+			printf("Entry found at inline data\n");
+			break;
+		}
+		dirent = (struct ext2_dir_entry *)((char *)dirent + rec_len);
+	}
+
+	return 0;
+}
+
+void *ext2fs_get_inline_xattr_pos(struct ext2_inode_large *inode,
+				  struct inline_data *idata)
+{
+	struct ext2_ext_attr_entry *entry;
+	struct ext2_ext_attr_ibody_header *header;
+
+	header = (struct ext2_ext_attr_ibody_header *)
+			((void *)inode +
+			EXT2_GOOD_OLD_INODE_SIZE +
+			inode->i_extra_isize);
+	entry = (struct ext2_ext_attr_entry *)
+			((void *)inode + idata->inline_off);
+
+	return (void *)((struct ext2_ext_attr_header *)((header) + 1)) +
+			entry->e_value_offs;
+}
+
+void ext2fs_iget_extra_inode(ext2_filsys fs, struct ext2_inode_large *inode,
+			     struct inline_data *idata)
+{
+	struct ext2_ext_attr_entry *entry;
+	char *start, *end;
+	int cmp;
+	__u32 *magic;
+
+	idata->inline_off = 0;
+	if (inode->i_extra_isize > (EXT2_INODE_SIZE(fs->super) -
+				   EXT2_GOOD_OLD_INODE_SIZE)) {
+		fprintf(stderr, "invalid inode->i_extra_isize (%u)\n",
+			inode->i_extra_isize);
+		return;
+	}
+
+	magic = (__u32*)((char *)inode + EXT2_GOOD_OLD_INODE_SIZE +
+			 inode->i_extra_isize);
+	if (*magic == EXT2_EXT_ATTR_MAGIC) {
+		end = (char *)inode + EXT2_INODE_SIZE(fs->super);
+		start = (char *)magic + sizeof(__u32);
+		entry = (struct ext2_ext_attr_entry *)start;
+
+		cmp = ext2fs_find_entry_ext_attr(&entry, EXT4_XATTR_SYSTEM_DATA_INDEX,
+						 EXT4_XATTR_SYSTEM_DATA_NAME,
+						 end - start, 0);
+		if (!cmp) {
+			idata->inline_off = (__u16)((void *)entry -
+						    (void *)inode);
+			idata->inline_size = EXT4_MIN_INLINE_DATA_SIZE +
+					     entry->e_value_size;
+		}
+	}
+}
+
+int ext2fs_has_inline_data(ext2_filsys fs, ext2_ino_t ino)
+{
+	struct ext2_inode *inode;
+	errcode_t retval;
+	__u32 flags;
+
+	retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+	if (retval)
+		return 0;
+
+	retval = ext2fs_read_inode_full(fs, ino, inode,
+					EXT2_INODE_SIZE(fs->super));
+	if (retval)
+		return 0;
+
+	flags = inode->i_flags;
+	ext2fs_free_mem(&inode);
+
+	return (flags & EXT4_INLINE_DATA_FL);
+}
+
+struct xlate {
+	int (*func)(struct ext2_dir_entry *dirent,
+		    int offset,
+		    int blocksize,
+		    char *buf,
+		    void *priv_data);
+	void *real_private;
+};
+
+static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
+		      int entry EXT2FS_ATTR((unused)),
+		      struct ext2_dir_entry *dirent, int offset,
+		      int blocksize, char *buf, void *priv_data)
+{
+	struct xlate *xl = (struct xlate *)priv_data;
+
+	return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
+}
+
+errcode_t ext2fs_inline_data_iterate(ext2_filsys fs,
+				     ext2_ino_t ino,
+				     int flags,
+				     char *block_buf,
+				     int (*func)(struct ext2_dir_entry *dirent,
+						 int offset,
+						 int blocksize,
+						 char *buf,
+						 void *priv_data),
+				     void *priv_data)
+{
+	struct xlate xl;
+
+	xl.real_private = priv_data;
+	xl.func = func;
+
+	return ext2fs_inline_data_iterate2(fs, ino, flags, block_buf,
+					   xlate_func, &xl);
+}
+
+errcode_t ext2fs_inline_data_iterate2(ext2_filsys fs,
+				      ext2_ino_t ino, int flags, char *block_buf,
+				      int (*func)(ext2_ino_t ino,
+						  int entry,
+						  struct ext2_dir_entry *dirent,
+						  int offset,
+						  int blocksize,
+						  char *buf,
+						  void *priv_data),
+				      void *priv_data)
+{
+	struct inline_data_context ctx;
+	struct ext2_inode_large *inode;
+	struct inline_data idata;
+	errcode_t retval;
+	blk64_t blk64;
+	void *inline_start;
+	int inline_size;
+	int i, limit, r;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	retval = ext2fs_check_directory(fs, ino);
+	if (retval)
+		return retval;
+
+	retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+	if (retval)
+		return retval;
+	retval = ext2fs_read_inode_full(fs, ino, (void *)inode,
+					EXT2_INODE_SIZE(fs->super));
+	if (retval) {
+		ext2fs_free_mem(&inode);
+		return retval;
+	}
+
+	if (inode->i_size == 0)
+		goto out;
+
+	ctx.ino = ino;
+	ctx.flags = flags;
+	ctx.buf = block_buf;
+	ctx.func = func;
+	ctx.priv_data = priv_data;
+	ctx.errcode = 0;
+
+	inline_start = inode->i_block;
+	inline_size = EXT4_MIN_INLINE_DATA_SIZE;
+	retval = inline_data_search_dir(fs, inode, inline_start, inline_size, &ctx);
+	if (retval)
+		goto out;
+
+	ext2fs_iget_extra_inode(fs, inode, &idata);
+	if (idata.inline_size > EXT4_MIN_INLINE_DATA_SIZE) {
+		inline_start = ext2fs_get_inline_xattr_pos(inode, &idata);
+		inline_size = idata.inline_size - EXT4_MIN_INLINE_DATA_SIZE;
+		retval = inline_data_search_dir(fs, inode, inline_start, inline_size, &ctx);
+	}
+
+out:
+	ext2fs_free_mem(&inode);
+	return retval & BLOCK_ABORT ? 0 : retval;
+}
+
+errcode_t ext2fs_inline_data_iterate3(ext2_filsys fs,
+				      ext2_ino_t ino,
+				      int flags,
+				      char *block_buf,
+				      const char *name,
+				      int namelen,
+				      int (*func)(struct ext2_dir_entry *dirent,
+						  int offset,
+						  int blocksize,
+						  char *buf,
+						  void *priv_data),
+				      void *priv_data)
+{
+	struct xlate xl;
+	struct inline_data_context ctx;
+	struct ext2_inode_large *inode;
+	struct inline_data idata;
+	struct ext2_dir_entry_tail *t;
+	ext2_extent_handle_t handle;
+	errcode_t retval;
+	blk64_t blk;
+	void *inline_start;
+	char *backup_buf;
+	char *blk_buf;
+	int inline_size;
+	int i, limit, r;
+	int csum_size = 0;
+
+	xl.real_private = priv_data;
+	xl.func = func;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+		csum_size = sizeof(struct ext2_dir_entry_tail);
+
+	retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+	if (retval)
+		return retval;
+	retval = ext2fs_read_inode_full(fs, ino, (void *)inode,
+					EXT2_INODE_SIZE(fs->super));
+	if (retval) {
+		ext2fs_free_mem(&inode);
+		return retval;
+	}
+
+	ctx.ino = ino;
+	ctx.flags = flags;
+	ctx.buf = block_buf;
+	ctx.func = xlate_func;
+	ctx.priv_data = &xl;
+	ctx.errcode = 0;
+
+	inline_start = inode->i_block;
+	inline_size = EXT4_MIN_INLINE_DATA_SIZE;
+	retval = inline_data_search_dir(fs, inode, inline_start, inline_size, &ctx);
+	if (retval)
+		goto out;
+
+	ext2fs_iget_extra_inode(fs, inode, &idata);
+	inline_size = idata.inline_size - EXT4_MIN_INLINE_DATA_SIZE;
+	if (inline_size > 0) {
+		inline_start = ext2fs_get_inline_xattr_pos(inode, &idata);
+		retval = inline_data_search_dir(fs, inode, inline_start, inline_size, &ctx);
+		if (retval)
+			goto out;
+	}
+
+	/*
+	 * The inline space is filled up. So create a new block for it.
+	 * As the extent tree se created, we have to save the inline
+	 * dir first.
+	 */
+	inline_size = idata.inline_size;
+	retval = ext2fs_get_mem(inline_size, &backup_buf);
+	if (retval)
+		goto out;
+
+	memcpy(backup_buf, (void *)inode->i_block, EXT4_MIN_INLINE_DATA_SIZE);
+	if (inline_size > EXT4_MIN_INLINE_DATA_SIZE)
+		memcpy(backup_buf + EXT4_MIN_INLINE_DATA_SIZE,
+		       ext2fs_get_inline_xattr_pos(inode, &idata),
+		       inline_size - EXT4_MIN_INLINE_DATA_SIZE);
+
+	/* clear the entry and the flag in dir now */
+	retval = inline_data_destory_data(fs, ino, inode, &idata);
+	if (retval)
+		goto out;
+
+	if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
+		if (LINUX_S_ISDIR(inode->i_mode) ||
+		    LINUX_S_ISREG(inode->i_mode) ||
+		    LINUX_S_ISLNK(inode->i_mode))
+			inode->i_flags |= EXT4_EXTENTS_FL;
+	}
+	inode->i_flags  &= ~EXT4_INLINE_DATA_FL;
+
+	retval = ext2fs_new_block2(fs, 0, 0, &blk);
+	if (retval)
+		goto out;
+
+	ext2fs_iblk_set(fs, (void *)inode, 1);
+	if (!(fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS))
+		inode->i_block[0] = blk;
+	inode->i_size = fs->blocksize;
+
+	retval = ext2fs_get_mem(fs->blocksize, &blk_buf);
+	if (retval)
+		goto out;
+
+	memcpy(blk_buf, backup_buf, inline_size);
+
+	/* set the final dir entry to cover the whole block */
+	inline_data_update_dir_entry(fs, blk_buf, inline_size,
+				     fs->blocksize - csum_size);
+
+	if (csum_size) {
+		t = EXT2_DIRENT_TAIL(blk_buf, fs->blocksize);
+		ext2fs_initialize_dirent_tail(fs, t);
+	}
+
+	retval = ext2fs_write_dir_block4(fs, blk, blk_buf, 0, ino);
+	if (retval)
+		goto out;
+	retval = ext2fs_write_inode_full(fs, ino, (void *)inode,
+					 EXT2_INODE_SIZE(fs->super));
+	if (retval)
+		goto out;
+
+	if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
+		retval = ext2fs_extent_open2(fs, ino, (void *)inode, &handle);
+		if (retval)
+			goto out;
+		retval = ext2fs_extent_set_bmap(handle, 0, blk, 0);
+		ext2fs_extent_free(handle);
+		if (retval)
+			goto out;
+	}
+
+	/* Update accouting */
+	ext2fs_block_alloc_stats2(fs, blk, +1);
+
+	/* try to add a new entry */
+	retval = ext2fs_dir_iterate(fs, ino, DIRENT_FLAG_INCLUDE_EMPTY,
+				    0, func, priv_data);
+
+	ext2fs_free_mem(&backup_buf);
+	ext2fs_free_mem(&blk_buf);
+out:
+	ext2fs_free_mem(&inode);
+	return retval & BLOCK_ABORT ? 0 : retval;
+}
+
+errcode_t ext2fs_inline_data_search_dir(ext2_filsys fs, ext2_ino_t ino,
+					       char *search_name, int len)
+{
+	struct ext2_inode_large *inode;
+	struct ext2_dir_entry *entry;
+	struct inline_data idata;
+	unsigned int rec_len;
+	errcode_t retval;
+	char *dlimit;
+	void *start;
+	int size;
+
+	retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+	if (retval)
+		return retval;
+
+	retval = ext2fs_read_inode_full(fs, ino, (void *)inode,
+					EXT2_INODE_SIZE(fs->super));
+	if (retval)
+		return retval;
+
+	if (!(inode->i_flags & EXT4_INLINE_DATA_FL))
+		goto out;
+
+	start = inode->i_block;
+	size = EXT4_MIN_INLINE_DATA_SIZE;
+	retval = inline_data_search_dir2(fs, start, size, search_name, len);
+	if (!retval)
+		goto out;
+
+	retval = 0;
+	ext2fs_iget_extra_inode(fs, inode, &idata);
+	if (idata.inline_size == EXT4_MIN_INLINE_DATA_SIZE)
+		goto out;
+
+	start = ext2fs_get_inline_xattr_pos(inode, &idata);
+	size = idata.inline_size - EXT4_MIN_INLINE_DATA_SIZE;
+	retval = inline_data_search_dir2(fs, start, size, search_name, len);
+
+out:
+	ext2fs_free_mem(&inode);
+	return retval;
+}
+
+errcode_t ext2fs_inline_data_header_verify(ext2_filsys fs,
+					   struct ext2_inode *inode)
+{
+	struct inline_data idata;
+	int ret = 0;
+
+	ext2fs_iget_extra_inode(fs, (void *)inode, &idata);
+	if (idata.inline_off == 0)
+		ret = -1;
+
+	return ret;
+}
+
+int ext2fs_inline_data_in_extra(ext2_filsys fs, ext2_ino_t ino)
+{
+	struct ext2_inode *inode;
+	struct inline_data idata;
+
+	ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+	ext2fs_read_inode_full(fs, ino, inode, EXT2_INODE_SIZE(fs->super));
+
+	ext2fs_iget_extra_inode(fs, inode, &idata);
+	ext2fs_free_mem(&inode);
+	if (idata.inline_off == 0 ||
+	    idata.inline_size == EXT4_MIN_INLINE_DATA_SIZE)
+		return 0;
+	else
+		return 1;
+}
+
+int ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino)
+{
+	struct ext2_inode *inode;
+	struct inline_data idata;
+
+	inode = (struct ext2_inode *) malloc(EXT2_INODE_SIZE(fs->super));
+	ext2fs_read_inode_full(fs, ino, inode, EXT2_INODE_SIZE(fs->super));
+
+	ext2fs_iget_extra_inode(fs, inode, &idata);
+	free(inode);
+	if (idata.inline_off == 0)
+		return 0;
+	else
+		return idata.inline_size;
+}
+
+errcode_t ext2fs_inline_data_expand_dir(ext2_filsys fs,
+					ext2_ino_t ino,
+					int flags,
+					char *block_buf,
+					int (*func)(ext2_filsys fs,
+						    blk64_t *blocknr,
+						    e2_blkcnt_t blockcnt,
+						    blk64_t ref_blk,
+						    int ref_offset,
+						    void *priv_data),
+					void *priv_data)
+{
+	struct ext2_inode_large *inode;
+	struct inline_data idata;
+	struct ext2_dir_entry_tail *t;
+	ext2_extent_handle_t handle;
+	errcode_t retval;
+	blk64_t blk;
+	void *inline_start;
+	char *backup_buf;
+	char *blk_buf;
+	int inline_size;
+	int i, limit, r;
+	int csum_size = 0;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+		csum_size = sizeof(struct ext2_dir_entry_tail);
+
+	retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+	if (retval)
+		return retval;
+	retval = ext2fs_read_inode_full(fs, ino, (void *)inode,
+					EXT2_INODE_SIZE(fs->super));
+	if (retval) {
+		ext2fs_free_mem(&inode);
+		return retval;
+	}
+
+	ext2fs_iget_extra_inode(fs, inode, &idata);
+
+	inline_size = idata.inline_size;
+	retval = ext2fs_get_mem(inline_size, &backup_buf);
+	if (retval) {
+		goto out;
+	}
+
+	memcpy(backup_buf, (void *)inode->i_block, EXT4_MIN_INLINE_DATA_SIZE);
+	if (inline_size > EXT4_MIN_INLINE_DATA_SIZE)
+		memcpy(backup_buf + EXT4_MIN_INLINE_DATA_SIZE,
+		       ext2fs_get_inline_xattr_pos(inode, &idata),
+		       inline_size - EXT4_MIN_INLINE_DATA_SIZE);
+
+	/* clear the entry and the flag in dir now */
+	retval = inline_data_destory_data(fs, ino, inode, &idata);
+	if (retval)
+		goto out;
+
+	if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
+		if (LINUX_S_ISDIR(inode->i_mode) ||
+		    LINUX_S_ISREG(inode->i_mode) ||
+		    LINUX_S_ISLNK(inode->i_mode))
+			inode->i_flags |= EXT4_EXTENTS_FL;
+	}
+	inode->i_flags  &= ~EXT4_INLINE_DATA_FL;
+
+	retval = ext2fs_new_block2(fs, 0, 0, &blk);
+	if (retval)
+		goto out;
+
+	ext2fs_iblk_set(fs, (void *)inode, 1);
+	if (!(fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS))
+		inode->i_block[0] = blk;
+	inode->i_size = fs->blocksize;
+
+	retval = ext2fs_get_mem(fs->blocksize, &blk_buf);
+	if (retval)
+		goto out;
+
+	memcpy(blk_buf, backup_buf, inline_size);
+
+	/* set the final dir entry to cover the whole block */
+	inline_data_update_dir_entry(fs, blk_buf, inline_size,
+				     fs->blocksize - csum_size);
+
+	if (csum_size) {
+		t = EXT2_DIRENT_TAIL(blk_buf, fs->blocksize);
+		ext2fs_initialize_dirent_tail(fs, t);
+	}
+
+	retval = ext2fs_write_dir_block4(fs, blk, blk_buf, 0, ino);
+	if (retval)
+		goto out;
+	retval = ext2fs_write_inode_full(fs, ino, (void *)inode,
+					 EXT2_INODE_SIZE(fs->super));
+	if (retval)
+		goto out;
+
+	if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
+		retval = ext2fs_extent_open2(fs, ino, (void *)inode, &handle);
+		if (retval)
+			goto out;
+		retval = ext2fs_extent_set_bmap(handle, 0, blk, 0);
+		ext2fs_extent_free(handle);
+		if (retval)
+			goto out;
+	}
+
+	/* Update accouting */
+	ext2fs_block_alloc_stats2(fs, blk, +1);
+
+	/* try to add a new entry */
+	retval = ext2fs_block_iterate3(fs, ino, flags, 0, func, priv_data);
+
+	ext2fs_free_mem(&backup_buf);
+	ext2fs_free_mem(&blk_buf);
+out:
+	ext2fs_free_mem(&inode);
+	return retval & BLOCK_ABORT ? 0 : retval;
+}
-- 
1.7.4.1


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

* [PATCH 08/36 v4] debugfs: make ncheck cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (6 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 07/36 v4] libext2fs: add inline_data file Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 09/36 v4] debugfs: make icheck " Zheng Liu
                   ` (28 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

When inode has inline data, ext2fs_inline_data_iterate function is called
to traverse dirs.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/ncheck.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/debugfs/ncheck.c b/debugfs/ncheck.c
index 58f3a50..6dda919 100644
--- a/debugfs/ncheck.c
+++ b/debugfs/ncheck.c
@@ -171,8 +171,12 @@ void do_ncheck(int argc, char **argv)
 		iw.dir = ino;
 		iw.get_pathname_failed = 0;
 
-		retval = ext2fs_dir_iterate(current_fs, ino, 0, 0,
-					    ncheck_proc, &iw);
+		if (ext2fs_has_inline_data(current_fs, ino))
+			retval = ext2fs_inline_data_iterate(current_fs, ino, 0,
+							    0, ncheck_proc, &iw);
+		else
+			retval = ext2fs_dir_iterate(current_fs, ino, 0, 0,
+						    ncheck_proc, &iw);
 		ext2fs_free_mem(&iw.parent);
 		if (retval) {
 			com_err("ncheck", retval,
-- 
1.7.4.1


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

* [PATCH 09/36 v4] debugfs: make icheck cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (7 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 08/36 v4] debugfs: make ncheck cmd support inline data Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 10/36 v4] debugfs: make chroot and cd " Zheng Liu
                   ` (27 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

When inode has inline_data, we don't need to check i_blocks.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/icheck.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/debugfs/icheck.c b/debugfs/icheck.c
index 48f432a..3caa930 100644
--- a/debugfs/icheck.c
+++ b/debugfs/icheck.c
@@ -132,9 +132,12 @@ void do_icheck(int argc, char **argv)
 		if (inode.i_dtime)
 			goto next;
 
-		retval = ext2fs_block_iterate3(current_fs, ino,
-					       BLOCK_FLAG_READ_ONLY, block_buf,
-					       icheck_proc, &bw);
+		/* we don't need to check i_blocks with inline_data */
+		if (!ext2fs_has_inline_data(current_fs, ino))
+			retval = ext2fs_block_iterate3(current_fs, ino,
+						       BLOCK_FLAG_READ_ONLY,
+						       block_buf,
+						       icheck_proc, &bw);
 		if (retval) {
 			com_err("icheck", retval,
 				"while calling ext2fs_block_iterate");
-- 
1.7.4.1


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

* [PATCH 10/36 v4] debugfs: make chroot and cd cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (8 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 09/36 v4] debugfs: make icheck " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 11/36 v4] debugfs: make ls " Zheng Liu
                   ` (26 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Both chroot and cd command call ext2fs_lookup.  So we can let it supoort
inline data simultaneously.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/lookup.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/lib/ext2fs/lookup.c b/lib/ext2fs/lookup.c
index 0e66e71..9835082 100644
--- a/lib/ext2fs/lookup.c
+++ b/lib/ext2fs/lookup.c
@@ -60,7 +60,11 @@ errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
 	ls.inode = inode;
 	ls.found = 0;
 
-	retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
+	if (ext2fs_has_inline_data(fs, dir))
+		retval = ext2fs_inline_data_iterate(fs, dir, 0, buf,
+						    lookup_proc, &ls);
+	else
+		retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
 	if (retval)
 		return retval;
 
-- 
1.7.4.1


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

* [PATCH 11/36 v4] debugfs: make ls cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (9 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 10/36 v4] debugfs: make chroot and cd " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 12/36 v4] debugfs: make stat " Zheng Liu
                   ` (25 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/ls.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/debugfs/ls.c b/debugfs/ls.c
index b4036de..00b497d 100644
--- a/debugfs/ls.c
+++ b/debugfs/ls.c
@@ -170,8 +170,12 @@ void do_list_dir(int argc, char *argv[])
 	if (ls.options & DELETED_OPT)
 		flags |= DIRENT_FLAG_INCLUDE_REMOVED;
 
-	retval = ext2fs_dir_iterate2(current_fs, inode, flags,
-				    0, list_dir_proc, &ls);
+	if (ext2fs_has_inline_data(current_fs, inode))
+		retval = ext2fs_inline_data_iterate2(current_fs, inode, flags,
+						     0, list_dir_proc, &ls);
+	else
+		retval = ext2fs_dir_iterate2(current_fs, inode, flags,
+					    0, list_dir_proc, &ls);
 	fprintf(ls.f, "\n");
 	close_pager(ls.f);
 	if (retval)
-- 
1.7.4.1


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

* [PATCH 12/36 v4] debugfs: make stat cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (10 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 11/36 v4] debugfs: make ls " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 13/36 v4] debugfs: make blocks " Zheng Liu
                   ` (24 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

It only tells the user that this inode contains inline data.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/debugfs.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 76c0867..14092e0 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -836,7 +836,9 @@ void internal_dump_inode(FILE *out, const char *prefix,
 		fprintf(out, "%sDevice major/minor number: %02d:%02d (hex %02x:%02x)\n",
 			devnote, major, minor, major, minor);
 	} else if (do_dump_blocks) {
-		if (inode->i_flags & EXT4_EXTENTS_FL)
+		if (inode->i_flags & EXT4_INLINE_DATA_FL)
+			fprintf(out, "Inode has inline data\n");
+		else if (inode->i_flags & EXT4_EXTENTS_FL)
 			dump_extents(out, prefix, inode_num,
 				     DUMP_LEAF_EXTENTS|DUMP_NODE_EXTENTS, 0, 0);
 		else
-- 
1.7.4.1


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

* [PATCH 13/36 v4] debugfs: make blocks cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (11 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 12/36 v4] debugfs: make stat " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 14/36 v4] debugfs: make filefrag " Zheng Liu
                   ` (23 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4

From: Zheng Liu <wenqing.lz@taobao.com>

Block entries don't point to blocks.  So it doesn't show anything when
this inode has inline data.

Singed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/debugfs.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 14092e0..db3d3b9 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -968,6 +968,9 @@ void do_blocks(int argc, char *argv[])
 		return;
 	}
 
+	if (ext2fs_has_inline_data(current_fs, inode))
+		return;
+
 	ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL,
 			      print_blocks_proc, NULL);
 	fputc('\n', stdout);
-- 
1.7.4.1


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

* [PATCH 14/36 v4] debugfs: make filefrag cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (12 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 13/36 v4] debugfs: make blocks " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 15/36 v4] debugfs: make link " Zheng Liu
                   ` (22 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Inode with inline data haven't any fragmentations.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/filefrag.c |   30 ++++++++++++++++++------------
 1 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/debugfs/filefrag.c b/debugfs/filefrag.c
index 7f28bc0..c94396c 100644
--- a/debugfs/filefrag.c
+++ b/debugfs/filefrag.c
@@ -153,16 +153,18 @@ static void filefrag(ext2_ino_t ino, struct ext2_inode *inode,
 		fprintf(fs->f, "\n%s has %llu block(s), i_size is %llu\n",
 			fs->name, num_blocks, EXT2_I_SIZE(inode));
 	}
-	print_header(fs);
-	retval = ext2fs_block_iterate3(current_fs, ino,
-				       BLOCK_FLAG_READ_ONLY, NULL,
-				       filefrag_blocks_proc, fs);
-	if (retval)
-		com_err("ext2fs_block_iterate3", retval, 0);
-
-	report_filefrag(fs);
-	fprintf(fs->f, "%s: %d contiguous extents%s\n", fs->name, fs->ext,
-		LINUX_S_ISDIR(inode->i_mode) ? " (dir)" : "");
+	if (!ext2fs_has_inline_data(current_fs, ino)) {
+		print_header(fs);
+		retval = ext2fs_block_iterate3(current_fs, ino,
+					       BLOCK_FLAG_READ_ONLY, NULL,
+					       filefrag_blocks_proc, fs);
+		if (retval)
+			com_err("ext2fs_block_iterate3", retval, 0);
+
+		report_filefrag(fs);
+		fprintf(fs->f, "%s: %d contiguous extents%s\n", fs->name, fs->ext,
+			LINUX_S_ISDIR(inode->i_mode) ? " (dir)" : "");
+	}
 }
 
 static int filefrag_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
@@ -240,8 +242,12 @@ static void dir_iterate(ext2_ino_t ino, struct filefrag_struct *fs)
 	fs->dir_name = fs->name;
 
 	while (1) {
-		retval = ext2fs_dir_iterate2(current_fs, ino, 0,
-					     0, filefrag_dir_proc, fs);
+		if (ext2fs_has_inline_data(current_fs, ino))
+			retval = ext2fs_inline_data_iterate2(current_fs, ino,
+						0, 0, filefrag_dir_proc, fs);
+		else
+			retval = ext2fs_dir_iterate2(current_fs, ino, 0,
+						     0, filefrag_dir_proc, fs);
 		if (retval)
 			com_err("ext2fs_dir_iterate2", retval, 0);
 		if (p) {
-- 
1.7.4.1


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

* [PATCH 15/36 v4] debugfs: make link cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (13 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 14/36 v4] debugfs: make filefrag " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 16/36 v4] debugfs: make unlink " Zheng Liu
                   ` (21 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/link.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/lib/ext2fs/link.c b/lib/ext2fs/link.c
index 2dec5dc..67151c3 100644
--- a/lib/ext2fs/link.c
+++ b/lib/ext2fs/link.c
@@ -135,8 +135,13 @@ errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
 	ls.blocksize = fs->blocksize;
 	ls.err = 0;
 
-	retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
-				    0, link_proc, &ls);
+	if (ext2fs_has_inline_data(fs, dir))
+		retval = ext2fs_inline_data_iterate3(fs, dir,
+				DIRENT_FLAG_INCLUDE_EMPTY, 0, ls.name,
+				ls.namelen, link_proc, &ls);
+	else
+		retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
+					    0, link_proc, &ls);
 	if (retval)
 		return retval;
 	if (ls.err)
-- 
1.7.4.1


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

* [PATCH 16/36 v4] debugfs: make unlink cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (14 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 15/36 v4] debugfs: make link " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 17/36 v4] debugfs: make mkdir " Zheng Liu
                   ` (20 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/unlink.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/lib/ext2fs/unlink.c b/lib/ext2fs/unlink.c
index d2d31cc..6852d4a 100644
--- a/lib/ext2fs/unlink.c
+++ b/lib/ext2fs/unlink.c
@@ -90,8 +90,13 @@ errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir,
 	ls.done = 0;
 	ls.prev = 0;
 
-	retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
-				    0, unlink_proc, &ls);
+	if (ext2fs_has_inline_data(fs, dir))
+		retval = ext2fs_inline_data_iterate(fs, dir,
+					DIRENT_FLAG_INCLUDE_EMPTY, 0,
+					unlink_proc, &ls);
+	else
+		retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
+					    0, unlink_proc, &ls);
 	if (retval)
 		return retval;
 
-- 
1.7.4.1


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

* [PATCH 17/36 v4] debugfs: make mkdir cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (15 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 16/36 v4] debugfs: make unlink " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 18/36 v4] debugfs: make rmdir " Zheng Liu
                   ` (19 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

We need to reload inode in ext2fs_mkdir because inode with inline itself
data is modified in ext2fs_link.

Now we cannot create an empty dir with inline data because we need to do
a lot of works for maniluating xattr, and it brings a huge impacts for
e2fsprogs.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/mkdir.c |   33 +++++++++++++++++++++++++++++----
 1 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/lib/ext2fs/mkdir.c b/lib/ext2fs/mkdir.c
index 4a85439..3c226f3 100644
--- a/lib/ext2fs/mkdir.c
+++ b/lib/ext2fs/mkdir.c
@@ -41,6 +41,7 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
 	ext2_ino_t		scratch_ino;
 	blk64_t			blk;
 	char			*block = 0;
+	int			unmark_blk = 0;
 
 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
@@ -115,6 +116,14 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
 	}
 
 	/*
+	 * XXX: We need to update accouting before we mkdir successful because
+	 * in ext2fs_link it could allocate a new block when there is no space
+	 * to store a new dir entry in inline data.  If ext2fs_link failed, we
+	 * need to unmark this block.
+	 */
+	ext2fs_block_alloc_stats2(fs, blk, +1);
+
+	/*
 	 * Link the directory into the filesystem hierarchy
 	 */
 	if (name) {
@@ -123,32 +132,48 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
 		if (!retval) {
 			retval = EXT2_ET_DIR_EXISTS;
 			name = 0;
+			unmark_blk = 1;
 			goto cleanup;
 		}
-		if (retval != EXT2_ET_FILE_NOT_FOUND)
+		if (retval != EXT2_ET_FILE_NOT_FOUND) {
+			unmark_blk = 1;
 			goto cleanup;
+		}
 		retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR);
-		if (retval)
+		if (retval) {
+			unmark_blk = 1;
 			goto cleanup;
+		}
 	}
 
 	/*
 	 * Update parent inode's counts
 	 */
 	if (parent != ino) {
+		/* Reload parent inode */
+		retval = ext2fs_read_inode(fs, parent, &parent_inode);
+		if (retval) {
+			unmark_blk = 1;
+			goto cleanup;
+		}
 		parent_inode.i_links_count++;
 		retval = ext2fs_write_inode(fs, parent, &parent_inode);
-		if (retval)
+		if (retval) {
+			unmark_blk = 1;
 			goto cleanup;
+		}
 	}
 
 	/*
 	 * Update accounting....
 	 */
-	ext2fs_block_alloc_stats2(fs, blk, +1);
 	ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
 
 cleanup:
+	/* Unmark block because mkdir failed */
+	if (unmark_blk)
+		ext2fs_block_alloc_stats2(fs, blk, -1);
+
 	if (block)
 		ext2fs_free_mem(&block);
 	return retval;
-- 
1.7.4.1


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

* [PATCH 18/36 v4] debugfs: make rmdir cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (16 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 17/36 v4] debugfs: make mkdir " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 19/36 v4] debugfs: make rm and kill_file " Zheng Liu
                   ` (18 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/debugfs.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index db3d3b9..87fc6a9 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -1958,8 +1958,12 @@ void do_rmdir(int argc, char *argv[])
 	rds.parent = 0;
 	rds.empty = 1;
 
-	retval = ext2fs_dir_iterate2(current_fs, inode_num, 0,
-				    0, rmdir_proc, &rds);
+	if (ext2fs_has_inline_data(current_fs, inode_num))
+		retval = ext2fs_inline_data_iterate2(current_fs, inode_num, 0,
+						     0, rmdir_proc, &rds);
+	else
+		retval = ext2fs_dir_iterate2(current_fs, inode_num, 0,
+					    0, rmdir_proc, &rds);
 	if (retval) {
 		com_err(argv[0], retval, "while iterating over directory");
 		return;
-- 
1.7.4.1


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

* [PATCH 19/36 v4] debugfs: make rm and kill_file cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (17 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 18/36 v4] debugfs: make rmdir " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 20/36 v4] debugfs: make pwd " Zheng Liu
                   ` (17 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

rm and kill_file command don't need to release blocks.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/debugfs.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 87fc6a9..9069735 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -1851,8 +1851,9 @@ static void kill_file_by_inode(ext2_ino_t inode)
 	if (!ext2fs_inode_has_valid_blocks2(current_fs, &inode_buf))
 		return;
 
-	ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL,
-			      release_blocks_proc, NULL);
+	if (!ext2fs_has_inline_data(current_fs, inode))
+		ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY,
+				      NULL, release_blocks_proc, NULL);
 	printf("\n");
 	ext2fs_inode_alloc_stats2(current_fs, inode, -1,
 				  LINUX_S_ISDIR(inode_buf.i_mode));
-- 
1.7.4.1


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

* [PATCH 20/36 v4] debugfs: make pwd cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (18 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 19/36 v4] debugfs: make rm and kill_file " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 21/36 v4] debugfs: make expand_dir " Zheng Liu
                   ` (16 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/get_pathname.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/lib/ext2fs/get_pathname.c b/lib/ext2fs/get_pathname.c
index 52aea62..f92f17d 100644
--- a/lib/ext2fs/get_pathname.c
+++ b/lib/ext2fs/get_pathname.c
@@ -98,7 +98,12 @@ static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir,
 	gp.name = 0;
 	gp.errcode = 0;
 
-	retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp);
+	if (ext2fs_has_inline_data(fs, dir))
+		retval = ext2fs_inline_data_iterate(fs, dir, 0, buf,
+						    get_pathname_proc, &gp);
+	else
+		retval = ext2fs_dir_iterate(fs, dir, 0, buf,
+					    get_pathname_proc, &gp);
 	if (retval == EXT2_ET_NO_DIRECTORY) {
 		char tmp[32];
 
-- 
1.7.4.1


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

* [PATCH 21/36 v4] debugfs: make expand_dir cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (19 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 20/36 v4] debugfs: make pwd " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 22/36 v4] debugfs: make lsdel " Zheng Liu
                   ` (15 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

expand_dir command allocates two new block for the dir.  It firstly allocates
a new block, and copies all of inline data into this block.  Then it allocates
another block for this dir.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/expanddir.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/lib/ext2fs/expanddir.c b/lib/ext2fs/expanddir.c
index 22558d6..8ba8a23 100644
--- a/lib/ext2fs/expanddir.c
+++ b/lib/ext2fs/expanddir.c
@@ -114,8 +114,12 @@ errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir)
 	es.newblocks = 0;
 	es.dir = dir;
 
-	retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND,
-				       0, expand_dir_proc, &es);
+	if (ext2fs_has_inline_data(fs, dir))
+		retval = ext2fs_inline_data_expand_dir(fs, dir, BLOCK_CHANGED,
+						       0, expand_dir_proc, &es);
+	else
+		retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND,
+					       0, expand_dir_proc, &es);
 
 	if (es.err)
 		return es.err;
-- 
1.7.4.1


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

* [PATCH 22/36 v4] debugfs: make lsdel cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (20 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 21/36 v4] debugfs: make expand_dir " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 23/36 v4] debugfs: make undelete " Zheng Liu
                   ` (14 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/lsdel.c |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/debugfs/lsdel.c b/debugfs/lsdel.c
index bed0ce6..ff283cd 100644
--- a/debugfs/lsdel.c
+++ b/debugfs/lsdel.c
@@ -141,15 +141,18 @@ void do_lsdel(int argc, char **argv)
 		lsd.free_blocks = 0;
 		lsd.bad_blocks = 0;
 
-		retval = ext2fs_block_iterate3(current_fs, ino,
-					       BLOCK_FLAG_READ_ONLY, block_buf,
-					       lsdel_proc, &lsd);
-		if (retval) {
-			com_err("ls_deleted_inodes", retval,
-				"while calling ext2fs_block_iterate2");
-			goto next;
+		if (!ext2fs_has_inline_data(current_fs, ino)) {
+			retval = ext2fs_block_iterate3(current_fs, ino,
+						       BLOCK_FLAG_READ_ONLY, block_buf,
+						       lsdel_proc, &lsd);
+			if (retval) {
+				com_err("ls_deleted_inodes", retval,
+					"while calling ext2fs_block_iterate2");
+				goto next;
+			}
 		}
-		if (lsd.free_blocks && !lsd.bad_blocks) {
+		if (lsd.free_blocks && !lsd.bad_blocks ||
+		    ext2fs_has_inline_data(current_fs, ino)) {
 			if (num_delarray >= max_delarray) {
 				max_delarray += 50;
 				delarray = realloc(delarray,
-- 
1.7.4.1


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

* [PATCH 23/36 v4] debugfs: make undelete cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (21 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 22/36 v4] debugfs: make lsdel " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 24/36 v4] debugfs: make dump and cat " Zheng Liu
                   ` (13 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Inode with inline data doesn't need to mark blocks.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/debugfs.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 9069735..cf32068 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -1445,8 +1445,9 @@ void do_undel(int argc, char *argv[])
 	if (debugfs_write_inode(ino, &inode, argv[0]))
 		return;
 
-	ext2fs_block_iterate3(current_fs, ino, BLOCK_FLAG_READ_ONLY, NULL,
-			      mark_blocks_proc, NULL);
+	if (!ext2fs_has_inline_data(current_fs, ino))
+		ext2fs_block_iterate3(current_fs, ino, BLOCK_FLAG_READ_ONLY, NULL,
+				      mark_blocks_proc, NULL);
 
 	ext2fs_inode_alloc_stats2(current_fs, ino, +1, 0);
 
-- 
1.7.4.1


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

* [PATCH 24/36 v4] debugfs: make dump and cat cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (22 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 23/36 v4] debugfs: make undelete " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 25/36 v4] debugfs: make rdump " Zheng Liu
                   ` (12 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

dump and cat command use the same function to read data.  We can
directly read the data from inode.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/dump.c |   30 ++++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/debugfs/dump.c b/debugfs/dump.c
index a15a0b7..10ebe7a 100644
--- a/debugfs/dump.c
+++ b/debugfs/dump.c
@@ -113,6 +113,36 @@ static void dump_file(const char *cmdname, ext2_ino_t ino, int fd,
 	if (debugfs_read_inode(ino, &inode, cmdname))
 		return;
 
+	if (ext2fs_has_inline_data(current_fs, ino)) {
+		struct ext2_inode_large *inode;
+		struct inline_data idata;
+		void *inline_start;
+		int inline_size;
+
+		retval = ext2fs_get_mem(EXT2_INODE_SIZE(current_fs->super),
+							&inode);
+		if (retval)
+			return;
+
+		retval = ext2fs_read_inode_full(current_fs, ino, (void *)inode,
+						EXT2_INODE_SIZE(current_fs->super));
+		if (retval)
+			goto out;
+		write(fd, inode->i_block, EXT4_MIN_INLINE_DATA_SIZE);
+
+		ext2fs_iget_extra_inode(current_fs, inode, &idata);
+		if (idata.inline_off == EXT4_MIN_INLINE_DATA_SIZE)
+			goto out;
+
+		inline_start = ext2fs_get_inline_xattr_pos(inode, &idata);
+		inline_size = idata.inline_size - EXT4_MIN_INLINE_DATA_SIZE;
+		write(fd, inline_start, inline_size);
+
+out:
+		ext2fs_free_mem(&inode);
+		return;
+	}
+
 	retval = ext2fs_file_open(current_fs, ino, 0, &e2_file);
 	if (retval) {
 		com_err(cmdname, retval, "while opening ext2 file");
-- 
1.7.4.1


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

* [PATCH 25/36 v4] debugfs: make rdump cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (23 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 24/36 v4] debugfs: make dump and cat " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 26/36 v4] debugfs: make dirsearch " Zheng Liu
                   ` (11 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/dump.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/debugfs/dump.c b/debugfs/dump.c
index 10ebe7a..84de606 100644
--- a/debugfs/dump.c
+++ b/debugfs/dump.c
@@ -308,8 +308,12 @@ static void rdump_inode(ext2_ino_t ino, struct ext2_inode *inode,
 			goto errout;
 		}
 
-		retval = ext2fs_dir_iterate(current_fs, ino, 0, 0,
-					    rdump_dirent, (void *) fullname);
+		if (ext2fs_has_inline_data(current_fs, ino))
+			retval = ext2fs_inline_data_iterate(current_fs, ino, 0, 0,
+							    rdump_dirent, (void *) fullname);
+		else
+			retval = ext2fs_dir_iterate(current_fs, ino, 0, 0,
+						    rdump_dirent, (void *) fullname);
 		if (retval)
 			com_err("rdump", retval, "while dumping %s", fullname);
 
-- 
1.7.4.1


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

* [PATCH 26/36 v4] debugfs: make dirsearch cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (24 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 25/36 v4] debugfs: make rdump " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 27/36 v4] debugfs: make bmap " Zheng Liu
                   ` (10 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 debugfs/htree.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/debugfs/htree.c b/debugfs/htree.c
index 1932962..8051618 100644
--- a/debugfs/htree.c
+++ b/debugfs/htree.c
@@ -374,9 +374,15 @@ void do_dirsearch(int argc, char *argv[])
 	pb.search_name = argv[2];
 	pb.len = strlen(pb.search_name);
 
+	if (ext2fs_has_inline_data(current_fs, inode))
+		if (ext2fs_inline_data_search_dir(current_fs, inode, argv[2],
+						  strlen(argv[2])) == 0)
+			goto out;
+
 	ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, 0,
 			      search_dir_block, &pb);
 
+out:
 	free(pb.buf);
 }
 
-- 
1.7.4.1


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

* [PATCH 27/36 v4] debugfs: make bmap cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (25 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 26/36 v4] debugfs: make dirsearch " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 28/36 v4] debugfs: make punch/truncate " Zheng Liu
                   ` (9 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Now this command returns inode's phy block when this inode has inline data.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/bmap.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/lib/ext2fs/bmap.c b/lib/ext2fs/bmap.c
index 16d51e0..101fe90 100644
--- a/lib/ext2fs/bmap.c
+++ b/lib/ext2fs/bmap.c
@@ -264,6 +264,22 @@ errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
 		block_buf = buf;
 	}
 
+	if (inode->i_flags & EXT4_INLINE_DATA_FL) {
+		unsigned long group, block, offset;
+
+		group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
+		if (group > fs->group_desc_count)
+			return EXT2_ET_BAD_INODE_NUM;
+		offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
+			 EXT2_INODE_SIZE(fs->super);
+		block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
+		if (!ext2fs_inode_table_loc(fs, (unsigned) group))
+			return EXT2_ET_MISSING_INODE_TABLE;
+		*phys_blk = ext2fs_inode_table_loc(fs, group) + block;
+
+		goto done;
+	}
+
 	if (inode->i_flags & EXT4_EXTENTS_FL) {
 		retval = ext2fs_extent_open2(fs, ino, inode, &handle);
 		if (retval)
-- 
1.7.4.1


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

* [PATCH 28/36 v4] debugfs: make punch/truncate cmd support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (26 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 27/36 v4] debugfs: make bmap " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 29/36 v4] e2fsck: add three problem descriptions in pass1 Zheng Liu
                   ` (8 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

If inode includes inline_data flag, start and end arguments will be ignored.
Meanwhile we truncate inline data.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/punch.c |   33 ++++++++++++++++++++++++++++++++-
 1 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/lib/ext2fs/punch.c b/lib/ext2fs/punch.c
index b53653a..28967a4 100644
--- a/lib/ext2fs/punch.c
+++ b/lib/ext2fs/punch.c
@@ -281,6 +281,34 @@ errout:
 	ext2fs_extent_free(handle);
 	return retval;
 }
+
+static errcode_t ext2fs_punch_inline_data(ext2_filsys fs, ext2_ino_t ino,
+					  struct ext2_inode *inode,
+					  blk64_t start, blk64_t end)
+{
+	struct ext2_inode_large large_inode;
+	struct inline_data idata;
+	errcode_t retval;
+	int inline_size;
+
+	retval = ext2fs_read_inode_full(fs, ino, (void *)&large_inode,
+					EXT2_INODE_SIZE(fs->super));
+	if (retval)
+		return retval;
+
+	ext2fs_iget_extra_inode(fs, &large_inode, &idata);
+
+	inline_size = idata.inline_size;
+	retval = inline_data_destory_data(fs, ino, &large_inode, &idata);
+	if (retval)
+		return retval;
+
+	large_inode.i_size = 0;
+	ext2fs_write_inode_full(fs, ino, (void *)&large_inode,
+				EXT2_INODE_SIZE(fs->super));
+
+	return retval;
+}
 	
 /*
  * Deallocate all logical blocks starting at start to end, inclusive.
@@ -307,7 +335,10 @@ extern errcode_t ext2fs_punch(ext2_filsys fs, ext2_ino_t ino,
 			return retval;
 		inode = &inode_buf;
 	}
-	if (inode->i_flags & EXT4_EXTENTS_FL)
+	if (inode->i_flags & EXT4_INLINE_DATA_FL) {
+		retval = ext2fs_punch_inline_data(fs, ino, inode, start, end);
+		return retval;
+	} else if (inode->i_flags & EXT4_EXTENTS_FL)
 		retval = ext2fs_punch_extent(fs, ino, inode, start, end);
 	else {
 		blk_t	count;
-- 
1.7.4.1


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

* [PATCH 29/36 v4] e2fsck: add three problem descriptions in pass1
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (27 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 28/36 v4] debugfs: make punch/truncate " Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 30/36 v4] e2fsck: check incorrect inline data flag Zheng Liu
                   ` (7 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

In pass1, we will meet three problems.  So add descriptions in problem
table.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 e2fsck/problem.c |   15 +++++++++++++++
 e2fsck/problem.h |    9 +++++++++
 2 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 286257d..e55372d 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -1000,6 +1000,21 @@ static struct e2fsck_problem problem_table[] = {
 	     "@i %i does not match.  "),
 	  PROMPT_FIX, 0 },
 
+	/* INLINE_DATA is set and EXT_ATTR is not set */
+	{ PR_1_INLINE_DATA_AND_EXT_ATTR,
+	  N_("INLINE_DATA is set in @S, but it is missing EXT_ATTR feature\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Inode has inline data, superblock missing INCOMPAT_INLINE_DATA feature */
+	{ PR_1_INLINE_DATA_FEATURE,
+	  N_("@i %i is in inline data format, but @S is missing INLINEDATA feature\n"),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* INLINE_DATA_FL flag set on a non-inline-data filesystem */
+	{ PR_1_INLINE_DATA_SET,
+	  N_("@i %i has INLINE_DATA_FL flag set on @f without inline data support.\n"),
+	  PROMPT_CLEAR, 0 },
+
 	/* Pass 1b errors */
 
 	/* Pass 1B: Rescan for duplicate/bad blocks */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 5caade4..4ea2b2d 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -587,6 +587,15 @@ struct problem_context {
 #define PR_1_EA_BLOCK_ONLY_CSUM_INVALID        0x01006C
 
 
+/* INLINE_DATA is set and EXT_ATTR is not set */
+#define PR_1_INLINE_DATA_AND_EXT_ATTR	0x01006D
+
+/* Inode has inline data, superblock missing INCOMPAT_INLINE_DATA feature */
+#define PR_1_INLINE_DATA_FEATURE	0x01006E
+
+/* INLINE_DATA_FL flag set on a non-inline-data capable filesystem */
+#define PR_1_INLINE_DATA_SET		0x01006F
+
 /*
  * Pass 1b errors
  */
-- 
1.7.4.1


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

* [PATCH 30/36 v4] e2fsck: check incorrect inline data flag
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (28 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 29/36 v4] e2fsck: add three problem descriptions in pass1 Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 31/36 v4] e2fsck: make pass1 support inline data Zheng Liu
                   ` (6 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

First, we need to check whether or not EXT_ATTR feature is set when
INLINE_DATA feature is set.  Then we will check inode flag to set
EXT4_INLINE_DATA_FL flag.  If the user doesn't set this flag, INLINE_DATA
feature will be clear.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 e2fsck/pass1.c |   33 ++++++++++++++++++++++++++++++++-
 1 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 48a1af0..fee0dc6 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -593,7 +593,7 @@ void e2fsck_pass1(e2fsck_t ctx)
 	struct ext2_super_block *sb = ctx->fs->super;
 	const char	*old_op;
 	unsigned int	save_type;
-	int		imagic_fs, extent_fs;
+	int		imagic_fs, extent_fs, inlinedata_fs;
 	int		busted_fs_time = 0;
 	int		inode_size;
 	int		failed_csum = 0;
@@ -627,6 +627,7 @@ void e2fsck_pass1(e2fsck_t ctx)
 
 	imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
 	extent_fs = (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS);
+	inlinedata_fs = (sb->s_feature_incompat & EXT4_FEATURE_INCOMPAT_INLINE_DATA);
 
 	/*
 	 * Allocate bitmaps structures
@@ -758,6 +759,17 @@ void e2fsck_pass1(e2fsck_t ctx)
 		ext2fs_mark_block_bitmap2(ctx->block_found_map,
 					  fs->super->s_mmp_block);
 
+	/*
+	 * If INLINE_DATA is set and EXT_ATTR doesn't, EXT_ATTR needs to be set
+	 * because INLINE_DATA depends on it.  So the user need to determine
+	 * whether EXT_ATTR is set or not.
+	 */
+	if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
+	    inlinedata_fs) {
+		if (fix_problem(ctx, PR_1_INLINE_DATA_AND_EXT_ATTR, &pctx))
+			ext2fs_mark_super_dirty(fs);
+	}
+
 	while (1) {
 		if (ino % (fs->super->s_inodes_per_group * 4) == 1) {
 			if (e2fsck_mmp_update(fs))
@@ -807,6 +819,25 @@ void e2fsck_pass1(e2fsck_t ctx)
 		}
 
 		/*
+		 * Test for incorrect inline data flags settings.
+		 *
+		 * TODO: check EXT2_ROOT_INO when '/' supports inline data
+		 * feature.
+		 */
+		if ((inode->i_flags & EXT4_INLINE_DATA_FL) && !inlinedata_fs &&
+		    (ino >= EXT2_FIRST_INODE(fs->super))) {
+			if (ext2fs_inline_data_header_verify(fs, inode) == 0 &&
+			    fix_problem(ctx, PR_1_INLINE_DATA_FEATURE, &pctx)) {
+				sb->s_feature_incompat |= EXT4_FEATURE_INCOMPAT_INLINE_DATA;
+				ext2fs_mark_super_dirty(fs);
+				inlinedata_fs = 1;
+			} else if (fix_problem(ctx, PR_1_INLINE_DATA_SET, &pctx)) {
+				e2fsck_clear_inode(ctx, ino, inode, 0, "pass1");
+				continue;
+			}
+		}
+
+		/*
 		 * Test for incorrect extent flag settings.
 		 *
 		 * On big-endian machines we must be careful:
-- 
1.7.4.1


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

* [PATCH 31/36 v4] e2fsck: make pass1 support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (29 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 30/36 v4] e2fsck: check incorrect inline data flag Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 32/36 v4] libext2fs: add read/write inline data functions Zheng Liu
                   ` (5 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 e2fsck/pass1.c          |   76 ++++++++++++++++++++++++++++++++++++++++++-----
 e2fsck/pass1b.c         |    5 ++-
 lib/ext2fs/dblist_dir.c |    8 ++++-
 3 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index fee0dc6..f1bf828 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -221,12 +221,37 @@ int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino,
 		if (len == fs->blocksize)
 			return 0;
 	} else {
-		if (inode->i_size >= sizeof(inode->i_block))
-			return 0;
+		if (inode->i_flags & EXT4_INLINE_DATA_FL) {
+			struct ext2_inode_large *large_inode;
+			struct inline_data idata;
+			void *inline_start;
+			int inline_data_size;
+			errcode_t retval;
+
+			inline_data_size = ext2fs_inline_data_size(fs, ino);
+			if (inode->i_size != inline_data_size)
+				return 0;
 
-		len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
-		if (len == sizeof(inode->i_block))
-			return 0;
+			large_inode = (struct ext2_inode_large *)inode;
+
+			ext2fs_iget_extra_inode(fs, large_inode, &idata);
+			if (idata.inline_off == EXT4_MIN_INLINE_DATA_SIZE)
+				return 0;
+			inline_start = ext2fs_get_inline_xattr_pos(large_inode,
+								   &idata);
+			len = strnlen((char *)inline_start,
+				      idata.inline_size - EXT4_MIN_INLINE_DATA_SIZE);
+			if (len != idata.inline_size - EXT4_MIN_INLINE_DATA_SIZE)
+				return 0;
+			len += EXT4_MIN_INLINE_DATA_SIZE;
+		} else {
+			if (inode->i_size >= sizeof(inode->i_block))
+				return 0;
+
+			len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
+			if (len == sizeof(inode->i_block))
+				return 0;
+		}
 	}
 	if (len != inode->i_size)
 		return 0;
@@ -304,6 +329,14 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
 			goto fix;
 		}
 
+		/*
+		 * not do the following checks for inline_data because
+		 * other checks ensure that the content of inline data
+		 * is correct.
+		 */
+		if (strncmp(EXT2_EXT_ATTR_NAME(entry), "data", 4) == 0)
+			goto next;
+
 		/* attribute len eats this space */
 		remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
 
@@ -331,6 +364,7 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
 			goto fix;
 		}
 
+next:
 		remain -= entry->e_value_size;
 
 		entry = EXT2_EXT_ATTR_NEXT(entry);
@@ -1203,7 +1237,8 @@ void e2fsck_pass1(e2fsck_t ctx)
 			ctx->fs_sockets_count++;
 		} else
 			mark_inode_bad(ctx, ino);
-		if (!(inode->i_flags & EXT4_EXTENTS_FL)) {
+		if (!(inode->i_flags & EXT4_EXTENTS_FL) &&
+		    !(inode->i_flags & EXT4_INLINE_DATA_FL)) {
 			if (inode->i_block[EXT2_IND_BLOCK])
 				ctx->fs_ind_count++;
 			if (inode->i_block[EXT2_DIND_BLOCK])
@@ -1212,6 +1247,7 @@ void e2fsck_pass1(e2fsck_t ctx)
 				ctx->fs_tind_count++;
 		}
 		if (!(inode->i_flags & EXT4_EXTENTS_FL) &&
+		    !(inode->i_flags & EXT4_INLINE_DATA_FL) &&
 		    (inode->i_block[EXT2_IND_BLOCK] ||
 		     inode->i_block[EXT2_DIND_BLOCK] ||
 		     inode->i_block[EXT2_TIND_BLOCK] ||
@@ -2089,6 +2125,22 @@ static void check_blocks_extents(e2fsck_t ctx, struct problem_context *pctx,
 	ext2fs_extent_free(ehandle);
 }
 
+static void check_blocks_inline_data(e2fsck_t ctx, struct problem_context *pctx,
+				     struct process_block_struct *pb)
+{
+	if (pb->is_dir) {
+		pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist,
+						      pb->ino, 0, 0);
+		if (pctx->errcode) {
+			pctx->blk = 0;
+			pctx->num = 0;
+			fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
+			/* Should never get here */
+			ctx->flags |= E2F_FLAG_ABORT;
+		}
+	}
+}
+
 /*
  * This subroutine is called on each inode to account for all of the
  * blocks used by that inode.
@@ -2103,6 +2155,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 	int		bad_size = 0;
 	int		dirty_inode = 0;
 	int		extent_fs;
+	int		inlinedata_fs;
 	__u64		size;
 
 	pb.ino = ino;
@@ -2126,6 +2179,8 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 
 	extent_fs = (ctx->fs->super->s_feature_incompat &
                      EXT3_FEATURE_INCOMPAT_EXTENTS);
+	inlinedata_fs = (ctx->fs->super->s_feature_incompat &
+		     EXT4_FEATURE_INCOMPAT_INLINE_DATA);
 
 	if (inode->i_flags & EXT2_COMPRBLK_FL) {
 		if (fs->super->s_feature_incompat &
@@ -2149,6 +2204,8 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 	if (ext2fs_inode_has_valid_blocks2(fs, inode)) {
 		if (extent_fs && (inode->i_flags & EXT4_EXTENTS_FL))
 			check_blocks_extents(ctx, pctx, &pb);
+		else if (inlinedata_fs && (inode->i_flags & EXT4_INLINE_DATA_FL))
+			check_blocks_inline_data(ctx, pctx, &pb);
 		else {
 			pctx->errcode = ext2fs_block_iterate3(fs, ino,
 						pb.is_dir ? BLOCK_FLAG_HOLE : 0,
@@ -2191,7 +2248,8 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 		}
 	}
 
-	if (!pb.num_blocks && pb.is_dir) {
+	if (!pb.num_blocks && pb.is_dir &&
+	    !(inode->i_flags & EXT4_INLINE_DATA_FL)) {
 		if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
 			e2fsck_clear_inode(ctx, ino, inode, 0, "check_blocks");
 			ctx->fs_directory_count--;
@@ -2217,7 +2275,9 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 #endif
 	if (pb.is_dir) {
 		int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
-		if (inode->i_size & (fs->blocksize - 1))
+		if (inode->i_flags & EXT4_INLINE_DATA_FL)
+			;
+		else if (inode->i_size & (fs->blocksize - 1))
 			bad_size = 5;
 		else if (nblock > (pb.last_block + 1))
 			bad_size = 1;
diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c
index 05cbd10..6918fcc 100644
--- a/e2fsck/pass1b.c
+++ b/e2fsck/pass1b.c
@@ -315,8 +315,9 @@ static void pass1b(e2fsck_t ctx, char *block_buf)
 		pb.inode = &inode;
 		pb.cur_cluster = ~0;
 
-		if (ext2fs_inode_has_valid_blocks2(fs, &inode) ||
-		    (ino == EXT2_BAD_INO))
+		if ((ext2fs_inode_has_valid_blocks2(fs, &inode) ||
+		     (ino == EXT2_BAD_INO)) &&
+		    !(inode.i_flags & EXT4_INLINE_DATA_FL))
 			pctx.errcode = ext2fs_block_iterate3(fs, ino,
 					     BLOCK_FLAG_READ_ONLY, block_buf,
 					     process_pass1b_block, &pb);
diff --git a/lib/ext2fs/dblist_dir.c b/lib/ext2fs/dblist_dir.c
index d4d5111..cc54d7a 100644
--- a/lib/ext2fs/dblist_dir.c
+++ b/lib/ext2fs/dblist_dir.c
@@ -72,8 +72,12 @@ static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry2 *db_info,
 	ctx->dir = db_info->ino;
 	ctx->errcode = 0;
 
-	ret = ext2fs_process_dir_block(fs, &db_info->blk,
-				       db_info->blockcnt, 0, 0, priv_data);
+	if (ext2fs_has_inline_data(fs, ctx->dir))
+		ret = ext2fs_inline_data_iterate2(fs, ctx->dir, 0, NULL,
+						  ctx->func, ctx->priv_data);
+	else
+		ret = ext2fs_process_dir_block(fs, &db_info->blk,
+					       db_info->blockcnt, 0, 0, priv_data);
 	if ((ret & BLOCK_ABORT) && !ctx->errcode)
 		return DBLIST_ABORT;
 	return 0;
-- 
1.7.4.1


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

* [PATCH 32/36 v4] libext2fs: add read/write inline data functions
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (30 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 31/36 v4] e2fsck: make pass1 support inline data Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 33/36 v4] e2fsck: check inline data in pass2 Zheng Liu
                   ` (4 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Add read/write inline data functions for pass2.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 lib/ext2fs/dirblock.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/ext2fs/ext2fs.h   |    7 +++++
 2 files changed, 69 insertions(+), 0 deletions(-)

diff --git a/lib/ext2fs/dirblock.c b/lib/ext2fs/dirblock.c
index 54b2777..77e8f39 100644
--- a/lib/ext2fs/dirblock.c
+++ b/lib/ext2fs/dirblock.c
@@ -62,6 +62,45 @@ errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
 	return ext2fs_read_dir_block3(fs, block, buf, 0);
 }
 
+errcode_t ext2fs_read_dir_inline_data(ext2_filsys fs, ext2_ino_t ino, void *buf)
+{
+	struct ext2_inode_large *inode;
+	struct inline_data idata;
+
+	ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+	ext2fs_read_inode_full(fs, ino, (void *)inode, EXT2_INODE_SIZE(fs->super));
+
+	if (!(inode->i_flags & EXT4_INLINE_DATA_FL))
+		return -1;
+
+	memcpy(buf, inode->i_block, EXT4_MIN_INLINE_DATA_SIZE);
+
+	ext2fs_free_mem(&inode);
+	return 0;
+}
+
+errcode_t ext2fs_read_dir_inline_data_more(ext2_filsys fs, ext2_ino_t ino, void *buf)
+{
+	struct ext2_inode_large *inode;
+	struct inline_data idata;
+
+	ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+	ext2fs_read_inode_full(fs, ino, (void *)inode, EXT2_INODE_SIZE(fs->super));
+
+	if (!(inode->i_flags & EXT4_INLINE_DATA_FL))
+		return -1;
+
+	ext2fs_iget_extra_inode(fs, inode, &idata);
+	if (idata.inline_size == EXT4_MIN_INLINE_DATA_SIZE)
+		return 0;
+
+	memcpy(buf + EXT4_MIN_INLINE_DATA_SIZE,
+	       ext2fs_get_inline_xattr_pos(inode, &idata),
+	       idata.inline_size - EXT4_MIN_INLINE_DATA_SIZE);
+
+	ext2fs_free_mem(&inode);
+	return 0;
+}
 
 errcode_t ext2fs_write_dir_block4(ext2_filsys fs, blk64_t block,
 				  void *inbuf, int flags EXT2FS_ATTR((unused)),
@@ -111,3 +150,26 @@ errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
 	return ext2fs_write_dir_block3(fs, block, inbuf, 0);
 }
 
+errcode_t ext2fs_write_dir_inline_data(ext2_filsys fs, ext2_ino_t ino, void *buf)
+{
+	struct ext2_inode_large *inode;
+	struct inline_data idata;
+
+	ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+	ext2fs_read_inode_full(fs, ino, (void *)inode, EXT2_INODE_SIZE(fs->super));
+
+	memcpy(inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE);
+
+	ext2fs_iget_extra_inode(fs, inode, &idata);
+	if (idata.inline_size == EXT4_MIN_INLINE_DATA_SIZE)
+		goto out;
+
+	memcpy(ext2fs_get_inline_xattr_pos(inode, &idata),
+	       buf + EXT4_MIN_INLINE_DATA_SIZE,
+	       idata.inline_size - EXT4_MIN_INLINE_DATA_SIZE);
+
+out:
+	ext2fs_write_inode_full(fs, ino, (void *)inode, EXT2_INODE_SIZE(fs->super));
+	ext2fs_free_mem(&inode);
+	return 0;
+}
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index bacc14d..0bd5023 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1060,6 +1060,11 @@ extern errcode_t ext2fs_read_dir_block3(ext2_filsys fs, blk64_t block,
 					void *buf, int flags);
 extern errcode_t ext2fs_read_dir_block4(ext2_filsys fs, blk64_t block,
 					void *buf, int flags, ext2_ino_t ino);
+extern errcode_t ext2fs_read_dir_inline_data(ext2_filsys fs, ext2_ino_t ino,
+					     void *buf);
+extern errcode_t ext2fs_read_dir_inline_data_more(ext2_filsys fs,
+						  ext2_ino_t ino,
+						  void *buf);
 extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
 					void *buf);
 extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
@@ -1068,6 +1073,8 @@ extern errcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block,
 					 void *buf, int flags);
 extern errcode_t ext2fs_write_dir_block4(ext2_filsys fs, blk64_t block,
 					 void *buf, int flags, ext2_ino_t ino);
+extern errcode_t ext2fs_write_dir_inline_data(ext2_filsys fs, ext2_ino_t ino,
+					      void *buf);
 
 /* dirhash.c */
 extern errcode_t ext2fs_dirhash(int version, const char *name, int len,
-- 
1.7.4.1


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

* [PATCH 33/36 v4] e2fsck: check inline data in pass2
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (31 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 32/36 v4] libext2fs: add read/write inline data functions Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 34/36 v4] mke2fs: enable inline_data feature on ext4dev filesystem Zheng Liu
                   ` (3 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 e2fsck/pass2.c           |   64 +++++++++++++++++++++++++++++++++++++--------
 lib/ext2fs/inline_data.c |    4 +-
 2 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index e28af61..7267409 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -725,6 +725,15 @@ static void salvage_directory(ext2_filsys fs,
 	}
 }
 
+static int is_last_entry(ext2_filsys fs, ext2_ino_t ino, unsigned int offset,
+			 int csum_size)
+{
+	if (ext2fs_has_inline_data(fs, ino))
+		return (offset < ext2fs_inline_data_size(fs, ino));
+	else
+		return (offset < fs->blocksize - csum_size);
+}
+
 static int check_dir_block(ext2_filsys fs,
 			   struct ext2_db_entry2 *db,
 			   void *priv_data)
@@ -734,6 +743,7 @@ static int check_dir_block(ext2_filsys fs,
 	struct dx_dirblock_info	*dx_db = 0;
 #endif /* ENABLE_HTREE */
 	struct ext2_dir_entry 	*dirent, *prev;
+	struct ext2_inode	inode;
 	ext2_dirhash_t		hash;
 	unsigned int		offset = 0;
 	int			dir_modified = 0;
@@ -756,6 +766,7 @@ static int check_dir_block(ext2_filsys fs,
 	int	dx_csum_size = 0, de_csum_size = 0;
 	int	failed_csum = 0;
 	int	is_leaf = 1;
+	int	has_inline_data = 0;
 
 	cd = (struct check_dir_struct *) priv_data;
 	buf = cd->buf;
@@ -787,7 +798,8 @@ static int check_dir_block(ext2_filsys fs,
 	cd->pctx.dirent = 0;
 	cd->pctx.num = 0;
 
-	if (db->blk == 0) {
+	/* We don't need to allocate dir blocks for inline_data dir */
+	if (db->blk == 0 && !ext2fs_has_inline_data(fs, db->ino)) {
 		if (allocate_dir_block(ctx, db, buf, &cd->pctx))
 			return 0;
 		block_nr = db->blk;
@@ -808,7 +820,20 @@ static int check_dir_block(ext2_filsys fs,
 #endif
 
 	ehandler_operation(_("reading directory block"));
-	cd->pctx.errcode = ext2fs_read_dir_block4(fs, block_nr, buf, 0, ino);
+	ext2fs_read_inode(fs, ino, &inode);
+
+	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+				      EXT4_FEATURE_INCOMPAT_INLINE_DATA))
+		has_inline_data = (inode.i_flags & EXT4_INLINE_DATA_FL);
+
+	if (has_inline_data) {
+		cd->pctx.errcode = ext2fs_read_dir_inline_data(fs, ino, buf);
+		if (!cd->pctx.errcode)
+			cd->pctx.errcode = ext2fs_read_dir_inline_data_more(fs,
+								ino, buf);
+	} else
+		cd->pctx.errcode = ext2fs_read_dir_block4(fs, block_nr, buf,
+							  0, ino);
 	ehandler_operation(0);
 	if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
 		cd->pctx.errcode = 0; /* We'll handle this ourselves */
@@ -879,7 +904,7 @@ out_htree:
 #endif /* ENABLE_HTREE */
 
 	/* Verify checksum. */
-	if (is_leaf && de_csum_size) {
+	if (is_leaf && de_csum_size && !has_inline_data) {
 		/* No space for csum?  Rebuild dirs in pass 3A. */
 		if (!ext2fs_dirent_has_tail(fs, (struct ext2_dir_entry *)buf)) {
 			de_csum_size = 0;
@@ -1173,7 +1198,7 @@ skip_checksum:
 			(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
 		offset += rec_len;
 		dot_state++;
-	} while (offset < fs->blocksize - de_csum_size);
+	} while (is_last_entry(fs, ino, offset, de_csum_size));
 #if 0
 	printf("\n");
 #endif
@@ -1191,12 +1216,24 @@ skip_checksum:
 	}
 #endif /* ENABLE_HTREE */
 
-	if (offset != fs->blocksize - de_csum_size) {
-		cd->pctx.num = rec_len - (fs->blocksize - de_csum_size) +
-			       offset;
-		if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
-			dirent->rec_len = cd->pctx.num;
-			dir_modified++;
+	if (!has_inline_data) {
+		if (offset != fs->blocksize - de_csum_size) {
+			cd->pctx.num = rec_len -
+				(fs->blocksize - de_csum_size) +
+				offset;
+			if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
+				dirent->rec_len = cd->pctx.num;
+				dir_modified++;
+			}
+		}
+	} else {
+		if (offset != ext2fs_inline_data_size(fs, ino)) {
+			cd->pctx.num = rec_len + offset -
+				ext2fs_inline_data_size(fs, ino);
+			if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
+				dirent->rec_len = cd->pctx.num;
+				dir_modified++;
+			}
 		}
 	}
 	if (dir_modified) {
@@ -1210,8 +1247,11 @@ skip_checksum:
 write_and_fix:
 		if (e2fsck_dir_will_be_rehashed(ctx, ino))
 			ctx->fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
-		cd->pctx.errcode = ext2fs_write_dir_block4(fs, block_nr, buf,
-							   0, ino);
+		if (inode.i_flags & EXT4_INLINE_DATA_FL)
+			cd->pctx.errcode = ext2fs_write_dir_inline_data(fs, ino, buf);
+		else
+			cd->pctx.errcode = ext2fs_write_dir_block4(fs,
+							block_nr, buf, 0, ino);
 		if (e2fsck_dir_will_be_rehashed(ctx, ino))
 			ctx->fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
 		if (cd->pctx.errcode) {
diff --git a/lib/ext2fs/inline_data.c b/lib/ext2fs/inline_data.c
index 59483a6..3adab3c 100644
--- a/lib/ext2fs/inline_data.c
+++ b/lib/ext2fs/inline_data.c
@@ -575,7 +575,7 @@ int ext2fs_inline_data_in_extra(ext2_filsys fs, ext2_ino_t ino)
 	ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
 	ext2fs_read_inode_full(fs, ino, inode, EXT2_INODE_SIZE(fs->super));
 
-	ext2fs_iget_extra_inode(fs, inode, &idata);
+	ext2fs_iget_extra_inode(fs, (void *)inode, &idata);
 	ext2fs_free_mem(&inode);
 	if (idata.inline_off == 0 ||
 	    idata.inline_size == EXT4_MIN_INLINE_DATA_SIZE)
@@ -592,7 +592,7 @@ int ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino)
 	inode = (struct ext2_inode *) malloc(EXT2_INODE_SIZE(fs->super));
 	ext2fs_read_inode_full(fs, ino, inode, EXT2_INODE_SIZE(fs->super));
 
-	ext2fs_iget_extra_inode(fs, inode, &idata);
+	ext2fs_iget_extra_inode(fs, (void *)inode, &idata);
 	free(inode);
 	if (idata.inline_off == 0)
 		return 0;
-- 
1.7.4.1


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

* [PATCH 34/36 v4] mke2fs: enable inline_data feature on ext4dev filesystem
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (32 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 33/36 v4] e2fsck: check inline data in pass2 Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 35/36 v4] tests: change test f_bad_disconnected_inode to support inline_data feature Zheng Liu
                   ` (2 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Now inline_data feature gets stable.  So we enable it on ext4dev filesystem.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 misc/mke2fs.conf.in |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/misc/mke2fs.conf.in b/misc/mke2fs.conf.in
index 178733f..4c5dba7 100644
--- a/misc/mke2fs.conf.in
+++ b/misc/mke2fs.conf.in
@@ -16,7 +16,7 @@
 		inode_size = 256
 	}
 	ext4dev = {
-		features = has_journal,extent,huge_file,flex_bg,metadata_csum,64bit,dir_nlink,extra_isize
+		features = has_journal,extent,huge_file,flex_bg,metadata_csum,inline_data,64bit,dir_nlink,extra_isize
 		inode_size = 256
 		options = test_fs=1
 	}
-- 
1.7.4.1


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

* [PATCH 35/36 v4] tests: change test f_bad_disconnected_inode to support inline_data feature
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (33 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 34/36 v4] mke2fs: enable inline_data feature on ext4dev filesystem Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-07-31 11:48 ` [PATCH 36/36 v4] tune2fs: set " Zheng Liu
  2012-09-17  1:06 ` [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Theodore Ts'o
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

In this test, inode flag is some random data, and when we apply inline data
patch set we should need to handle it.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 tests/f_bad_disconnected_inode/expect.1 |   27 ++++++++++++---------------
 1 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/tests/f_bad_disconnected_inode/expect.1 b/tests/f_bad_disconnected_inode/expect.1
index 11862f6..9b7f7d8 100644
--- a/tests/f_bad_disconnected_inode/expect.1
+++ b/tests/f_bad_disconnected_inode/expect.1
@@ -2,7 +2,16 @@ Pass 1: Checking inodes, blocks, and sizes
 Inode 1 has EXTENTS_FL flag set on filesystem without extents support.
 Clear? yes
 
-Inode 15 has EXTENTS_FL flag set on filesystem without extents support.
+Inode 11 has INLINE_DATA_FL flag set on filesystem without inline data support.
+Clear? yes
+
+Inode 13 has INLINE_DATA_FL flag set on filesystem without inline data support.
+Clear? yes
+
+Inode 14 has INLINE_DATA_FL flag set on filesystem without inline data support.
+Clear? yes
+
+Inode 15 has INLINE_DATA_FL flag set on filesystem without inline data support.
 Clear? yes
 
 Inode 16 has EXTENTS_FL flag set on filesystem without extents support.
@@ -15,18 +24,6 @@ Pass 3: Checking directory connectivity
 Pass 4: Checking reference counts
 Inode 2 ref count is 4, should be 3.  Fix? yes
 
-i_file_acl for inode 13 (...) is 4218798225, should be zero.
-Clear? yes
-
-Inode 13 (...) has invalid mode (0117003).
-Clear? yes
-
-i_file_acl for inode 14 (...) is 2892851642, should be zero.
-Clear? yes
-
-Inode 14 (...) has invalid mode (0154247).
-Clear? yes

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

* [PATCH 36/36 v4] tune2fs: set inline_data feature
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (34 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 35/36 v4] tests: change test f_bad_disconnected_inode to support inline_data feature Zheng Liu
@ 2012-07-31 11:48 ` Zheng Liu
  2012-09-17  1:06 ` [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Theodore Ts'o
  36 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-07-31 11:48 UTC (permalink / raw)
  To: linux-ext4; +Cc: Zheng Liu

From: Zheng Liu <wenqing.lz@taobao.com>

Now inline_data feature can be set when ext_attr feature enabled.  Currently we
cannot clear this feature in tune2fs because we need to allocate some blocks for
inode which contains inline data, and it may exhaust all of disk space.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 misc/tune2fs.8.in |    5 +++++
 misc/tune2fs.c    |   15 ++++++++++++++-
 2 files changed, 19 insertions(+), 1 deletions(-)

diff --git a/misc/tune2fs.8.in b/misc/tune2fs.8.in
index e77dde7..c10696a 100644
--- a/misc/tune2fs.8.in
+++ b/misc/tune2fs.8.in
@@ -531,6 +531,11 @@ Setting the filesystem feature is equivalent to using the
 .B \-j
 option.
 .TP
+.B inline_data
+Allow data to be stored in inode.
+.B Tune2fs
+only supports setting this filesystem feature.
+.TP
 .B large_file
 Filesystem can contain files that are greater than 2GB.  (Modern kernels
 set this feature automatically when a file > 2GB is created.)
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 6a48009..1ee6a65 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -137,7 +137,8 @@ static __u32 ok_features[3] = {
 	EXT2_FEATURE_INCOMPAT_FILETYPE |
 		EXT3_FEATURE_INCOMPAT_EXTENTS |
 		EXT4_FEATURE_INCOMPAT_FLEX_BG |
-		EXT4_FEATURE_INCOMPAT_MMP,
+		EXT4_FEATURE_INCOMPAT_MMP |
+		EXT4_FEATURE_INCOMPAT_INLINE_DATA,
 	/* R/O compat */
 	EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
 		EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -991,6 +992,18 @@ mmp_error:
 		disable_uninit_bg(fs,
 				EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
 
+	if (FEATURE_ON(E2P_FEATURE_INCOMPAT,
+			EXT4_FEATURE_INCOMPAT_INLINE_DATA)) {
+		/* We cannot be enable inline_data when ext_attr disabled */
+		if (!(fs->super->s_feature_compat &
+		      EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+			fputs(_("The inline data feature can't "
+				"be set if the extend attribute feature "
+				"disabled.\n"), stderr);
+			return 1;
+		}
+	}
+
 	if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
 				EXT4_FEATURE_RO_COMPAT_QUOTA)) {
 		/*
-- 
1.7.4.1


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

* Re: [PATCH 05/36 v4] libext2fs: add EXT4_INLINE_DATA_FL flag for inode
  2012-07-31 11:47 ` [PATCH 05/36 v4] libext2fs: add EXT4_INLINE_DATA_FL flag for inode Zheng Liu
@ 2012-08-07 18:27   ` Theodore Ts'o
  0 siblings, 0 replies; 44+ messages in thread
From: Theodore Ts'o @ 2012-08-07 18:27 UTC (permalink / raw)
  To: Zheng Liu; +Cc: linux-ext4, Zheng Liu

On Tue, Jul 31, 2012 at 07:47:58PM +0800, Zheng Liu wrote:
> From: Zheng Liu <wenqing.lz@taobao.com>
> 
> Add EXT4_INLINE_DATA_FL flag.
> 
> Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>

I've accepted this patch into the next branch, along with a related
change to libe2p/pf.c so that lsattr will display the inline data
flag.

					- Ted

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

* Re: [PATCH 07/36 v4] libext2fs: add inline_data file
  2012-07-31 11:48 ` [PATCH 07/36 v4] libext2fs: add inline_data file Zheng Liu
@ 2012-08-07 18:40   ` Theodore Ts'o
  2012-08-13  8:07     ` Zheng Liu
  0 siblings, 1 reply; 44+ messages in thread
From: Theodore Ts'o @ 2012-08-07 18:40 UTC (permalink / raw)
  To: Zheng Liu; +Cc: linux-ext4, Zheng Liu

One major comment about the library functions.  The reason why we have
functions of the form ext2fs_foo(), ext2fs_foo2(), ext2fs_foo3(),
etc. is to preserve backwards compatibility of the ABI.  In general,
ext2fs_foo2() will have an extra parameter which wasn't in
ext2fs_foo(), and ext2fs_foo2() will have a superset of the
functionality of ext2fs_foo().  If later we need to add to add another
parameter to further extend the functionality of the function, we
might have an ext2fs_foo3(), which again will be a supserset of the
functionality of ext2fs_foo2().   

So in general, we only need to implement ext2fs_fooN(), and then
ext2fs_fooX where 0 <= X <= N simply call ext2fs_fooN with the extra
parameters defaulted out (usually to 0 or NULL).

It also follows that when we create a new function, there's no need to
do this.  So the fact that you have an ext2fs_inlinedata_iterate()
which just calls ext2fs_inline_data_iterate2() is not something you
need to do.

More seriously, ext2fs_inline_data_iterate3() has an implementation
which is completely different from that of
ext2fs_inline_data_iterate2(), and that's an immediate red flag.  This
means that these two functions are semantically different, and so they
should have fundamentally different names --- or you need to make
ext2fs_inline_data_iterate3() a strict superset of the functionality
of ext2fs_inline_data_iterate2().

Also, I note that there are a number of patches which basically do
this:

-	retval = ext2fs_dir_iterate2(current_fs, inode_num, 0,
-				    0, rmdir_proc, &rds);
+	if (ext2fs_has_inline_data(current_fs, inode_num))
+		retval = ext2fs_inline_data_iterate2(current_fs, inode_num, 0,
+						     0, rmdir_proc, &rds);
+	else
+		retval = ext2fs_dir_iterate2(current_fs, inode_num, 0,
+					    0, rmdir_proc, &rds);

The much better thing to do is to make ext2fs_dir_iterate2() check to
see if the inode has inline data, and if so, to call
ext2fs_inline_data_iterate2() directly.   This has a couple of benefits.

The first is it will reduce the number of patches we need to apply.
More importantly, it means that existing programs that don't know
about inline data, but who happen to use ext2fs_dir_iterate(), will be
able to work automatically, without requiring code changes.  It's also
much cleaner from a conceptual point of view, since the
ext2fs_dir_iterate abstraction shouldn't need to expose to the user
whether the directory data is inline or in a separate data block.

Regards,

						- Ted

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

* Re: [PATCH 06/36 v4] libext2fs: add data structures for inline data feature
  2012-07-31 11:47 ` [PATCH 06/36 v4] libext2fs: add data structures for inline data feature Zheng Liu
@ 2012-08-07 18:50   ` Theodore Ts'o
  2012-08-13  8:10     ` Zheng Liu
  0 siblings, 1 reply; 44+ messages in thread
From: Theodore Ts'o @ 2012-08-07 18:50 UTC (permalink / raw)
  To: Zheng Liu; +Cc: linux-ext4, Zheng Liu

On Tue, Jul 31, 2012 at 07:47:59PM +0800, Zheng Liu wrote:
> +struct ext2_ext_attr_ibody_header {
> +	__u32	h_magic;
> +};
> +

I've searched through the entire patch series, and I don't find any
usage of h_magic, and in fact the only place this structure definition
is used is in ext2fs_get_inline_xattr_pos().

So that's a bit worrying; if this is a magic number, then it should be
checked (and an error returned if the magic number is not what we
expect it tobe).  Add checks into e2fsck would also be a really good
idea.  Also, what is the value that h_magic is epxected to be?  It
needs to be defined here.

It's also clear from looking at this function that this patch
significantly changes the layout of the extended attribute block of
data.  It would be a really good idea to add some ascii art to
document exactly what is going on.  A diagram so it's obvious to
future developers about the data layout is really needed.

Regards,

						- Ted

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

* Re: [PATCH 07/36 v4] libext2fs: add inline_data file
  2012-08-07 18:40   ` Theodore Ts'o
@ 2012-08-13  8:07     ` Zheng Liu
  0 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-08-13  8:07 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: linux-ext4, Zheng Liu

On Tue, Aug 07, 2012 at 02:40:02PM -0400, Theodore Ts'o wrote:
> One major comment about the library functions.  The reason why we have
> functions of the form ext2fs_foo(), ext2fs_foo2(), ext2fs_foo3(),
> etc. is to preserve backwards compatibility of the ABI.  In general,
> ext2fs_foo2() will have an extra parameter which wasn't in
> ext2fs_foo(), and ext2fs_foo2() will have a superset of the
> functionality of ext2fs_foo().  If later we need to add to add another
> parameter to further extend the functionality of the function, we
> might have an ext2fs_foo3(), which again will be a supserset of the
> functionality of ext2fs_foo2().   
> 
> So in general, we only need to implement ext2fs_fooN(), and then
> ext2fs_fooX where 0 <= X <= N simply call ext2fs_fooN with the extra
> parameters defaulted out (usually to 0 or NULL).
> 
> It also follows that when we create a new function, there's no need to
> do this.  So the fact that you have an ext2fs_inlinedata_iterate()
> which just calls ext2fs_inline_data_iterate2() is not something you
> need to do.
> 
> More seriously, ext2fs_inline_data_iterate3() has an implementation
> which is completely different from that of
> ext2fs_inline_data_iterate2(), and that's an immediate red flag.  This
> means that these two functions are semantically different, and so they
> should have fundamentally different names --- or you need to make
> ext2fs_inline_data_iterate3() a strict superset of the functionality
> of ext2fs_inline_data_iterate2().
> 
> Also, I note that there are a number of patches which basically do
> this:
> 
> -	retval = ext2fs_dir_iterate2(current_fs, inode_num, 0,
> -				    0, rmdir_proc, &rds);
> +	if (ext2fs_has_inline_data(current_fs, inode_num))
> +		retval = ext2fs_inline_data_iterate2(current_fs, inode_num, 0,
> +						     0, rmdir_proc, &rds);
> +	else
> +		retval = ext2fs_dir_iterate2(current_fs, inode_num, 0,
> +					    0, rmdir_proc, &rds);
> 
> The much better thing to do is to make ext2fs_dir_iterate2() check to
> see if the inode has inline data, and if so, to call
> ext2fs_inline_data_iterate2() directly.   This has a couple of benefits.
> 
> The first is it will reduce the number of patches we need to apply.
> More importantly, it means that existing programs that don't know
> about inline data, but who happen to use ext2fs_dir_iterate(), will be
> able to work automatically, without requiring code changes.  It's also
> much cleaner from a conceptual point of view, since the
> ext2fs_dir_iterate abstraction shouldn't need to expose to the user
> whether the directory data is inline or in a separate data block.

Thanks for patient explanation.  I will fix the patches according to
your advice.

Regards,
Zheng

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

* Re: [PATCH 06/36 v4] libext2fs: add data structures for inline data feature
  2012-08-07 18:50   ` Theodore Ts'o
@ 2012-08-13  8:10     ` Zheng Liu
  0 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-08-13  8:10 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: linux-ext4, Zheng Liu

On Tue, Aug 07, 2012 at 02:50:53PM -0400, Theodore Ts'o wrote:
> On Tue, Jul 31, 2012 at 07:47:59PM +0800, Zheng Liu wrote:
> > +struct ext2_ext_attr_ibody_header {
> > +	__u32	h_magic;
> > +};
> > +
> 
> I've searched through the entire patch series, and I don't find any
> usage of h_magic, and in fact the only place this structure definition
> is used is in ext2fs_get_inline_xattr_pos().
> 
> So that's a bit worrying; if this is a magic number, then it should be
> checked (and an error returned if the magic number is not what we
> expect it tobe).  Add checks into e2fsck would also be a really good
> idea.  Also, what is the value that h_magic is epxected to be?  It
> needs to be defined here.
> 
> It's also clear from looking at this function that this patch
> significantly changes the layout of the extended attribute block of
> data.  It would be a really good idea to add some ascii art to
> document exactly what is going on.  A diagram so it's obvious to
> future developers about the data layout is really needed.

Thanks, I will fix it.

Regards,
Zheng

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

* Re: [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data
  2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
                   ` (35 preceding siblings ...)
  2012-07-31 11:48 ` [PATCH 36/36 v4] tune2fs: set " Zheng Liu
@ 2012-09-17  1:06 ` Theodore Ts'o
  2012-09-17  2:04   ` Zheng Liu
  36 siblings, 1 reply; 44+ messages in thread
From: Theodore Ts'o @ 2012-09-17  1:06 UTC (permalink / raw)
  To: Zheng Liu; +Cc: linux-ext4, Zheng Liu

On Tue, Jul 31, 2012 at 07:47:53PM +0800, Zheng Liu wrote:
> Hi list,
> 
> Here is v4 for making e2fsprogs support inline data.

Hi Zheng,

I see Tao Ma has released a new set of kernel patches for inline data.

Is there an updated version for the e2fsprogs patches that I should
use when testing/evaluating the inline data patch?

Thanks!!

						- Ted

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

* Re: [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data
  2012-09-17  1:06 ` [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Theodore Ts'o
@ 2012-09-17  2:04   ` Zheng Liu
  0 siblings, 0 replies; 44+ messages in thread
From: Zheng Liu @ 2012-09-17  2:04 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: linux-ext4, Zheng Liu

On Sun, Sep 16, 2012 at 09:06:45PM -0400, Theodore Ts'o wrote:
> On Tue, Jul 31, 2012 at 07:47:53PM +0800, Zheng Liu wrote:
> > Hi list,
> > 
> > Here is v4 for making e2fsprogs support inline data.
> 
> Hi Zheng,
> 
> I see Tao Ma has released a new set of kernel patches for inline data.
> 
> Is there an updated version for the e2fsprogs patches that I should
> use when testing/evaluating the inline data patch?

Hi Ted,

Sorry about that.  Now mke2fs, tune2fs, and e2fsck has an updated
version for e2fsprogs, but there still has some works to be done
in debugfs.  I could finish it at this week, and send it out.

Regards,
Zheng

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

end of thread, other threads:[~2012-09-17  1:53 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-31 11:47 [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Zheng Liu
2012-07-31 11:47 ` [PATCH 01/36 v4] libext2fs: add EXT4_FEATURE_INCOMPAT_INLINE_DATA flag Zheng Liu
2012-07-31 11:47 ` [PATCH 02/36 v4] mke2fs: make it support inline data feature Zheng Liu
2012-07-31 11:47 ` [PATCH 03/36 v4] mke2fs: add inline_data feature in mke2fs's manpage Zheng Liu
2012-07-31 11:47 ` [PATCH 04/36 v4] libext2fs: add ext2fs_find_entry_ext_attr function Zheng Liu
2012-07-31 11:47 ` [PATCH 05/36 v4] libext2fs: add EXT4_INLINE_DATA_FL flag for inode Zheng Liu
2012-08-07 18:27   ` Theodore Ts'o
2012-07-31 11:47 ` [PATCH 06/36 v4] libext2fs: add data structures for inline data feature Zheng Liu
2012-08-07 18:50   ` Theodore Ts'o
2012-08-13  8:10     ` Zheng Liu
2012-07-31 11:48 ` [PATCH 07/36 v4] libext2fs: add inline_data file Zheng Liu
2012-08-07 18:40   ` Theodore Ts'o
2012-08-13  8:07     ` Zheng Liu
2012-07-31 11:48 ` [PATCH 08/36 v4] debugfs: make ncheck cmd support inline data Zheng Liu
2012-07-31 11:48 ` [PATCH 09/36 v4] debugfs: make icheck " Zheng Liu
2012-07-31 11:48 ` [PATCH 10/36 v4] debugfs: make chroot and cd " Zheng Liu
2012-07-31 11:48 ` [PATCH 11/36 v4] debugfs: make ls " Zheng Liu
2012-07-31 11:48 ` [PATCH 12/36 v4] debugfs: make stat " Zheng Liu
2012-07-31 11:48 ` [PATCH 13/36 v4] debugfs: make blocks " Zheng Liu
2012-07-31 11:48 ` [PATCH 14/36 v4] debugfs: make filefrag " Zheng Liu
2012-07-31 11:48 ` [PATCH 15/36 v4] debugfs: make link " Zheng Liu
2012-07-31 11:48 ` [PATCH 16/36 v4] debugfs: make unlink " Zheng Liu
2012-07-31 11:48 ` [PATCH 17/36 v4] debugfs: make mkdir " Zheng Liu
2012-07-31 11:48 ` [PATCH 18/36 v4] debugfs: make rmdir " Zheng Liu
2012-07-31 11:48 ` [PATCH 19/36 v4] debugfs: make rm and kill_file " Zheng Liu
2012-07-31 11:48 ` [PATCH 20/36 v4] debugfs: make pwd " Zheng Liu
2012-07-31 11:48 ` [PATCH 21/36 v4] debugfs: make expand_dir " Zheng Liu
2012-07-31 11:48 ` [PATCH 22/36 v4] debugfs: make lsdel " Zheng Liu
2012-07-31 11:48 ` [PATCH 23/36 v4] debugfs: make undelete " Zheng Liu
2012-07-31 11:48 ` [PATCH 24/36 v4] debugfs: make dump and cat " Zheng Liu
2012-07-31 11:48 ` [PATCH 25/36 v4] debugfs: make rdump " Zheng Liu
2012-07-31 11:48 ` [PATCH 26/36 v4] debugfs: make dirsearch " Zheng Liu
2012-07-31 11:48 ` [PATCH 27/36 v4] debugfs: make bmap " Zheng Liu
2012-07-31 11:48 ` [PATCH 28/36 v4] debugfs: make punch/truncate " Zheng Liu
2012-07-31 11:48 ` [PATCH 29/36 v4] e2fsck: add three problem descriptions in pass1 Zheng Liu
2012-07-31 11:48 ` [PATCH 30/36 v4] e2fsck: check incorrect inline data flag Zheng Liu
2012-07-31 11:48 ` [PATCH 31/36 v4] e2fsck: make pass1 support inline data Zheng Liu
2012-07-31 11:48 ` [PATCH 32/36 v4] libext2fs: add read/write inline data functions Zheng Liu
2012-07-31 11:48 ` [PATCH 33/36 v4] e2fsck: check inline data in pass2 Zheng Liu
2012-07-31 11:48 ` [PATCH 34/36 v4] mke2fs: enable inline_data feature on ext4dev filesystem Zheng Liu
2012-07-31 11:48 ` [PATCH 35/36 v4] tests: change test f_bad_disconnected_inode to support inline_data feature Zheng Liu
2012-07-31 11:48 ` [PATCH 36/36 v4] tune2fs: set " Zheng Liu
2012-09-17  1:06 ` [PATCH 00/36 v4] e2fsprogs: make e2fsprogs support inline data Theodore Ts'o
2012-09-17  2:04   ` Zheng Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.