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;
}