summaryrefslogtreecommitdiff
path: root/ext2fs
diff options
context:
space:
mode:
Diffstat (limited to 'ext2fs')
-rw-r--r--ext2fs/ext2fs.h4
-rw-r--r--ext2fs/inode.c19
-rw-r--r--ext2fs/truncate.c15
3 files changed, 37 insertions, 1 deletions
diff --git a/ext2fs/ext2fs.h b/ext2fs/ext2fs.h
index 2b49d2ea..ba0eaecd 100644
--- a/ext2fs/ext2fs.h
+++ b/ext2fs/ext2fs.h
@@ -505,7 +505,9 @@ record_global_poke (void *ptr)
block_t block = boffs_block (bptr_offs (ptr));
void *block_ptr = bptr (block);
ext2_debug ("(%p = %p)", ptr, block_ptr);
+#ifdef EXT2FS_DEBUG
assert_backtrace (disk_cache_block_is_ref (block));
+#endif
global_block_modified (block);
pokel_add (&global_pokel, block_ptr, block_size);
}
@@ -531,7 +533,9 @@ record_indir_poke (struct node *node, void *ptr)
block_t block = boffs_block (bptr_offs (ptr));
void *block_ptr = bptr (block);
ext2_debug ("(%llu, %p)", node->cache_id, ptr);
+#ifdef EXT2FS_DEBUG
assert_backtrace (disk_cache_block_is_ref (block));
+#endif
global_block_modified (block);
pokel_add (&diskfs_node_disknode (node)->indir_pokel, block_ptr, block_size);
}
diff --git a/ext2fs/inode.c b/ext2fs/inode.c
index d73d0bca..3bfbdfdb 100644
--- a/ext2fs/inode.c
+++ b/ext2fs/inode.c
@@ -632,6 +632,18 @@ diskfs_set_translator (struct node *np, const char *name, unsigned namelen,
if (namelen && !blkno)
{
+ mode_t newmode = 0;
+
+ if (S_ISLNK (np->dn_stat.st_mode))
+ {
+ /* Avoid storing both a symlink and a translator,
+ * e2fsck does not like it. */
+ newmode = (np->dn_stat.st_mode & ~S_IFMT) | S_IFREG;
+ err = diskfs_validate_mode_change (np, newmode);
+ if (err)
+ return err;
+ }
+
/* Allocate block for translator */
blkno =
ext2_new_block ((diskfs_node_disknode (np)->info.i_block_group
@@ -645,6 +657,13 @@ diskfs_set_translator (struct node *np, const char *name, unsigned namelen,
return ENOSPC;
}
+ if (newmode)
+ {
+ /* Clear previous data */
+ diskfs_truncate (np, 0);
+ np->dn_stat.st_mode = newmode;
+ }
+
di->i_translator = blkno;
diskfs_node_disknode (np)->info_i_translator = blkno;
record_global_poke (di);
diff --git a/ext2fs/truncate.c b/ext2fs/truncate.c
index 265f7f2c..44aab3c7 100644
--- a/ext2fs/truncate.c
+++ b/ext2fs/truncate.c
@@ -240,7 +240,7 @@ force_delayed_copies (struct node *node, off_t length)
mach_port_t obj;
pager_change_attributes (pager, MAY_CACHE, MEMORY_OBJECT_COPY_NONE, 1);
- obj = diskfs_get_filemap (node, VM_PROT_READ);
+ obj = diskfs_get_filemap (node, VM_PROT_READ | VM_PROT_WRITE);
if (obj != MACH_PORT_NULL)
{
/* XXX should cope with errors from diskfs_get_filemap */
@@ -296,6 +296,19 @@ diskfs_truncate (struct node *node, off_t length)
is true for fast symlinks, and also apparently for some device nodes
in linux. */
{
+ off_t froblen = node->dn_stat.st_size;
+ off_t frobmax = sizeof(diskfs_node_disknode (node)->info.i_data);
+
+ if (froblen > frobmax)
+ {
+ ext2_warning ("inline data was %lld, more than max %lld",
+ (long long) froblen, (long long) frobmax);
+ froblen = frobmax;
+ }
+ froblen -= length;
+ memset (((char *) (diskfs_node_disknode (node)->info.i_data)) + length,
+ 0, froblen);
+
node->dn_stat.st_size = length;
node->dn_set_mtime = 1;
node->dn_set_ctime = 1;