shithub: lwext4

Download patch

ref: b373cd2f4d2c1ad44ce55544927d9f824e9cd25e
parent: c6ecf74220bd1a8aaf259f198f9edd81f4b5bc29
author: ngkaho1234 <[email protected]>
date: Tue Oct 20 19:51:20 EDT 2015

TODO: More complicated truncate operation.

--- a/lwext4/ext4_extent_full.c
+++ b/lwext4/ext4_extent_full.c
@@ -1272,6 +1272,10 @@
 	return ret;
 }
 
+static int ext4_ext_split_extent_at(struct ext4_inode_ref *inode_ref,
+				    struct ext4_extent_path **ppath,
+				    ext4_lblk_t split, uint32_t split_flag);
+
 static void ext4_ext_remove_blocks(struct ext4_inode_ref *inode_ref,
 				   struct ext4_extent *ex, ext4_lblk_t from,
 				   ext4_lblk_t to)
@@ -1348,21 +1352,24 @@
 		int32_t new_len = 0;
 		int unwritten;
 		ext4_lblk_t start, new_start;
+		ext4_fsblk_t newblock;
 		new_start = start = to_le32(ex->first_block);
 		len = ext4_ext_get_actual_len(ex);
+		newblock = ext4_ext_pblock(ex);
 		if (start < from) {
 			len -= from - start;
 			new_len = from - start;
 			start = from;
 			start_ex++;
+		} else {
+			if (start + len - 1 > to) {
+				len -= start + len - 1 - to;
+				new_len = start + len - 1 - to;
+				new_start = to + 1;
+				newblock += to + 1 - start;
+				ex2 = ex;
+			}
 		}
-		/* TODO: More complicated truncate operation. */
-		/*if (start + len - 1 > to) {*/
-			/*len -= start + len - 1 - to;*/
-			/*new_len = start + len - 1 - to;*/
-			/*new_start = to + 1;*/
-			/*ex2 = ex;*/
-		/*}*/
 
 		ext4_ext_remove_blocks(inode_ref, ex, start, start + len - 1);
 		ex->first_block = to_le32(new_start);
@@ -1371,6 +1378,7 @@
 		else {
 			unwritten = ext4_ext_is_unwritten(ex);
 			ex->block_count = to_le16(new_len);
+			ext4_ext_store_pblock(ex, newblock);
 			if (unwritten)
 				ext4_ext_mark_unwritten(ex);
 		}
@@ -1435,6 +1443,34 @@
 
 	if (!in_range) {
 		ret = EOK;
+		goto out;
+	}
+
+	/* If we do remove_space inside the range of an extent */
+	if ((to_le32(path[depth].extent->first_block) < from) &&
+	    (to < to_le32(path[depth].extent->first_block) +
+			ext4_ext_get_actual_len(path[depth].extent) - 1)) {
+
+		struct ext4_extent *ex = path[depth].extent, newex;
+		int unwritten = ext4_ext_is_unwritten(ex);
+		ext4_lblk_t ee_block = to_le32(ex->first_block);
+		int32_t len = ext4_ext_get_actual_len(ex);
+		ext4_fsblk_t newblock =
+			to + 1 - ee_block + ext4_ext_pblock(ex);
+
+		ex->block_count = to_le16(from - ee_block);
+		if (unwritten)
+			ext4_ext_mark_unwritten(ex);
+
+		ext4_ext_dirty(inode_ref, path + depth);
+
+		newex.first_block = to_le32(to + 1);
+		newex.block_count = to_le16(ee_block + len - 1 - to);
+		ext4_ext_store_pblock(&newex, newblock);
+		if (unwritten)
+			ext4_ext_mark_unwritten(&newex);
+
+		ret = ext4_ext_insert_extent(inode_ref, &path, &newex, 0);
 		goto out;
 	}