[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