[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