[Ocfs2-tools-devel] [PATCH 06/11] libocfs2: read/write now know inline data.

Tao Ma tao.ma at oracle.com
Thu Jul 24 17:46:28 PDT 2008


yes, you are right, here is the new updated patch.

We initialize a file with extent list, but if the user write some
data into a file which can be fit for a inline data, it will be
inserted into inode. When the file content exceeds the limit, they
will be moved out to extent list.

Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
Signed-off-by: Tao ma <tao.ma at oracle.com>
---
 include/ocfs2/ocfs2.h |    9 +++
 libocfs2/alloc.c      |   32 ++++++++-
 libocfs2/fileio.c     |  177 ++++++++++++++++++++++++++++++++++++++++++++++++-
 libocfs2/ocfs2_err.et |    3 +
 4 files changed, 214 insertions(+), 7 deletions(-)

diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 9d0f61b..4739ac0 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -479,6 +479,9 @@ errcode_t ocfs2_cached_inode_insert_extent(ocfs2_cached_inode *ci,
 					   uint32_t cpos, uint64_t c_blkno,
 					   uint32_t clusters, uint16_t flag);
 
+void ocfs2_dinode_new_extent_list(ocfs2_filesys *fs, struct ocfs2_dinode *di);
+void ocfs2_set_inode_data_inline(ocfs2_filesys *fs, struct ocfs2_dinode *di);
+errcode_t ocfs2_convert_inline_data_to_extents(ocfs2_cached_inode *ci);
 errcode_t ocfs2_new_inode(ocfs2_filesys *fs, uint64_t *ino, int mode);
 errcode_t ocfs2_new_system_inode(ocfs2_filesys *fs, uint64_t *ino, int mode, int flags);
 errcode_t ocfs2_delete_inode(ocfs2_filesys *fs, uint64_t ino);
@@ -786,6 +789,12 @@ static inline int ocfs2_uses_extended_slot_map(struct ocfs2_super_block *osb)
 	return 0;
 }
 
