[Ocfs2-tools-devel] [patch 07/11] Modify file read and write.take 2

tao.ma at oracle.com tao.ma at oracle.com
Wed Aug 22 17:07:55 PDT 2007


Change ocfs2_file_read and ocfs2_file_write accordingly.
===================================================================
--- quilt.ocfs2-tools.orig/libocfs2/fileio.c	2007-08-21 06:38:06.000000000 -0400
+++ quilt.ocfs2-tools/libocfs2/fileio.c	2007-08-22 05:51:42.000000000 -0400
@@ -128,7 +128,7 @@ errcode_t ocfs2_file_read(ocfs2_cached_i
 	errcode_t	ret = 0;
 	char		*ptr = (char *) buf;
 	uint32_t	wanted_blocks;
-	uint32_t	contig_blocks;
+	uint64_t	contig_blocks;
 	uint64_t	v_blkno;
 	uint64_t	p_blkno;
 	uint32_t	tmp;
@@ -162,9 +162,15 @@ errcode_t ocfs2_file_read(ocfs2_cached_i
 		if (contig_blocks > wanted_blocks)
 			contig_blocks = wanted_blocks;
 
-		ret = io_read_block(fs->fs_io, p_blkno, contig_blocks, ptr);
-		if (ret)
-			return ret;
+		if (!p_blkno) {
+			/* we meet with a hole, just empty the content.*/
+			memset(ptr, 0, contig_blocks * fs->fs_blocksize);
+		} else {
+			ret = io_read_block(fs->fs_io, p_blkno,
+					    contig_blocks, ptr);
+			if (ret)
+				return ret;
+		}
 
 		*got += (contig_blocks <<
 			 OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits);
@@ -184,6 +190,38 @@ errcode_t ocfs2_file_read(ocfs2_cached_i
 	return ret;
 }
 
+/*
+ * Emtpy the blocks on the disk.
+ */
+static errcode_t empty_blocks(ocfs2_filesys *fs,
+			      uint64_t start_blk,
+			      uint64_t num_blocks)
+{
+	errcode_t ret;
+	char *buf = NULL;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &buf);
+	if (ret)
+		goto bail;
+
+	memset(buf, 0, fs->fs_blocksize);
+
+	while (num_blocks) {
+		ret = io_write_block(fs->fs_io, start_blk, 1, buf);
+		if (ret)
+			goto bail;
+
+		num_blocks--;
+		start_blk++;
+	}
+
+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)
 {
@@ -191,12 +229,15 @@ errcode_t ocfs2_file_write(ocfs2_cached_
 	errcode_t	ret = 0;
 	char		*ptr = (char *) buf;
 	uint32_t	wanted_blocks;
-	uint32_t	contig_blocks;
+	uint64_t	contig_blocks;
 	uint64_t	v_blkno;
 	uint64_t	p_blkno;
 	uint32_t	tmp;
 	uint64_t	num_blocks;
 	int		bs_bits = OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
+	uint64_t	ino = ci->ci_blkno;
+	uint32_t	n_clusters, cluster_begin, cluster_end;
+	uint64_t	empty_start, bpc = fs->fs_clustersize/fs->fs_blocksize;
 
 	/* o_direct requires aligned io */
 	tmp = fs->fs_blocksize - 1;
@@ -225,6 +266,68 @@ errcode_t ocfs2_file_write(ocfs2_cached_
 		if (contig_blocks > wanted_blocks)
 			contig_blocks = wanted_blocks;
 
+	 	if (!p_blkno) {
+			cluster_begin = ocfs2_blocks_to_clusters(fs, v_blkno);
+			cluster_end = ocfs2_blocks_to_clusters(fs,
+						v_blkno + contig_blocks -1);
+			n_clusters = cluster_end - cluster_begin + 1;
+			ret = ocfs2_new_clusters(fs, 1, n_clusters, &p_blkno,
+						 &n_clusters);
+			if (ret)
+				return ret;
+
+	 		ret = ocfs2_insert_extent(fs, ci->ci_blkno,
+					ocfs2_blocks_to_clusters(fs,v_blkno),
+					p_blkno, n_clusters);
+			if (ret) {
+				/*
+				 * XXX: We don't wan't to overwrite the error
+				 * from insert_extent().  But we probably need
+				 * to BE LOUDLY UPSET.
+				 */
+				ocfs2_free_clusters(fs, n_clusters, p_blkno);
+				return ret;
+			}
+
+			/*
+			 * since the inode information has been changed, we
+			 * may need to reinitialize it.
+			 */
+			ocfs2_free_cached_inode(fs, ci);
+			ret = ocfs2_read_cached_inode(fs,ino, &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 (p_blkno & (bpc - 1)) {
+				/*
+				 * The user don't write the first blocks,
+				 * so we have to clear them.
+				 */
+				empty_start = p_blkno & (~(bpc - 1));
+				ret = empty_blocks(fs, empty_start,
+						   p_blkno - empty_start);
+				if (ret)
+					return ret;
+			}
+			if (contig_blocks > wanted_blocks) {
+				/*
+				 * we don't need to write that many blocks,
+				 * so empty the blocks at the bottom.
+				 */
+				empty_start = p_blkno + wanted_blocks;
+				ret = empty_blocks(fs, empty_start,
+						contig_blocks - wanted_blocks);
+				if (ret)
+					return ret;
+				contig_blocks = wanted_blocks;
+			}
+		}
+
 		ret = io_write_block(fs->fs_io, p_blkno, contig_blocks, ptr);
 		if (ret)
 			return ret;
@@ -432,4 +535,3 @@ out:
 	return 0;
 }
 #endif  /* DEBUG_EXE */
-

-- 



More information about the Ocfs2-tools-devel mailing list