Merge
This commit is contained in:
8
Rakefile
8
Rakefile
@@ -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!
|
||||
|
15
src/serve.c
15
src/serve.c
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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
80
tests/fuzz
Normal 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)
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user