+static inline int ocfs2_support_inline_data(struct ocfs2_super_block *osb)
+{
+	if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_INLINE_DATA)
+		return 1;
+	return 0;
+}
 
 /*
  * shamelessly lifted from the kernel
diff --git a/libocfs2/alloc.c b/libocfs2/alloc.c
index 3e54629..b6d440f 100644
--- a/libocfs2/alloc.c
+++ b/libocfs2/alloc.c
@@ -120,6 +120,33 @@ static int ocfs2_clusters_per_group(int block_size, int cluster_size_bits)
 	return (megabytes << ONE_MB_SHIFT) >> cluster_size_bits;
 }
 
+static inline void ocfs2_zero_dinode_id2(int blocksize,
+					 struct ocfs2_dinode *di)
+{
+	memset(&di->id2, 0, blocksize - offsetof(struct ocfs2_dinode, id2));
+}
+
+void ocfs2_dinode_new_extent_list(ocfs2_filesys *fs,
+				  struct ocfs2_dinode *di)
+{
+	ocfs2_zero_dinode_id2(fs->fs_blocksize, di);
+
+	di->id2.i_list.l_tree_depth = 0;
+	di->id2.i_list.l_next_free_rec = 0;
+	di->id2.i_list.l_count = ocfs2_extent_recs_per_inode(fs->fs_blocksize);
+}
+
+void ocfs2_set_inode_data_inline(ocfs2_filesys *fs, struct ocfs2_dinode *di)
+{
+	struct ocfs2_inline_data *idata = &di->id2.i_data;
+
+	ocfs2_zero_dinode_id2(fs->fs_blocksize, di);
+
+	idata->id_count = ocfs2_max_inline_data(fs->fs_blocksize);
+
+	di->i_dyn_features |= OCFS2_INLINE_DATA_FL;
+}
+
 static void ocfs2_init_inode(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 			     int16_t slot, uint64_t gd_blkno,
 			     uint64_t blkno, uint16_t mode,
@@ -171,10 +198,7 @@ static void ocfs2_init_inode(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 	if (flags & OCFS2_SUPER_BLOCK_FL)
 		return ;
 
-	fel = &di->id2.i_list;
-	fel->l_tree_depth = 0;
-	fel->l_next_free_rec = 0;
-	fel->l_count = ocfs2_extent_recs_per_inode(fs->fs_blocksize);
+	ocfs2_dinode_new_extent_list(fs, di);
 }
 
 static void ocfs2_init_eb(ocfs2_filesys *fs,
diff --git a/libocfs2/fileio.c b/libocfs2/fileio.c
index 9005d6e..4000354 100644
--- a/libocfs2/fileio.c
+++ b/libocfs2/fileio.c
@@ -65,6 +65,31 @@ static int read_whole_func(ocfs2_filesys *fs,
 	return 0;
 }
 
+static errcode_t ocfs2_inline_data_read(struct ocfs2_dinode *di, void *buf,
+					uint32_t count, uint64_t offset,
+					uint32_t *got)
+{
+	struct ocfs2_inline_data *id;
+	uint8_t *p;
+
+	if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL))
+		return OCFS2_ET_INVALID_ARGUMENT;
+
+	id = &(di->id2.i_data);
+	*got = 0;
+
+	if (offset > id->id_count)
+		return 0;
+
+	p = (__u8 *) &(id->id_data);
+	p += offset;
+
+	*got = ocfs2_min((di->i_size - offset), (uint64_t)count);
+	memcpy(buf, p, *got);
+
+	return 0;
+}
+
 errcode_t ocfs2_read_whole_file(ocfs2_filesys *fs,
 				uint64_t blkno,
 				char **buf,
@@ -95,11 +120,14 @@ errcode_t ocfs2_read_whole_file(ocfs2_filesys *fs,
 		goto out_free;
 
 	retval = ocfs2_malloc_blocks(fs->fs_io,
-				     ocfs2_clusters_to_blocks(fs, di->i_clusters),
+				     ocfs2_blocks_in_bytes(fs, di->i_size),
 				     buf);
 	if (retval)
 		goto out_free;
 
+	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL)
+		return ocfs2_inline_data_read(di, *buf, di->i_size, 0, len);
+
 	ctx.buf = *buf;
 	ctx.ptr = *buf;
 	ctx.size = di->i_size;
@@ -140,6 +168,10 @@ errcode_t ocfs2_file_read(ocfs2_cached_inode *ci, void *buf, uint32_t count,
 	uint64_t	num_blocks;
 	uint16_t	extent_flags;
 
+	if (ci->ci_inode->i_dyn_features & OCFS2_INLINE_DATA_FL)
+		return ocfs2_inline_data_read(ci->ci_inode, buf, count,
+					      offset, got);
+
 	/* o_direct requires aligned io */
 	tmp = fs->fs_blocksize - 1;
 	if ((count & tmp) || (offset & (uint64_t)tmp) ||
@@ -232,8 +264,31 @@ bail:
 	return ret;
 }
 
