shithub: lwext4

Download patch

ref: 01c6151eb539b10954a8459193482524f4365242
parent: c879d4700facd0ce86ad3781432f01bb0952e4bb
author: root <ngkaho1234@gmail.com>
date: Sun Sep 20 12:22:17 EDT 2015

ext4_ftruncate being separated into two parts: ext4_ftruncate_no_lock and ext4_ftruncate.

--- a/lwext4/ext4.c
+++ b/lwext4/ext4.c
@@ -1113,18 +1113,12 @@
 	return EOK;
 }
 
-int ext4_ftruncate(ext4_file *f, uint64_t size)
+static int ext4_ftruncate_no_lock(ext4_file *f, uint64_t size)
 {
 	struct ext4_inode_ref ref;
 	int r;
 
-	ext4_assert(f && f->mp);
 
-	if (f->flags & O_RDONLY)
-		return EPERM;
-
-	EXT4_MP_LOCK(f->mp);
-
 	r = ext4_fs_get_inode_ref(&f->mp->fs, f->inode, &ref);
 	if (r != EOK) {
 		EXT4_MP_UNLOCK(f->mp);
@@ -1138,6 +1132,23 @@
 		goto Finish;
 	}
 
+	if ((ext4_inode_get_mode(&f->mp->fs.sb, ref.inode) & EXT4_INODE_MODE_SOFTLINK)
+			== EXT4_INODE_MODE_SOFTLINK
+			&& f->fsize < sizeof(ref.inode->blocks)
+			&& !ext4_inode_get_blocks_count(&f->mp->fs.sb, ref.inode)) {
+		char *content = (char *)ref.inode->blocks;
+		memset(content + size, 0, sizeof(ref.inode->blocks) - size);
+		ext4_inode_set_size(ref.inode, size);
+		ref.dirty = true;
+
+		f->fsize = size;
+		if (f->fpos > size)
+			f->fpos = size;
+
+		r = EOK;
+		goto Finish;
+	}
+
 	/*Start write back cache mode.*/
 	r = ext4_block_cache_write_back(f->mp->fs.bdev, 1);
 	if (r != EOK)
@@ -1159,6 +1170,22 @@
 
 Finish:
 	ext4_fs_put_inode_ref(&ref);
+	return r;
+
+}
+
+int ext4_ftruncate(ext4_file *f, uint64_t size)
+{
+	int r;
+	ext4_assert(f && f->mp);
+
+	if (f->flags & O_RDONLY)
+		return EPERM;
+
+	EXT4_MP_LOCK(f->mp);
+
+	r = ext4_ftruncate_no_lock(f, size);
+
 	EXT4_MP_UNLOCK(f->mp);
 	return r;
 }