[Ocfs2-tools-commits] taoma commits r1315 - trunk/libocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Wed Mar 7 21:46:21 PST 2007
Author: taoma
Date: 2007-03-07 21:46:18 -0800 (Wed, 07 Mar 2007)
New Revision: 1315
Modified:
trunk/libocfs2/extents.c
trunk/libocfs2/truncate.c
Log:
Modify ocfs2_truncate in libocfs2 to truncate a file.
ocfs2_truncate is designed to modify a file to a desirable size, but actually this function
can't work except setting the i_size of ocfs2_dinode.
For more details, please see
http://oss.oracle.com/bugzilla/show_bug.cgi?id=856
Signed-off-by: jlbec
Modified: trunk/libocfs2/extents.c
===================================================================
--- trunk/libocfs2/extents.c 2007-03-02 22:13:04 UTC (rev 1314)
+++ trunk/libocfs2/extents.c 2007-03-08 05:46:18 UTC (rev 1315)
@@ -217,20 +217,6 @@
struct ocfs2_extent_rec *before,
struct 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;
}
@@ -238,14 +224,6 @@
struct ocfs2_extent_rec *before,
struct 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;
}
Modified: trunk/libocfs2/truncate.c
===================================================================
--- trunk/libocfs2/truncate.c 2007-03-02 22:13:04 UTC (rev 1314)
+++ trunk/libocfs2/truncate.c 2007-03-08 05:46:18 UTC (rev 1315)
@@ -33,10 +33,7 @@
#include "ocfs2.h"
/*
- * 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..
+ * Delete and free clusters if needed. This only works with DEPTH_TRAVERSE.
*/
static int truncate_iterate(ocfs2_filesys *fs,
struct ocfs2_extent_rec *rec,
@@ -44,22 +41,50 @@
uint64_t ref_blkno, int ref_recno,
void *priv_data)
{
- uint64_t new_i_clusters = *(uint64_t *)priv_data;
+ uint32_t len, new_i_clusters = *(uint32_t *)priv_data;
+ uint64_t start = 0;
+ errcode_t ret;
if ((rec->e_cpos + rec->e_clusters) <= new_i_clusters)
return 0;
if (rec->e_cpos >= new_i_clusters) {
/* the rec is entirely outside the new size, free it */
+ if (!tree_depth) {
+ start = rec->e_blkno;
+ len = rec->e_clusters;
+ } else {
+ /* here we meet with a full empty extent block, delete
+ * it. The extent list it contains should already be
+ * iterated and all the clusters have been freed.
+ */
+ ret = ocfs2_delete_extent_block(fs, rec->e_blkno);
+ if (ret)
+ goto bail;
+ }
+
rec->e_blkno = 0;
rec->e_clusters = 0;
rec->e_cpos = 0;
} else {
/* we're truncating into the middle of the rec */
+ len = rec->e_cpos + rec->e_clusters;
+ len -= new_i_clusters;
rec->e_clusters = new_i_clusters - rec->e_cpos;
+ if (!tree_depth)
+ start = rec->e_blkno +
+ ocfs2_clusters_to_blocks(fs, rec->e_clusters);
}
+ if (start) {
+ ret = ocfs2_free_clusters(fs, len, start);
+ if (ret)
+ goto bail;
+ }
+
return OCFS2_EXTENT_CHANGED;
+bail:
+ return OCFS2_EXTENT_ERROR;
}
/* XXX care about zeroing new clusters and final partially truncated
@@ -92,6 +117,13 @@
new_i_clusters - di->i_clusters);
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 {
ret = ocfs2_extent_iterate_inode(fs, di,
OCFS2_EXTENT_FLAG_DEPTH_TRAVERSE,
@@ -99,6 +131,14 @@
&new_i_clusters);
if (ret)
goto out;
+
+ /* now all the clusters and extent blocks are freed.
+ * only when the file's content is empty, should the tree depth
+ * change.
+ */
+ if (new_i_clusters == 0)
+ di->id2.i_list.l_tree_depth = 0;
+
}
di->i_clusters = new_i_clusters;
@@ -110,3 +150,92 @@
return ret;
}
+
+#ifdef DEBUG_EXE
+#include <stdlib.h>
+#include <getopt.h>
+#include <inttypes.h>
+
+static uint64_t read_number(const char *num)
+{
+ uint64_t val;
+ char *ptr;
+
+ val = strtoull(num, &ptr, 0);
+ if (!ptr || *ptr)
+ return 0;
+
+ return val;
+}
+
+static void print_usage(void)
+{
+ fprintf(stderr,
+ "Usage: debug_truncate -i <ino_blkno> -s <new_size> device\n");
+}
+
+extern int opterr, optind;
+extern char *optarg;
+
+int main(int argc, char *argv[])
+{
+ errcode_t ret;
+ int c;
+ uint64_t blkno = 0, new_size = 0;
+ ocfs2_filesys *fs;
+ char *device;
+
+ initialize_ocfs_error_table();
+
+ while ((c = getopt(argc, argv, "i:s:")) != EOF) {
+ switch (c) {
+ case 'i':
+ blkno = read_number(optarg);
+ if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) {
+ fprintf(stderr,
+ "Invalid inode block: %s\n",
+ optarg);
+ print_usage();
+ return 1;
+ }
+ break;
+
+ case 's':
+ new_size = read_number(optarg);
+ break;
+
+ default:
+ print_usage();
+ return 1;
+ break;
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "Missing device name\n");
+ print_usage();
+ return 1;
+ }
+ device = argv[optind];
+
+ if (!blkno || !new_size) {
+ print_usage();
+ return 1;
+ }
+
+ ret = ocfs2_open(device, OCFS2_FLAG_RW, 0, 0, &fs);
+ if (ret) {
+ com_err(argv[0], ret,
+ "while opening file \"%s\"", device);
+ return ret;
+ }
+
+ ret = ocfs2_truncate(fs, blkno, new_size);
+ if (ret)
+ com_err(argv[0], ret, "while truncating inode %"PRIu64, blkno);
+
+ ocfs2_close(fs);
+
+ return ret;
+}
+#endif /* DEBUG_EXE */
More information about the Ocfs2-tools-commits
mailing list