[Ocfs2-tools-commits] taoma commits r1343 - in branches/sparse-files: extras libocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Mon Apr 23 00:22:56 PDT 2007


Author: taoma
Date: 2007-04-23 00:22:52 -0700 (Mon, 23 Apr 2007)
New Revision: 1343

Modified:
   branches/sparse-files/extras/sparse.c
   branches/sparse-files/libocfs2/fileio.c
   branches/sparse-files/libocfs2/truncate.c
Log:
Modify ocfs2_truncate to zero the area past i_size but still within an allocated cluster. 

Rewrite ocfs2_truncate and change ocfs2_dinode to ocfs2_cached_inode
since we need to use extent map to get blocks.

I also empty the allocated clusters before ocfs2_insert_extent since:
1) We may write only one block, but we have to allocate one cluster for it.
    So they must be emptied.
2) When we call ocfs2_extend_file to increase the size, we don't need to
    empty the content.
3) when i_size is corrupted and the user wants to fix the problem, fsck.ocfs2
    will make the i_size equal to the end of the the last allocated cluster. 
    So here the content is zeroed after the real size.

Other minor bug fixed in this commit:
1) Return an error if we have inserted the clusters during ocfs2_file_write,
    but still can't get the physical blocks by ocfs2_extent_map_get_blocks.
2) Empty the written content for sparse.c

Modified: branches/sparse-files/extras/sparse.c
===================================================================
--- branches/sparse-files/extras/sparse.c	2007-04-18 09:26:05 UTC (rev 1342)
+++ branches/sparse-files/extras/sparse.c	2007-04-23 07:22:52 UTC (rev 1343)
@@ -267,6 +267,7 @@
 		com_err(progname, ret, "while allocating %u blocks", block_num);
 		goto bail;
 	}
+	memset(buf, 0, buflen);
 
 	srand(write_byte);
 	create_data(buf, write_byte);

Modified: branches/sparse-files/libocfs2/fileio.c
===================================================================
--- branches/sparse-files/libocfs2/fileio.c	2007-04-18 09:26:05 UTC (rev 1342)
+++ branches/sparse-files/libocfs2/fileio.c	2007-04-23 07:22:52 UTC (rev 1343)
@@ -190,6 +190,42 @@
 	return ret;
 }
 
