Skip to content
Browse files

Fixes for issue #6 and sparse files

The crash in issue #6 was caused by buf being incremented past the end
of its allocated space.  This only happened when a file was fragmented
enough to cause the op_read() loop to run more than twice, so it wasn't
caught by the existing tests.

This also adds support for sparse files.  A missing pblock is assumed to
be a "hole" in the file, rather than an error.
  • Loading branch information...
1 parent 0b12021 commit f653f7428b7dd355328d2376d9bb33738bc53429 @pwi pwi committed Nov 18, 2011
Showing with 99 additions and 10 deletions.
  1. +0 −1 extents.c
  2. +15 −9 op_read.c
  3. +45 −0 test/0013-file-integrity-fragmented.sh
  4. +39 −0 test/0014-file-integrity-sparse.sh
View
1 extents.c
@@ -95,6 +95,5 @@ uint64_t extent_get_pblock(struct ext4_inode_extent *inode_ext, uint32_t lblock,
}
}
- ASSERT(ret);
return ret;
}
View
24 op_read.c
@@ -71,7 +71,7 @@ int op_read(const char *path, char *buf, size_t size, off_t offset,
size_t ret = 0;
uint32_t extent_len;
- DEBUG("read(%s, buf, %jd, %zd, fi->fh=%d)", path, size, offset, fi->fh);
+ DEBUG("read(%s, buf, %zd, %zd, fi->fh=%d)", path, size, offset, fi->fh);
int inode_get_ret = inode_get_by_number(fi->fh, &inode);
if (inode_get_ret < 0) {
@@ -86,15 +86,21 @@ int op_read(const char *path, char *buf, size_t size, off_t offset,
for (int lblock = offset / BLOCK_SIZE; size > ret; lblock += extent_len) {
uint64_t pblock = inode_get_data_pblock(&inode, lblock, &extent_len);
- struct disk_ctx read_ctx;
-
- ASSERT(pblock);
-
- disk_ctx_create(&read_ctx, BLOCKS2BYTES(pblock), BLOCK_SIZE, extent_len);
- ret += disk_ctx_read(&read_ctx, size - ret, buf);
+ size_t bytes;
+
+ if (pblock) {
+ struct disk_ctx read_ctx;
+
+ disk_ctx_create(&read_ctx, BLOCKS2BYTES(pblock), BLOCK_SIZE, extent_len);
+ bytes = disk_ctx_read(&read_ctx, size - ret, buf);
+ } else {
+ bytes = BLOCK_SIZE;
+ memset(buf,0,bytes);
+ DEBUG("sparse file, skipping %d bytes",bytes);
+ }
+ ret += bytes;
+ buf += bytes;
DEBUG("Read %zd/%zd bytes from %d consecutive blocks", ret, size, extent_len);
-
- buf += ret;
}
/* We always read as many bytes as requested (after initial truncation) */
View
45 test/0013-file-integrity-fragmented.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+function t0013 {
+ FUSE_MD5=$(md5sum $MOUNTPOINT/`basename $TMP_FILE` | cut -d\ -f1)
+}
+
+function t0013-check {
+ [ "$FUSE_MD5" = "$FILE_MD5" ]
+}
+
+set -e
+source `dirname $0`/lib.sh
+
+# Make a random file, and store the md5
+TMP_FILE=`mktemp`
+dd if=/dev/urandom of=$TMP_FILE bs=1024 count=1024 &> /dev/null
+FILE_MD5=`md5sum $TMP_FILE | cut -d\ -f1`
+
+e4test_make_LOGFILE
+e4test_make_FS 8
+e4test_make_MOUNTPOINT
+
+# Copy the file in the FS
+e4test_mount
+
+dd if=/dev/urandom of=$MOUNTPOINT/filler bs=1024 count=64 &> /dev/null
+for x in `seq 1 106`; do
+ cp $MOUNTPOINT/filler $MOUNTPOINT/filler.$x
+done
+for x in `seq 2 2 32`; do
+ rm $MOUNTPOINT/filler.$x
+done
+
+cp $TMP_FILE $MOUNTPOINT
+
+e4test_umount
+
+# Check the md5 after mount using fuse
+e4test_fuse_mount
+e4test_run t0013
+e4test_fuse_umount
+
+rm $FS
+rm $TMP_FILE
+
+e4test_end t0013-check
View
39 test/0014-file-integrity-sparse.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+function t0014 {
+ FUSE_MD5=$(md5sum $MOUNTPOINT/`basename $TMP_FILE` | cut -d\ -f1)
+}
+
+function t0014-check {
+ [ "$FUSE_MD5" = "$FILE_MD5" ]
+}
+
+set -e
+source `dirname $0`/lib.sh
+
+# Make a sparse 1MB file w/4k allocated in the middle, and store the md5
+TMP_FILE=`mktemp`
+dd if=/dev/zero of=$TMP_FILE bs=1024 seek=1024 count=0 &> /dev/null
+dd if=/dev/urandom of=$TMP_FILE.rnd bs=1024 count=4 &> /dev/null
+dd if=$TMP_FILE.rnd of=$TMP_FILE bs=1024 seek=512 conv=notrunc &> /dev/null
+FILE_MD5=`md5sum $TMP_FILE | cut -d\ -f1`
+
+e4test_make_LOGFILE
+e4test_make_FS 2
+e4test_make_MOUNTPOINT
+
+# Recreate the same sparse file on the target fs
+e4test_mount
+NEWTMP=$MOUNTPOINT/`basename $TMP_FILE`
+dd if=/dev/zero of=$NEWTMP bs=1024 seek=1024 count=0 &> /dev/null
+dd if=$TMP_FILE.rnd of=$NEWTMP bs=1024 seek=512 conv=notrunc &> /dev/null
+e4test_umount
+
+# Check the md5 after mount using fuse
+e4test_fuse_mount
+e4test_run t0014
+e4test_fuse_umount
+
+rm $FS
+rm $TMP_FILE
+
+e4test_end t0014-check

0 comments on commit f653f74

Please sign in to comment.
Something went wrong with that request. Please try again.