-errcode_t ocfs2_file_write(ocfs2_cached_inode *ci, void *buf, uint32_t count,
-			   uint64_t offset, uint32_t *wrote)
+static errcode_t ocfs2_inline_data_write(struct ocfs2_dinode *di, void *buf,
+					 uint32_t count, uint64_t offset)
+{
+	struct ocfs2_inline_data *id;
+	uint8_t *p;
+
+	if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL))
+		return OCFS2_ET_INVALID_ARGUMENT;
+
+	id = &(di->id2.i_data);
+
+	if (offset + count > id->id_count)
+		return OCFS2_ET_NO_SPACE;
+
+	p = (__u8 *) &(id->id_data);
+	p += offset;
+
+	memcpy(p, buf, count);
+
+	return 0;
+}
+
+static errcode_t ocfs2_file_block_write(ocfs2_cached_inode *ci,
+					void *buf, uint32_t count,
+					uint64_t offset, uint32_t *wrote)
 {
 	ocfs2_filesys	*fs = ci->ci_fs;
 	errcode_t	ret = 0;
@@ -403,6 +458,122 @@ errcode_t ocfs2_file_write(ocfs2_cached_inode *ci, void *buf, uint32_t count,
 	return ret;
 }
 
+static inline int ocfs2_size_fits_inline_data(struct ocfs2_dinode *di,
+					      uint64_t new_size)
+{
+	if (new_size <= di->id2.i_data.id_count)
+		return 1;
+	return 0;
+}
+
+errcode_t ocfs2_convert_inline_data_to_extents(ocfs2_cached_inode *ci)
+{
+	errcode_t ret;
+	uint32_t bytes, n_clusters;
+	uint64_t p_start;
+	char *inline_data = NULL;
+	struct ocfs2_dinode *di = ci->ci_inode;
+	ocfs2_filesys *fs = ci->ci_fs;
+	uint64_t bpc = fs->fs_clustersize/fs->fs_blocksize;
+
+	if (di->i_size) {
+		ret = ocfs2_malloc_block(fs->fs_io, &inline_data);
+		if (ret)
+			goto out;
+
+		ret = ocfs2_inline_data_read(di, inline_data,
+					     fs->fs_blocksize,
+					     0, &bytes);
+		if (ret)
+			goto out;
+	}
+
+	ocfs2_dinode_new_extent_list(fs, di);
+	di->i_dyn_features &= ~OCFS2_INLINE_DATA_FL;
+
+	ret = ocfs2_new_clusters(fs, 1, 1, &p_start, &n_clusters);
+	if (ret || n_clusters == 0)
+		goto out;
+
+	ret = empty_blocks(fs, p_start, bpc);
+	if (ret)
+		goto out;
+
+	if (di->i_size) {
+		ret = io_write_block(fs->fs_io, p_start, 1, inline_data);
+		if (ret)
+			goto out;
+	}
+
+	ret = ocfs2_cached_inode_insert_extent(ci, 0, p_start, n_clusters, 0);
+	if (ret)
+		goto out;
+
+	ret = ocfs2_write_cached_inode(fs, ci);
+out:
+	if (inline_data)
+		ocfs2_free(&inline_data);
+	return ret;
+}
+
+static errcode_t ocfs2_try_to_write_inline_data(ocfs2_cached_inode *ci,
+						void *buf, uint32_t count,
+						uint64_t offset)
+{
+	int ret, written = 0;
+	uint64_t end = offset + count;
+	ocfs2_filesys *fs = ci->ci_fs;
+	struct ocfs2_dinode *di = ci->ci_inode;
+
+	/* Handle inodes which already have inline data 1st. */
+	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
+		if (ocfs2_size_fits_inline_data(ci->ci_inode, end))
+			goto do_inline_write;
+
+		/*
+		 * The write won't fit - we have to give this inode an
+		 * inline extent list now.
+		 */
+		ret = ocfs2_convert_inline_data_to_extents(ci);
+		if (!ret)
+			ret = OCFS2_ET_CANNOT_INLINE_DATA;
+		goto out;
+	}
+
+	if (di->i_clusters > 0 || end > ocfs2_max_inline_data(fs->fs_blocksize))
+		return OCFS2_ET_CANNOT_INLINE_DATA;
+
+	ocfs2_set_inode_data_inline(fs, ci->ci_inode);
+	ci->ci_inode->i_dyn_features |= OCFS2_INLINE_DATA_FL;
+
+do_inline_write:
+	ret = ocfs2_inline_data_write(di, buf, count, offset);
+	if (ret)
+		goto out;
+
+	ret = ocfs2_write_cached_inode(fs, ci);
+out:
+	return ret;
+}
+
+errcode_t ocfs2_file_write(ocfs2_cached_inode *ci,
+			   void *buf, uint32_t count,
+			   uint64_t offset, uint32_t *wrote)
+{
+	errcode_t ret;
+	ocfs2_filesys *fs = ci->ci_fs;
+
+	if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super))) {
+		ret = ocfs2_try_to_write_inline_data(ci, buf, count, offset);
+		if (!ret || ret != OCFS2_ET_CANNOT_INLINE_DATA)
+			goto out;
+	}
+
+	ret = ocfs2_file_block_write(ci, buf, count, offset, wrote);
+out:
+	return ret;
+}
+
 /*
  * FIXME: port the reset of e2fsprogs/lib/ext2fs/fileio.c
  */
diff --git a/libocfs2/ocfs2_err.et b/libocfs2/ocfs2_err.et
index 35dee5a..2001585 100644
--- a/libocfs2/ocfs2_err.et
+++ b/libocfs2/ocfs2_err.et
@@ -168,4 +168,7 @@ ec	OCFS2_ET_NO_BACKUP_SUPER,
 ec      OCFS2_ET_TOO_MANY_SLOTS,
         "Too many slots for slot map"
 
+ec	OCFS2_ET_CANNOT_INLINE_DATA,
+	"Can't write the data inline"
+
 	end
-- 
1.5.4.GIT




More information about the Ocfs2-tools-devel mailing list