+/*
+ * Emtpy the clusters on the disk.
+ *
+ * The "start_blk" is aligned with the cluster border since it is got by
+ * ocfs2_new_clusters.
+ */
+static errcode_t empty_clusters(ocfs2_filesys *fs,
+				uint64_t start_blk,
+				uint32_t num_clusters)
+{
+	errcode_t ret;
+	char *buf = NULL;
+	int bpc = fs->fs_clustersize / fs->fs_blocksize;
+
+	ret = ocfs2_malloc_blocks(fs->fs_io, bpc, &buf);
+	if (ret)
+		goto bail;
+
+	memset(buf, 0, fs->fs_clustersize);
+
+	while (num_clusters) {
+		ret = io_write_block(fs->fs_io, start_blk, bpc, buf);
+		if (ret)
+			goto bail;
+
+		num_clusters--;
+		start_blk += bpc;
+	}
+
+bail:
+	if (buf)
+		ocfs2_free(&buf);
+
+	return ret;
+}
+
 errcode_t ocfs2_file_write(ocfs2_cached_inode *ci, void *buf, uint32_t count,
 			   uint64_t offset, uint32_t *wrote)
 {
@@ -243,9 +279,7 @@
 			if (ret)
 				return ret;
 
-	 		ret = ocfs2_insert_extent(fs, ci->ci_blkno,
-					ocfs2_blocks_to_clusters(fs,v_blkno),
-					p_blkno, n_clusters);
+			ret = empty_clusters(fs, p_blkno, n_clusters);
 			if (ret) {
 				/* XXX: We don't wan't to overwrite the error
 				 * from insert_extent().  But we probably need
@@ -254,6 +288,14 @@
 				return ret;
 			}
 
+	 		ret = ocfs2_insert_extent(fs, ci->ci_blkno,
+					ocfs2_blocks_to_clusters(fs,v_blkno),
+					p_blkno, n_clusters);
+			if (ret) {
+				ocfs2_free_clusters(fs, n_clusters, p_blkno);
+				return ret;
+			}
+
 			/* since the extent information has been changed, we
 			 * may need to reinitialize it. */
 			ocfs2_extent_map_free(ci);
@@ -262,6 +304,9 @@
 			ocfs2_extent_map_init(fs,ci);
 			ret = ocfs2_extent_map_get_blocks(ci, v_blkno, 1,
 						&p_blkno, &contig_blocks);
+			/* now we shouldn't find a hole. */
+			if (!p_blkno && !ret)
+				ret = OCFS2_ET_INTERNAL_FAILURE;
 			if (ret)
 				return ret;
 			if (contig_blocks > wanted_blocks)

Modified: branches/sparse-files/libocfs2/truncate.c
===================================================================
--- branches/sparse-files/libocfs2/truncate.c	2007-04-18 09:26:05 UTC (rev 1342)
+++ branches/sparse-files/libocfs2/truncate.c	2007-04-23 07:22:52 UTC (rev 1343)
@@ -133,70 +133,114 @@
 	return func_ret;
 }
 
+/*
+ * Zero the area past i_size but still within an allocated
+ * cluster. This avoids exposing nonzero data on subsequent file
+ * extends.
+ */
+static errcode_t ocfs2_zero_tail_for_truncate(ocfs2_cached_inode *ci,
+					      uint64_t new_size)
+{
+	errcode_t ret;
+	char *buf = NULL;
+	ocfs2_filesys *fs = ci->ci_fs;
+	uint64_t start_blk, p_blkno, contig_blocks, start_off;
+	int count, byte_counts, bpc = fs->fs_clustersize /fs->fs_blocksize;
+
+	if (new_size >= ci->ci_inode->i_size || new_size == 0)
+		return 0;
+
+	ret = ocfs2_extent_map_init(fs, ci);
+	if (ret)
+		goto out;
+
+	start_blk = new_size / fs->fs_blocksize;
+
+	ret = ocfs2_extent_map_get_blocks(ci, start_blk, 1,
+					  &p_blkno, &contig_blocks);
+	if (ret)
+		goto out;
+
+	/* Tail is a hole. */
+	if (!p_blkno)
+		goto out;
+
+	/* calculate the total blocks we need to empty. */
+	count = bpc - (p_blkno & (bpc - 1));
+	ret = ocfs2_malloc_blocks(fs->fs_io, count, &buf);
+	if (ret)
+		goto out;
+
+	ret = io_read_block(fs->fs_io, p_blkno, count, buf);
+	if (ret)
+		goto out;
+
+	/* empty the content after the new_size and within the same cluster. */
+	start_off = new_size % fs->fs_blocksize;
+	byte_counts = count * fs->fs_blocksize - start_off;
+	memset(buf + start_off, 0, byte_counts);
+
+	ret = io_write_block(fs->fs_io, p_blkno, count, buf);
+
+out:
+	ocfs2_extent_map_free(ci);
+	if (buf)
+		ocfs2_free(&buf);
+	return ret;
+}
+
 /* 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;
-	struct ocfs2_dinode *di;
 	uint32_t new_size_in_clusters;
 	uint64_t new_size_in_blocks;
+	ocfs2_cached_inode *ci = NULL;
 
-	ret = ocfs2_malloc_block(fs->fs_io, &buf);
+	ret = ocfs2_read_cached_inode(fs, ino, &ci);
 	if (ret)
-		return ret;
-
-	ret = ocfs2_read_inode(fs, ino, buf);
-	if (ret)
 		goto out;
-	di = (struct ocfs2_dinode *)buf;
 
-	if (di->i_size == new_i_size)
+	if (ci->ci_inode->i_size == new_i_size)
 		goto out;
 
 	new_size_in_blocks = ocfs2_blocks_in_bytes(fs, new_i_size);
 	new_size_in_clusters = ocfs2_clusters_in_blocks(fs, new_size_in_blocks);
 
-	if (di->i_size < new_i_size) {
+	if (ci->ci_inode->i_size < new_i_size)
 		ret = ocfs2_extend_file(fs, ino, new_i_size);
-		if (ret)
-			goto out;
-
-		/* the information of dinode has been changed, and we need to
-		 * read it again.
-		 */
-		ret = ocfs2_read_inode(fs, ino, buf);
-		if (ret)
-			goto out;
-	} else {
+	else {
 		struct truncate_ctxt ctxt = {
-			.new_i_clusters = di->i_clusters,
+			.new_i_clusters = ci->ci_inode->i_clusters,
 			.new_size_in_clusters = new_size_in_clusters,
 		};
 
-		ret = ocfs2_extent_iterate_inode(fs, di,
+		ret = ocfs2_extent_iterate_inode(fs, ci->ci_inode,
 						 OCFS2_EXTENT_FLAG_DEPTH_TRAVERSE,
 						 NULL, truncate_iterate,
 						 &ctxt);
 		if (ret)
 			goto out;
 
-		di->i_clusters = ctxt.new_i_clusters;
+		ci->ci_inode->i_clusters = ctxt.new_i_clusters;
 		/* now all the clusters and extent blocks are freed.
 		 * only when the file's content is empty, should the tree depth
 		 * change.
 		 */
 		if (ctxt.new_i_clusters == 0)
-			di->id2.i_list.l_tree_depth = 0;
-	}
+			ci->ci_inode->id2.i_list.l_tree_depth = 0;
 
-	di->i_size = new_i_size;
-	ret = ocfs2_write_inode(fs, ino, buf);
+		ret = ocfs2_zero_tail_for_truncate(ci, new_i_size);
+		if (ret)
+			goto out;
 
+		ci->ci_inode->i_size = new_i_size;
+		ret = ocfs2_write_cached_inode(fs, ci);
+	}
 out:
-	ocfs2_free(&buf);
-
+	if (ci)
+		ocfs2_free_cached_inode(fs, ci);
 	return ret;
 }
 




More information about the Ocfs2-tools-commits mailing list