Skip to content

Commit

Permalink
Fix off-by-one error when tracking dirty blocks.
Browse files Browse the repository at this point in the history
I could not find an easy way to test this, since it requires control over how the
vfstraceWrite() C function gets called (need to check if the right blocks are marked when
iAmt+iOfst is equal to a multiple of the block size, just above it, and just below it).
  • Loading branch information
Nikratio committed Jul 21, 2023
1 parent ea9d640 commit 203380f
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/s3ql/_sqlite3ext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,14 @@ static int vfstraceWrite(
if (!p->block_map) {
return rc;
}

size_t end_off = iOfst + iAmt;
size_t max_blockno = end_off / blocksize;
if (max_blockno * blocksize < end_off) {
max_blockno++;
}
for (size_t blockno = iOfst / blocksize;
blockno <= (iOfst + iAmt) / blocksize;
blockno < max_blockno;
blockno++) {
p->block_map->insert(blockno);
}
Expand Down
16 changes: 16 additions & 0 deletions tests/t1_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@


import logging
import math
import os
import tempfile
from argparse import Namespace
from typing import List
Expand Down Expand Up @@ -66,6 +68,20 @@ def test_track_dirty():
db.close()


def test_track_dirty_count():
sqlite3ext.reset()
with tempfile.NamedTemporaryFile() as tmpfh:
db = Connection(tmpfh.name, BLOCKSIZE)
db.execute("CREATE TABLE foo (id INT);")
db.execute("INSERT INTO FOO VALUES(42)")

db.checkpoint()
db_size = tmpfh.seek(0, os.SEEK_END)
assert db.dirty_blocks.get_count() == math.ceil(db_size / BLOCKSIZE)

db.close()


@pytest.fixture
def backend():
with tempfile.TemporaryDirectory(prefix="s3ql-backend-") as backend_dir:
Expand Down

0 comments on commit 203380f

Please sign in to comment.