[Ocfs2-tools-devel] [PATCH 06/11] libocfs2: read/write now know inline data.
Tao Ma
tao.ma at oracle.com
Tue Jul 22 15:52:25 PDT 2008
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 | 181 ++++++++++++++++++++++++++++++++++++++++++++++++-
libocfs2/ocfs2_err.et | 3 +
4 files changed, 218 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..36758ed 100644
--- a/libocfs2/fileio.c
+++ b/libocfs2/fileio.c
@@ -65,6 +65,33 @@ 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;
+ uint64_t isize;
+ uint8_t *p;
+
+ if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL))
+ return OCFS2_ET_INVALID_ARGUMENT;
+
+ id = &(di->id2.i_data);
+ isize = di->i_size;
+ *got = 0;
+
+ if (offset > id->id_count)
+ return 0;
+
+ p = (__u8 *) &(id->id_data);
+ p += offset;
+
+ *got = ocfs2_min((isize - 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 +122,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 +170,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 +266,33 @@ 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;
+ uint64_t isize;
+ uint8_t *p;
+
+ if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL))
+ return OCFS2_ET_INVALID_ARGUMENT;
+
+ id = &(di->id2.i_data);
+ isize = di->i_size;
+
+ 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 +462,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