[Ocfs2-tools-devel] [PATCH 1/1] Add truncate for "clear sparse"
function in tunefs.
Tao Ma
tao.ma at oracle.com
Mon Nov 12 22:59:08 PST 2007
When we remove "sparse" flag from the OCFS2 volume, we need to truncate
all the blocks that exceed i_size. They are illegal in a non-sparse
OCFS2 system.
Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
tunefs.ocfs2/sparse_file.c | 65 +++++++++++++++++++++++++++++++++++++++-----
1 files changed, 58 insertions(+), 7 deletions(-)
diff --git a/tunefs.ocfs2/sparse_file.c b/tunefs.ocfs2/sparse_file.c
index 8ef6710..427dae9 100644
--- a/tunefs.ocfs2/sparse_file.c
+++ b/tunefs.ocfs2/sparse_file.c
@@ -67,10 +67,14 @@ struct unwritten_list {
* unwritten_list. Since filling up a hole may need a new extent record and
* lead to some new extent block, the total hole number in the sparse file
* will also be recorded.
+ *
+ * Some sparse file may also have some clusters which exceed the limit of
+ * i_size, and they should be truncated.
*/
struct sparse_file {
uint64_t blkno;
uint32_t holes_num;
+ int truncate;
struct hole_list *holes;
struct unwritten_list *unwritten;
struct sparse_file *next;
@@ -208,6 +212,7 @@ static void list_sparse_iterate(void *priv_data,
* Iterate a file.
* Call "func" when we meet with a hole.
* Call "unwritten_func" when we meet with unwritten clusters.
+ * Call "seen_exceed" when we see some clusters exceed i_size.
*/
static errcode_t iterate_file(ocfs2_filesys *fs,
struct ocfs2_dinode *di,
@@ -218,10 +223,12 @@ static errcode_t iterate_file(ocfs2_filesys *fs,
uint32_t start,
uint32_t len,
uint64_t p_start),
+ void (*seen_exceed)(void *priv_data),
void *priv_data)
{
errcode_t ret;
uint32_t clusters, v_cluster = 0, p_cluster, num_clusters;
+ uint32_t get_clusters = 0;
uint64_t p_blkno;
uint16_t extent_flags;
ocfs2_cached_inode *ci = NULL;
@@ -250,7 +257,8 @@ static errcode_t iterate_file(ocfs2_filesys *fs,
if (func)
func(priv_data, v_cluster, num_clusters);
- }
+ } else
+ get_clusters += num_clusters;
if ((extent_flags & OCFS2_EXT_UNWRITTEN) && unwritten_func) {
p_blkno = ocfs2_clusters_to_blocks(fs, p_cluster);
@@ -261,6 +269,17 @@ static errcode_t iterate_file(ocfs2_filesys *fs,
v_cluster += num_clusters;
}
+ /*
+ * If there are some extra clusters we need to record them.
+ * There are 2 scenarios:
+ * 1. there are more cotinguous clusters allocated in which case
+ * get_clusters > di->i_clusters
+ * 2. there are more clusters allocated after i_size in which case
+ * get_clusters < di->i_clusters
+ */
+ if (get_clusters != di->i_clusters && seen_exceed)
+ seen_exceed(priv_data);
+
bail:
if (ci)
ocfs2_free_cached_inode(fs, ci);
@@ -297,7 +316,7 @@ static errcode_t list_sparse_file(ocfs2_filesys *fs,
}
}
- ret = iterate_file(fs, di, ctxt->func, NULL, ctxt);
+ ret = iterate_file(fs, di, ctxt->func, NULL, NULL, ctxt);
if (ret)
goto bail;
@@ -521,7 +540,11 @@ out:
return ret;
}
-static errcode_t set_func(ocfs2_filesys *fs, struct ocfs2_dinode *di)
+/*
+ * Truncate file according to i_size.
+ * All allocated clusters which exceeds i_size will be released.
+ */
+static errcode_t truncate_file(ocfs2_filesys *fs, struct ocfs2_dinode *di)
{
errcode_t ret;
uint32_t new_clusters;
@@ -558,7 +581,7 @@ errcode_t set_sparse_file_flag(ocfs2_filesys *fs, char *progname)
if (ocfs2_sparse_alloc(super))
return 0;
- ret = iterate_all_regular(fs, progname, set_func);
+ ret = iterate_all_regular(fs, progname, truncate_file);
if (ret)
goto bail;
@@ -634,6 +657,14 @@ static void add_unwritten(void *priv_data, uint32_t start,
ctxt->files->unwritten = unwritten;
}
+static void add_truncate(void *priv_data)
+{
+ struct clear_hole_unwritten_ctxt *ctxt =
+ (struct clear_hole_unwritten_ctxt *)priv_data;
+
+ ctxt->files->truncate = 1;
+}
+
static errcode_t calc_hole_and_unwritten(ocfs2_filesys *fs,
struct ocfs2_dinode *di)
{
@@ -652,14 +683,18 @@ static errcode_t calc_hole_and_unwritten(ocfs2_filesys *fs,
file->blkno = di->i_blkno;
old_files = clear_ctxt.files;
clear_ctxt.files = file;
- ret = iterate_file(fs, di, add_hole, add_unwritten, &clear_ctxt);
+ ret = iterate_file(fs, di, add_hole, add_unwritten,
+ add_truncate, &clear_ctxt);
if (ret || clear_ctxt.ret) {
clear_ctxt.files = old_files;
goto bail;
}
- /* If there is no hole or unwritten extents in the file, free it. */
- if (!file->unwritten && !file->holes) {
+ /*
+ * If there is no hole or unwritten extents in the file and we don't
+ * need to truncate it, just free it.
+ */
+ if (!file->unwritten && !file->holes && !file->truncate) {
clear_ctxt.files = old_files;
goto bail;
}
@@ -763,7 +798,23 @@ errcode_t clear_sparse_file_flag(ocfs2_filesys *fs, char *progname)
if (clear_ctxt.unwritten_only)
goto fill_unwritten;
+ /* Iterate all the files and truncate them if needed. */
+ while (file) {
+ if (file->truncate) {
+ ret = ocfs2_read_inode(fs, file->blkno, buf);
+ if (ret)
+ goto bail;
+
+ di = (struct ocfs2_dinode *)buf;
+ ret = truncate_file(fs, di);
+ if (ret)
+ goto bail;
+ }
+ file = file->next;
+ }
+
/* Iterate all the holes and fill them. */
+ file = clear_ctxt.files;
while (file) {
hole = file->holes;
while (hole) {
--
1.5.3.2.g4f337
More information about the Ocfs2-tools-devel
mailing list