[Ocfs2-tools-commits] zab commits r601 - in trunk/libocfs2: .
include
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Wed Jan 26 17:24:10 CST 2005
Author: zab
Date: 2005-01-26 17:24:08 -0600 (Wed, 26 Jan 2005)
New Revision: 601
Modified:
trunk/libocfs2/Makefile
trunk/libocfs2/extents.c
trunk/libocfs2/include/ocfs2.h
trunk/libocfs2/truncate.c
Log:
o A first pass at ocfs2_truncate() by altering extent records and returning
_CHANGED to ocfs2_extent_iterate(). This needs review.
Modified: trunk/libocfs2/Makefile
===================================================================
--- trunk/libocfs2/Makefile 2005-01-26 23:17:30 UTC (rev 600)
+++ trunk/libocfs2/Makefile 2005-01-26 23:24:08 UTC (rev 601)
@@ -67,7 +67,8 @@
expanddir.c \
newdir.c \
extend_file.c \
- namei.c
+ namei.c \
+ truncate.c
HFILES = \
include/jfs_user.h \
Modified: trunk/libocfs2/extents.c
===================================================================
--- trunk/libocfs2/extents.c 2005-01-26 23:17:30 UTC (rev 600)
+++ trunk/libocfs2/extents.c 2005-01-26 23:24:08 UTC (rev 601)
@@ -152,6 +152,8 @@
errcode_t errcode;
char **eb_bufs;
void *priv_data;
+ uint64_t last_eb_blkno;
+ uint64_t last_eb_cpos;
};
static int extent_iterate_eb(ocfs2_extent_rec *eb_rec,
@@ -159,37 +161,92 @@
int ref_recno,
struct extent_context *ctxt);
+static int update_leaf_rec(struct extent_context *ctxt,
+ ocfs2_extent_rec *before,
+ ocfs2_extent_rec *current)
+{
+ uint64_t start;
+ uint32_t len;
+ if (current->e_clusters == before->e_clusters)
+ return 0;
+
+ start = current->e_blkno +
+ ocfs2_clusters_to_blocks(ctxt->fs, current->e_clusters);
+ len = current->e_clusters - before->e_clusters;
+
+ ctxt->errcode = ocfs2_free_clusters(ctxt->fs, len, start);
+ if (ctxt->errcode)
+ return OCFS2_EXTENT_ERROR;
+
+ return 0;
+}
+
+static int update_eb_rec(struct extent_context *ctxt,
+ ocfs2_extent_rec *before,
+ ocfs2_extent_rec *current)
+{
+ if (current->e_clusters)
+ return 0;
+
+ ctxt->errcode = ocfs2_delete_extent_block(ctxt->fs, before->e_blkno);
+ if (ctxt->errcode)
+ return OCFS2_EXTENT_ERROR;
+
+ return 0;
+}
+
static int extent_iterate_el(ocfs2_extent_list *el, uint64_t ref_blkno,
struct extent_context *ctxt)
{
+ ocfs2_extent_rec before;
int iret = 0;
int i;
for (i = 0; i < el->l_next_free_rec; i++) {
+ /* XXX we could put some constraints on how the rec
+ * is allowed to change.. */
+ before = el->l_recs[i];
+
if (el->l_tree_depth) {
iret |= extent_iterate_eb(&el->l_recs[i],
el->l_tree_depth,
ref_blkno, i, ctxt);
+ if (iret & OCFS2_EXTENT_CHANGED)
+ iret |= update_eb_rec(ctxt, &before,
+ &el->l_recs[i]);
+
+ if (el->l_recs[i].e_clusters &&
+ (el->l_recs[i].e_cpos >= ctxt->last_eb_cpos))
+ ctxt->last_eb_blkno = el->l_recs[i].e_blkno;
+
} else {
iret |= (*ctxt->func)(ctxt->fs, &el->l_recs[i],
el->l_tree_depth,
ctxt->ccount, ref_blkno,
i, ctxt->priv_data);
+ if (iret & OCFS2_EXTENT_CHANGED)
+ iret |= update_leaf_rec(ctxt, &before,
+ &el->l_recs[i]);
ctxt->ccount += el->l_recs[i].e_clusters;
}
if (iret & (OCFS2_EXTENT_ABORT | OCFS2_EXTENT_ERROR))
- goto out_abort;
+ break;
}
-out_abort:
if (iret & OCFS2_EXTENT_CHANGED) {
- /* Something here ? */
+ for (i = 0; i < el->l_count; i++) {
+ if (el->l_recs[i].e_clusters)
+ continue;
+ el->l_next_free_rec = i;
+ break;
+ }
}
return iret;
}
+/* XXX this needs to be fixed to update the last extent block stuff */
static int extent_iterate_eb(ocfs2_extent_rec *eb_rec,
int ref_tree_depth, uint64_t ref_blkno,
int ref_recno, struct extent_context *ctxt)
@@ -206,12 +263,12 @@
ctxt->ccount, ref_blkno,
ref_recno, ctxt->priv_data);
if (!eb_rec->e_blkno || (iret & OCFS2_EXTENT_ABORT))
- return iret;
+ goto out;
if ((eb_rec->e_blkno < OCFS2_SUPER_BLOCK_BLKNO) ||
(eb_rec->e_blkno > ctxt->fs->fs_blocks)) {
ctxt->errcode = OCFS2_ET_BAD_BLKNO;
iret |= OCFS2_EXTENT_ERROR;
- return iret;
+ goto out;
}
ctxt->errcode =
@@ -220,7 +277,7 @@
ctxt->eb_bufs[tree_depth]);
if (ctxt->errcode) {
iret |= OCFS2_EXTENT_ERROR;
- return iret;
+ goto out;
}
eb = (ocfs2_extent_block *)ctxt->eb_bufs[tree_depth];
@@ -230,7 +287,7 @@
(eb->h_blkno != eb_rec->e_blkno)) {
ctxt->errcode = OCFS2_ET_CORRUPT_EXTENT_BLOCK;
iret |= OCFS2_EXTENT_ERROR;
- return iret;
+ goto out;
}
flags = extent_iterate_el(el, eb_rec->e_blkno, ctxt);
@@ -238,8 +295,16 @@
if (flags & (OCFS2_EXTENT_ABORT | OCFS2_EXTENT_ERROR))
iret |= flags & (OCFS2_EXTENT_ABORT | OCFS2_EXTENT_ERROR);
- if (changed & OCFS2_EXTENT_CHANGED) {
- /* Do something */
+ /* if the list was changed and we still have recs then we need
+ * to write the changes to disk */
+ if (changed & OCFS2_EXTENT_CHANGED && el->l_next_free_rec) {
+ ctxt->errcode = ocfs2_write_extent_block(ctxt->fs,
+ eb_rec->e_blkno,
+ ctxt->eb_bufs[tree_depth]);
+ if (ctxt->errcode) {
+ iret |= OCFS2_EXTENT_ERROR;
+ goto out;
+ }
}
if ((ctxt->flags & OCFS2_EXTENT_FLAG_DEPTH_TRAVERSE) &&
@@ -249,6 +314,7 @@
ref_tree_depth,
ctxt->ccount, ref_blkno,
ref_recno, ctxt->priv_data);
+out:
return iret;
}
@@ -312,6 +378,8 @@
ctxt.priv_data = priv_data;
ctxt.flags = flags;
ctxt.ccount = 0;
+ ctxt.last_eb_blkno = 0;
+ ctxt.last_eb_cpos = 0;
ret = 0;
iret |= extent_iterate_el(el, 0, &ctxt);
@@ -321,11 +389,16 @@
if (iret & OCFS2_EXTENT_ABORT)
goto out_abort;
-out_abort:
- if (iret & OCFS2_EXTENT_CHANGED) {
- /* Do something */
+ /* we can only trust ctxt.last_eb_blkno if we walked the whole tree */
+ if (inode->i_last_eb_blk != ctxt.last_eb_blkno) {
+ inode->i_last_eb_blk = ctxt.last_eb_blkno;
+ iret |= OCFS2_EXTENT_CHANGED;
}
+out_abort:
+ if (iret & OCFS2_EXTENT_CHANGED)
+ ret = ocfs2_write_inode(fs, inode->i_blkno, (char *)inode);
+
out_eb_bufs:
if (ctxt.eb_bufs) {
if (!block_buf && ctxt.eb_bufs[0])
Modified: trunk/libocfs2/include/ocfs2.h
===================================================================
--- trunk/libocfs2/include/ocfs2.h 2005-01-26 23:17:30 UTC (rev 600)
+++ trunk/libocfs2/include/ocfs2.h 2005-01-26 23:24:08 UTC (rev 601)
@@ -509,6 +509,7 @@
errcode_t ocfs2_delete_extent_block(ocfs2_filesys *fs, uint64_t blkno);
errcode_t ocfs2_extend_allocation(ocfs2_filesys *fs, uint64_t ino,
uint32_t new_clusters);
+errcode_t ocfs2_truncate(ocfs2_filesys *fs, uint64_t ino, uint64_t new_i_size);
errcode_t ocfs2_new_clusters(ocfs2_filesys *fs,
uint32_t requested,
uint64_t *start_blkno);
Modified: trunk/libocfs2/truncate.c
===================================================================
--- trunk/libocfs2/truncate.c 2005-01-26 23:17:30 UTC (rev 600)
+++ trunk/libocfs2/truncate.c 2005-01-26 23:24:08 UTC (rev 601)
@@ -32,27 +32,80 @@
#include "ocfs2.h"
-
-struct truncate_context {
- ocfs2_dinode *di;
- uint32_t clusters;
-};
-
-
+/*
+ * We let ocfs2_extent_iterate() update the tree for us by
+ * altering the records beyond the new size and returning
+ * _CHANGED. It will delete unused extent blocks and file
+ * data for us. This only works with DEPTH_TRAVERSE..
+ */
static int truncate_iterate(ocfs2_filesys *fs, ocfs2_extent_rec *rec,
int tree_depth, uint32_t ccount,
uint64_t ref_blkno, int ref_recno,
void *priv_data)
{
- int iret;
- uint32_t cluster;
- struct truncate_context *ctxt = priv_data;
+ uint64_t new_i_clusters = *(uint64_t *)priv_data;
- if ((rec->e_cpos + rec->e_clusters) <= ctxt->clusters)
+ if ((rec->e_cpos + rec->e_clusters) <= new_i_clusters)
return 0;
- if (!tree_depth) {
+ if (rec->e_cpos >= new_i_clusters) {
+ /* the rec is entirely outside the new size, free it */
+ rec->e_blkno = 0;
+ rec->e_clusters = 0;
+ rec->e_cpos = 0;
+ } else {
+ /* we're truncating into the middle of the rec */
+ rec->e_clusters = new_i_clusters - rec->e_cpos;
}
- return iret;
+ return OCFS2_EXTENT_CHANGED;
}
+
+/* XXX care about zeroing new clusters and final partially truncated
+ * clusters */
+errcode_t ocfs2_truncate(ocfs2_filesys *fs, uint64_t ino, uint64_t new_i_size)
+{
+ errcode_t ret;
+ char *buf;
+ ocfs2_dinode *di;
+ uint32_t new_i_clusters;
+ uint64_t new_i_blocks;
+
+ ret = ocfs2_malloc_block(fs->fs_io, &buf);
+ if (ret)
+ return ret;
+
+ ret = ocfs2_read_inode(fs, ino, buf);
+ if (ret)
+ goto out;
+ di = (ocfs2_dinode *)buf;
+
+ if (di->i_size == new_i_size)
+ goto out;
+
+ new_i_blocks = ocfs2_blocks_in_bytes(fs, new_i_size);
+ new_i_clusters = ocfs2_clusters_in_blocks(fs, new_i_blocks);
+
+ if (di->i_clusters < new_i_clusters) {
+ ret = ocfs2_extend_allocation(fs, ino,
+ new_i_clusters - di->i_clusters);
+ if (ret)
+ goto out;
+ } else {
+ ret = ocfs2_extent_iterate_inode(fs, di,
+ OCFS2_EXTENT_FLAG_DEPTH_TRAVERSE,
+ NULL, truncate_iterate,
+ &new_i_clusters);
+ if (ret)
+ goto out;
+ }
+
+ di->i_clusters = new_i_clusters;
+ di->i_size = new_i_size;
+ ret = ocfs2_write_inode(fs, ino, buf);
+
+out:
+ ocfs2_free(&buf);
+
+ return ret;
+}
More information about the Ocfs2-tools-commits
mailing list