This commit is contained in:
Alex Young
2012-06-06 10:19:59 +01:00
5 changed files with 114 additions and 15 deletions

View File

@@ -1,5 +1,3 @@
require 'rake_utils/debian'
include RakeUtils::DSL
DEBUG = ENV.has_key?('DEBUG') &&
%w|yes y ok 1 true t|.include?(ENV['DEBUG'])
@@ -85,8 +83,10 @@ task :clean do
sh "rm -rf *~ build"
end
namespace :pkg do
deb do |t|
namespace :pkg do
task :deb do |t|
require 'rake_utils/debian'
t.code_files = ALL_SOURCES + ["Rakefile"]
t.pkg_name = "flexnbd"
t.generate_changelog!

View File

@@ -283,6 +283,21 @@ void client_reply_to_write( struct client_params* client, struct nbd_request req
request.len );
dirty(client->serve, request.from, request.len);
}
if (1) /* not sure whether this is necessary... */
{
/* multiple of 4K page size */
uint64_t from_rounded = request.from & (!0xfff);
uint64_t len_rounded = request.len + (request.from - from_rounded);
CLIENT_ERROR_ON_FAILURE(
msync(
client->mapped + from_rounded,
len_rounded,
MS_SYNC),
"msync failed %ld %ld", request.from, request.len
);
}
client_write_reply( client, &request, 0);
}

View File

@@ -16,19 +16,24 @@ class FlexNBD
@port = port
end
def serve(ip, port, file, *acl)
def serve(file, *acl)
File.unlink(ctrl) if File.exists?(ctrl)
cmd ="#{@bin} serve "\
"--addr #{ip} "\
"--port #{port} "\
"--file #{file} "\
"--sock #{ctrl} "\
"#{@debug} "\
"#{acl.join(' ')}"
@pid = fork do
cmd ="#{@bin} serve "\
"--addr #{ip} "\
"--port #{port} "\
"--file #{file} "\
"--sock #{ctrl} "\
"#{@debug} "\
"#{acl.join(' ')}"
exec(cmd)
end
sleep 0.1 until File.socket?(ctrl)
while !File.socket?(ctrl)
pid, status = Process.wait2(@pid, Process::WNOHANG)
raise "server did not start (#{cmd})" if pid
sleep 0.1
end
at_exit { kill }
end
def kill

80
tests/fuzz Normal file
View File

@@ -0,0 +1,80 @@
#!/usr/bin/ruby
require 'flexnbd'
binary = ARGV.shift
test_size = ARGV.shift.to_i
repetitions = ARGV.shift.to_i
repetitions = 50 if repetitions == 0
seed = ARGV.shift.to_i
max_length = test_size > 10000000 ? 10000000 : test_size
CHEAT_AND_ROUND_DOWN = false # set to 'false' to expose bugs
srand(seed)
if test_size < 32768 || repetitions < 1 || !File.executable?(binary)
STDERR.print "Syntax: #{$0} <flexnbd bin> <test size> [repetitions] [seed]\n"
STDERR.print "test_size must be >= 32768 and repeitions must be >= 1"
exit 1
end
testname_local = "#{$0}.test.#{$$}.local"
testname_serve = "#{$0}.test.#{$$}.serve"
[testname_local, testname_serve].each do |name|
File.open(name, "w+") { |fh| fh.seek(test_size-1, IO::SEEK_SET); fh.write("0") }
end
@local = File.open(testname_local, "r+")
@serve = FlexNBD.new(binary, "127.0.0.1", 41234)
@serve.serve(testname_serve)
repetitions.times do |n|
begin
if File.size(testname_local) != File.size(testname_serve)
STDERR.print "Before pass #{n}: File sizes are different: local=#{File.size(testname_local)} serve=#{File.size(testname_serve)}\n"
exit 1;
end
md5_local = `md5sum < #{testname_local}`.split(" ").first
md5_serve = `md5sum < #{testname_serve}`.split(" ").first
if md5_local != md5_serve
STDERR.print "Before pass #{n}: MD5 error: local=#{md5_local} serve=#{md5_serve}\n"
STDERR.print "**** Local contents:\n"
system("hexdump #{testname_local}")
STDERR.print "**** Serve contents:\n"
system("hexdump #{testname_serve}")
exit 1
end
length = rand(max_length)
length &= 0xfffff000 if CHEAT_AND_ROUND_DOWN
offset = rand(test_size - length)
offset &= 0xfffff000 if CHEAT_AND_ROUND_DOWN
content = (n%2 == 1) ? ("x" * length) : ("\0" * length)
@local.seek(offset, IO::SEEK_SET)
@local.write(content)
@serve.write(offset, content)
if @serve.read(offset, length) != content
STDERR.print "After pass #{n}: Didn't read back what we wrote!"
exit 1
end
rescue StandardError => ex
STDERR.print "During pass #{n}: Exception: #{ex}"
STDERR.print ex.backtrace.join("\n") + "\n"
exit 2
end
end
File.unlink(testname_local)
File.unlink(testname_serve)

View File

@@ -17,7 +17,6 @@ class NBDScenarios < Test::Unit::TestCase
end
def teardown
@nbd1.kill rescue nil
[@filename1, @filename2].each do |f|
File.unlink(f) if File.exists?(f)
end
@@ -73,7 +72,7 @@ class NBDScenarios < Test::Unit::TestCase
protected
def serve1(*acl)
@nbd1.serve(@ip, @port1, @filename1, *acl)
@nbd1.serve(@filename1, *acl)
end
def writefile1(data)